From fd21661836f9da5262c4d784e14ab6944b796878 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Tue, 26 Nov 2024 11:27:44 +0100 Subject: [PATCH 001/426] fixup branch sorting for automatic pr (#4102) (#4103) --- hack/build/ci/update-e2e-ondemand-pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/build/ci/update-e2e-ondemand-pipeline.py b/hack/build/ci/update-e2e-ondemand-pipeline.py index 6157a800f0..f25d6d330b 100644 --- a/hack/build/ci/update-e2e-ondemand-pipeline.py +++ b/hack/build/ci/update-e2e-ondemand-pipeline.py @@ -9,7 +9,7 @@ version = "" # read versions to list with open(version_file, "r") as f: - version = f.readline().strip().replace("origin/", "") + version = [v.strip().replace("origin/", "") for v in f.readlines()][-1] yaml = YAML() yaml.width = 4096 From 74abeb5b086d8cb21d94fabaa121e52ad25cb004 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:19:12 +0000 Subject: [PATCH 002/426] chore(deps): update docker/build-push-action action to v6.10.0 (main) (#4105) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 76ae31bd49..10ec2770a7 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -31,7 +31,7 @@ runs: run: | hack/build/ci/third-party-licenses.sh - name: Build target - uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0 + uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 with: builder: ${{ steps.buildx.outputs.name }} build-args: | From 56048b8cc4949b20d1c83e363670bef085f3ec2c Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Tue, 26 Nov 2024 12:34:25 +0100 Subject: [PATCH 003/426] Always add ActiveGate ports no matter the capability (#4069) Co-authored-by: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> --- pkg/api/v1beta3/dynakube/activegate/props.go | 12 ------- pkg/api/v1beta3/dynakube/activegate/spec.go | 3 +- pkg/api/v1beta3/dynakube/activegate_props.go | 1 - .../internal/capability/reconciler.go | 18 ++++------ .../internal/capability/reconciler_test.go | 8 +++-- .../activegate/internal/capability/service.go | 30 +++++++---------- .../internal/capability/service_test.go | 2 +- .../builder/modifiers/config_test.go | 1 - .../builder/modifiers/serviceport.go | 8 ++--- .../builder/modifiers/serviceport_test.go | 31 ----------------- .../dynakube/activegate/reconciler.go | 4 --- .../dynakube/activegate/reconciler_test.go | 33 +++++-------------- 12 files changed, 37 insertions(+), 114 deletions(-) diff --git a/pkg/api/v1beta3/dynakube/activegate/props.go b/pkg/api/v1beta3/dynakube/activegate/props.go index a347446494..d0a47ab444 100644 --- a/pkg/api/v1beta3/dynakube/activegate/props.go +++ b/pkg/api/v1beta3/dynakube/activegate/props.go @@ -27,10 +27,6 @@ func (ag *Spec) SetExtensionsDependency(isEnabled bool) { ag.enabledDependencies.extensions = isEnabled } -func (ag *Spec) SetKSPMDependency(isEnabled bool) { - ag.enabledDependencies.kspm = isEnabled -} - func (ag *Spec) apiUrlHost() string { parsedUrl, err := url.Parse(ag.apiUrl) if err != nil { @@ -92,14 +88,6 @@ func (ag *Spec) IsMetricsIngestEnabled() bool { return ag.IsMode(MetricsIngestCapability.DisplayName) } -func (ag *Spec) NeedsService() bool { - return ag.IsRoutingEnabled() || - ag.IsApiEnabled() || - ag.IsMetricsIngestEnabled() || - ag.enabledDependencies.extensions || - ag.enabledDependencies.kspm -} - func (ag *Spec) HasCaCert() bool { return ag.IsEnabled() && ag.TlsSecretName != "" } diff --git a/pkg/api/v1beta3/dynakube/activegate/spec.go b/pkg/api/v1beta3/dynakube/activegate/spec.go index 56b3f951de..e58f866682 100644 --- a/pkg/api/v1beta3/dynakube/activegate/spec.go +++ b/pkg/api/v1beta3/dynakube/activegate/spec.go @@ -60,11 +60,10 @@ type ActiveGate struct { // dependencies is a collection of possible other feature/components that need an ActiveGate, but is not directly configured in the ActiveGate section. type dependencies struct { extensions bool - kspm bool } func (d dependencies) Any() bool { - return d.extensions + return d.extensions // kspm is a dependency too, but blocked by validation webhook to not run standalone } // +kubebuilder:object:generate=true diff --git a/pkg/api/v1beta3/dynakube/activegate_props.go b/pkg/api/v1beta3/dynakube/activegate_props.go index 91347a70bd..d7573c5f1d 100644 --- a/pkg/api/v1beta3/dynakube/activegate_props.go +++ b/pkg/api/v1beta3/dynakube/activegate_props.go @@ -8,7 +8,6 @@ func (dk *DynaKube) ActiveGate() *activegate.ActiveGate { dk.Spec.ActiveGate.SetApiUrl(dk.ApiUrl()) dk.Spec.ActiveGate.SetName(dk.Name) dk.Spec.ActiveGate.SetExtensionsDependency(dk.IsExtensionsEnabled()) - dk.Spec.ActiveGate.SetKSPMDependency(dk.KSPM().IsEnabled()) return &activegate.ActiveGate{ Spec: &dk.Spec.ActiveGate, diff --git a/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go b/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go index f79e5c4eb8..67e6e5a191 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go @@ -42,18 +42,14 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { return errors.WithStack(err) } - if r.dk.ActiveGate().NeedsService() { - err = r.createOrUpdateService(ctx) - if err != nil { - return err - } + err = r.createOrUpdateService(ctx) + if err != nil { + return err + } - err = r.setAGServiceIPs(ctx) - if err != nil { - return err - } - } else { - r.dk.Status.ActiveGate.ServiceIPs = []string{} + err = r.setAGServiceIPs(ctx) + if err != nil { + return err } err = r.statefulsetReconciler.Reconcile(ctx) diff --git a/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go index ae32b9f6a4..121d2400f5 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go @@ -161,7 +161,7 @@ func TestReconcile(t *testing.T) { assert.NotNil(t, service) require.NoError(t, err) }) - t.Run(`service does not get created when missing capabilities`, func(t *testing.T) { + t.Run(`service is created even though capability does not need it`, func(t *testing.T) { clt := createClient() dk := buildDynakube(capabilitiesWithoutService) mockStatefulSetReconciler := getMockReconciler(t, nil) @@ -179,8 +179,10 @@ func TestReconcile(t *testing.T) { service := corev1.Service{} err = r.client.Get(context.Background(), client.ObjectKey{Name: r.dk.Name + "-" + r.capability.ShortName(), Namespace: r.dk.Namespace}, &service) - assert.Empty(t, service) - require.Error(t, err) + require.NoError(t, err) + + assert.NotEmpty(t, service) + assert.Len(t, service.Spec.Ports, 2) }) } diff --git a/pkg/controllers/dynakube/activegate/internal/capability/service.go b/pkg/controllers/dynakube/activegate/internal/capability/service.go index 51647ff441..a02b07eb8d 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/service.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/service.go @@ -13,24 +13,18 @@ import ( func CreateService(dk *dynakube.DynaKube, feature string) *corev1.Service { var ports []corev1.ServicePort - if dk.ActiveGate().NeedsService() { - ports = append(ports, - corev1.ServicePort{ - Name: consts.HttpsServicePortName, - Protocol: corev1.ProtocolTCP, - Port: consts.HttpsServicePort, - TargetPort: intstr.FromString(consts.HttpsServicePortName), - }, - ) - if dk.ActiveGate().IsMetricsIngestEnabled() { - ports = append(ports, corev1.ServicePort{ - Name: consts.HttpServicePortName, - Protocol: corev1.ProtocolTCP, - Port: consts.HttpServicePort, - TargetPort: intstr.FromString(consts.HttpServicePortName), - }) - } - } + ports = append(ports, + corev1.ServicePort{ + Name: consts.HttpsServicePortName, + Protocol: corev1.ProtocolTCP, + Port: consts.HttpsServicePort, + TargetPort: intstr.FromString(consts.HttpsServicePortName), + }, corev1.ServicePort{ + Name: consts.HttpServicePortName, + Protocol: corev1.ProtocolTCP, + Port: consts.HttpServicePort, + TargetPort: intstr.FromString(consts.HttpServicePortName), + }) coreLabels := labels.NewCoreLabels(dk.Name, labels.ActiveGateComponentLabel) diff --git a/pkg/controllers/dynakube/activegate/internal/capability/service_test.go b/pkg/controllers/dynakube/activegate/internal/capability/service_test.go index 8ac773305a..ce00f66325 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/service_test.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/service_test.go @@ -81,7 +81,7 @@ func TestCreateService(t *testing.T) { ports := service.Spec.Ports assert.Contains(t, ports, agHttpsPort) - assert.NotContains(t, ports, agHttpPort) + assert.Contains(t, ports, agHttpPort) }) t.Run("check AG service if metrics-ingest enabled", func(t *testing.T) { dk := createTestDynaKube() diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config_test.go index d52f1c11da..8d95367158 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config_test.go @@ -78,7 +78,6 @@ func enableAllModifiers(dk *dynakube.DynaKube, capability capability.Capability) setCustomPropertyUsage(capability, true) setProxyUsage(dk, true) setKubernetesMonitoringUsage(dk, true) - setServicePortUsage(dk, true) } func TestNoConflict(t *testing.T) { diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport.go index 592b1f4191..acad9f5465 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport.go @@ -30,7 +30,7 @@ type ServicePortModifier struct { } func (mod ServicePortModifier) Enabled() bool { - return mod.dk.ActiveGate().NeedsService() + return true } func (mod ServicePortModifier) Modify(sts *appsv1.StatefulSet) error { @@ -48,12 +48,10 @@ func (mod ServicePortModifier) getPorts() []corev1.ContainerPort { Name: consts.HttpsServicePortName, ContainerPort: consts.HttpsContainerPort, }, - } - if mod.dk.ActiveGate().IsMetricsIngestEnabled() { - ports = append(ports, corev1.ContainerPort{ + { Name: consts.HttpServicePortName, ContainerPort: consts.HttpContainerPort, - }) + }, } return ports diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport_test.go index ec8fd4e70c..2c30cd7282 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport_test.go @@ -3,8 +3,6 @@ package modifiers import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/prioritymap" @@ -12,38 +10,9 @@ import ( "github.com/stretchr/testify/require" ) -func setServicePortUsage(dk *dynakube.DynaKube, isUsed bool) { - if isUsed { - dk.Spec.ActiveGate.Capabilities = append(dk.Spec.ActiveGate.Capabilities, activegate.MetricsIngestCapability.DisplayName) - } -} - -func TestServicePortEnabled(t *testing.T) { - t.Run("true", func(t *testing.T) { - dk := getBaseDynakube() - setServicePortUsage(&dk, true) - multiCapability := capability.NewMultiCapability(&dk) - - mod := NewServicePortModifier(dk, multiCapability, prioritymap.New()) - - assert.True(t, mod.Enabled()) - }) - - t.Run("false", func(t *testing.T) { - dk := getBaseDynakube() - setServicePortUsage(&dk, false) - multiCapability := capability.NewMultiCapability(&dk) - - mod := NewServicePortModifier(dk, multiCapability, prioritymap.New()) - - assert.False(t, mod.Enabled()) - }) -} - func TestServicePortModify(t *testing.T) { t.Run("successfully modified", func(t *testing.T) { dk := getBaseDynakube() - setServicePortUsage(&dk, true) multiCapability := capability.NewMultiCapability(&dk) mod := NewServicePortModifier(dk, multiCapability, prioritymap.New()) builder := createBuilderForTesting() diff --git a/pkg/controllers/dynakube/activegate/reconciler.go b/pkg/controllers/dynakube/activegate/reconciler.go index add8f3b148..e8d2a02496 100644 --- a/pkg/controllers/dynakube/activegate/reconciler.go +++ b/pkg/controllers/dynakube/activegate/reconciler.go @@ -199,10 +199,6 @@ func (r *Reconciler) deleteCapability(ctx context.Context, agCapability capabili } func (r *Reconciler) deleteService(ctx context.Context, agCapability capability.Capability) error { - if r.dk.ActiveGate().NeedsService() { - return nil - } - svc := corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: capability.BuildServiceName(r.dk.Name, agCapability.ShortName()), diff --git a/pkg/controllers/dynakube/activegate/reconciler_test.go b/pkg/controllers/dynakube/activegate/reconciler_test.go index 1a2b746ac1..272d0698f8 100644 --- a/pkg/controllers/dynakube/activegate/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/reconciler_test.go @@ -435,19 +435,24 @@ func TestServiceCreation(t *testing.T) { }, } - t.Run("service exposes correct ports for single capabilities", func(t *testing.T) { + t.Run("service exposes all ports for every capabilities", func(t *testing.T) { expectedCapabilityPorts := map[activegate.CapabilityDisplayName][]string{ activegate.RoutingCapability.DisplayName: { + consts.HttpServicePortName, consts.HttpsServicePortName, }, activegate.MetricsIngestCapability.DisplayName: { - consts.HttpsServicePortName, consts.HttpServicePortName, + consts.HttpsServicePortName, }, activegate.DynatraceApiCapability.DisplayName: { + consts.HttpServicePortName, + consts.HttpsServicePortName, + }, + activegate.KubeMonCapability.DisplayName: { + consts.HttpServicePortName, consts.HttpsServicePortName, }, - activegate.KubeMonCapability.DisplayName: {}, } for capName, expectedPorts := range expectedCapabilityPorts { @@ -477,28 +482,6 @@ func TestServiceCreation(t *testing.T) { assertContainsAllPorts(t, expectedPorts, activegateService.Spec.Ports) } }) - - t.Run("service exposes correct ports for multiple capabilities", func(t *testing.T) { - fakeClient := fake.NewClient(testKubeSystemNamespace) - - reconciler := NewReconciler(fakeClient, fakeClient, dk, dynatraceClient, nil, nil).(*Reconciler) - reconciler.connectionReconciler = createGenericReconcilerMock(t) - reconciler.versionReconciler = createVersionReconcilerMock(t) - reconciler.pullSecretReconciler = createGenericReconcilerMock(t) - - dk.Spec.ActiveGate.Capabilities = []activegate.CapabilityDisplayName{ - activegate.RoutingCapability.DisplayName, - } - expectedPorts := []string{ - consts.HttpsServicePortName, - } - - err := reconciler.Reconcile(context.Background()) - require.NoError(t, err) - - activegateService := getTestActiveGateService(t, fakeClient) - assertContainsAllPorts(t, expectedPorts, activegateService.Spec.Ports) - }) } func assertContainsAllPorts(t *testing.T, expectedPorts []string, servicePorts []corev1.ServicePort) { From eab3a9b72bb80de6d9b89cef73f00591f5defce4 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Tue, 26 Nov 2024 14:14:33 +0100 Subject: [PATCH 004/426] Replace util/address with k8s.io-utils-ptr (#4100) --- cmd/operator/builder_test.go | 4 +-- cmd/operator/manager_test.go | 4 +-- .../v1alpha1/edgeconnect/convert_from_test.go | 6 ++-- pkg/api/v1beta1/dynakube/convert_from.go | 4 +-- pkg/api/v1beta1/dynakube/convert_from_test.go | 10 +++--- pkg/api/v1beta1/dynakube/convert_to.go | 10 +++--- pkg/api/v1beta1/dynakube/convert_to_test.go | 8 ++--- pkg/api/v1beta2/dynakube/convert_from_test.go | 10 +++--- pkg/api/v1beta2/dynakube/convert_to.go | 6 ++-- .../v1beta3/dynakube/dynakube_props_test.go | 16 ++++----- .../activegate/capability/capability.go | 4 +-- .../statefulset/builder/modifiers/kubemon.go | 14 ++++---- .../statefulset/builder/modifiers/rawimage.go | 6 ++-- .../statefulset/builder/modifiers/readonly.go | 4 +-- .../internal/statefulset/statefulset.go | 4 +-- .../internal/statefulset/statefulset_test.go | 4 +-- .../dynakube/extension/eec/statefulset.go | 16 ++++----- .../dynakube/extension/otel/statefulset.go | 4 +-- .../extension/otel/statefulset_test.go | 4 +-- .../dynakube/injection/reconciler_test.go | 8 ++--- .../dynakube/istio/reconciler_test.go | 4 +-- .../dynakube/kspm/daemonset/container.go | 14 ++++---- .../logmonitoring/daemonset/container.go | 14 ++++---- .../metadata/rules/reconciler_test.go | 8 ++--- .../monitoredentities/reconciler_test.go | 6 ++-- .../dynakube/oneagent/daemonset/daemonset.go | 16 ++++----- .../oneagent/daemonset/daemonset_test.go | 20 +++++------ .../dynakube/oneagent/daemonset/env_vars.go | 10 +++--- .../dynakube/version/oneagent_test.go | 4 +-- .../edgeconnect/deployment/deployment.go | 16 ++++----- .../edgeconnect/version/updater_test.go | 6 ++-- .../namespace/ingestendpoint/secret_test.go | 12 +++---- pkg/util/address/address.go | 5 --- pkg/util/address/address_test.go | 35 ------------------- pkg/util/kubeobjects/statefulset/builder.go | 4 +-- pkg/webhook/mutation/pod/init_container.go | 14 ++++---- .../mutation/pod/init_container_test.go | 14 ++++---- .../mutation/pod/metadata/mutator_test.go | 10 +++--- .../mutation/pod/metadata/workload_test.go | 18 +++++----- pkg/webhook/mutation/pod/oneagent/volumes.go | 4 +-- pkg/webhook/mutation/pod/request_test.go | 6 ++-- .../applicationmonitoring/without_csi.go | 6 ++-- test/helpers/components/dynakube/options.go | 4 +-- .../kubeobjects/namespace/namespace.go | 4 +-- test/helpers/sample/app.go | 4 +-- 45 files changed, 182 insertions(+), 222 deletions(-) delete mode 100644 pkg/util/address/address.go delete mode 100644 pkg/util/address/address_test.go diff --git a/cmd/operator/builder_test.go b/cmd/operator/builder_test.go index d693577db3..92f53b2e9f 100644 --- a/cmd/operator/builder_test.go +++ b/cmd/operator/builder_test.go @@ -6,7 +6,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/cmd/manager" dtfake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" configmock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/config" providermock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/manager" managermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager" @@ -19,6 +18,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/config" @@ -166,7 +166,7 @@ func TestOperatorCommand(t *testing.T) { mockMgr.On("GetScheme").Return(scheme.Scheme) mockMgr.On("GetClient").Return(clt) mockMgr.On("GetAPIReader").Return(clt) - mockMgr.On("GetControllerOptions").Return(config.Controller{SkipNameValidation: address.Of(true)}) + mockMgr.On("GetControllerOptions").Return(config.Controller{SkipNameValidation: ptr.To(true)}) mockMgr.On("GetLogger").Return(logr.Logger{}) mockMgr.On("Add", mock.AnythingOfType("*controller.Controller[sigs.k8s.io/controller-runtime/pkg/reconcile.Request]")).Return(nil) mockMgr.On("GetCache").Return(nil) diff --git a/cmd/operator/manager_test.go b/cmd/operator/manager_test.go index e2b92d90ac..3dd726eaa4 100644 --- a/cmd/operator/manager_test.go +++ b/cmd/operator/manager_test.go @@ -6,7 +6,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" managermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager" "github.com/go-logr/logr" "github.com/stretchr/testify/assert" @@ -15,6 +14,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/config" ) @@ -79,7 +79,7 @@ func testHealthzAndReadyz(t *testing.T, createProviderAndRunManager func(mockMgr mockMgr.On("GetScheme").Return(scheme.Scheme) mockMgr.On("GetClient").Return(client) mockMgr.On("GetAPIReader").Return(client) - mockMgr.On("GetControllerOptions").Return(config.Controller{SkipNameValidation: address.Of(true)}) + mockMgr.On("GetControllerOptions").Return(config.Controller{SkipNameValidation: ptr.To(true)}) mockMgr.On("GetLogger").Return(logr.Logger{}) mockMgr.On("Add", mock.AnythingOfType("*controller.Controller[sigs.k8s.io/controller-runtime/pkg/reconcile.Request]")).Return(nil) mockMgr.On("GetCache").Return(nil) diff --git a/pkg/api/v1alpha1/edgeconnect/convert_from_test.go b/pkg/api/v1alpha1/edgeconnect/convert_from_test.go index ae37af9b1d..dc5c38c5b6 100644 --- a/pkg/api/v1alpha1/edgeconnect/convert_from_test.go +++ b/pkg/api/v1alpha1/edgeconnect/convert_from_test.go @@ -10,11 +10,11 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/proxy" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) func TestConvertFrom(t *testing.T) { @@ -92,7 +92,7 @@ func getCurrentSpec() edgeconnect.EdgeConnectSpec { }, CustomPullSecret: "m", CaCertsRef: "n", - ServiceAccountName: address.Of("o"), + ServiceAccountName: ptr.To("o"), OAuth: edgeconnect.OAuthSpec{ ClientSecret: "p", Endpoint: "q", @@ -138,7 +138,7 @@ func getCurrentSpec() edgeconnect.EdgeConnectSpec { HostPatterns: []string{ "y", }, - AutoUpdate: address.Of(true), + AutoUpdate: ptr.To(true), } } diff --git a/pkg/api/v1beta1/dynakube/convert_from.go b/pkg/api/v1beta1/dynakube/convert_from.go index 043e2265ea..3ce9bc625a 100644 --- a/pkg/api/v1beta1/dynakube/convert_from.go +++ b/pkg/api/v1beta1/dynakube/convert_from.go @@ -4,8 +4,8 @@ import ( "strconv" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/conversion" ) @@ -77,7 +77,7 @@ func (dst *DynaKube) fromActiveGateSpec(src *dynakube.DynaKube) { dst.Spec.ActiveGate.DNSPolicy = src.Spec.ActiveGate.DNSPolicy dst.Spec.ActiveGate.TopologySpreadConstraints = src.Spec.ActiveGate.TopologySpreadConstraints dst.Spec.ActiveGate.Resources = src.Spec.ActiveGate.Resources - dst.Spec.ActiveGate.Replicas = address.Of(src.Spec.ActiveGate.GetReplicas()) + dst.Spec.ActiveGate.Replicas = ptr.To(src.Spec.ActiveGate.GetReplicas()) for _, capability := range src.Spec.ActiveGate.Capabilities { dst.Spec.ActiveGate.Capabilities = append(dst.Spec.ActiveGate.Capabilities, CapabilityDisplayName(capability)) diff --git a/pkg/api/v1beta1/dynakube/convert_from_test.go b/pkg/api/v1beta1/dynakube/convert_from_test.go index 025c41d02e..9ed9621959 100644 --- a/pkg/api/v1beta1/dynakube/convert_from_test.go +++ b/pkg/api/v1beta1/dynakube/convert_from_test.go @@ -8,13 +8,13 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) func TestConvertFrom(t *testing.T) { @@ -270,9 +270,9 @@ func getNewDynakubeBase() dynakube.DynaKube { }, TrustedCAs: "trusted-ca", NetworkZone: "network-zone", - DynatraceApiRequestThreshold: address.Of(uint16(42)), + DynatraceApiRequestThreshold: ptr.To(uint16(42)), MetadataEnrichment: dynakube.MetadataEnrichment{ - Enabled: address.Of(true), + Enabled: ptr.To(true), NamespaceSelector: getTestNamespaceSelector(), }, }, @@ -286,7 +286,7 @@ func getNewHostInjectSpec() dynakube.HostInjectSpec { Tolerations: []corev1.Toleration{ {Key: "host-inject-toleration-key", Operator: "In", Value: "host-inject-toleration-value"}, }, - AutoUpdate: address.Of(false), + AutoUpdate: ptr.To(false), DNSPolicy: corev1.DNSClusterFirstWithHostNet, Annotations: map[string]string{ "host-inject-annotation-key": "host-inject-annotation-value", @@ -380,7 +380,7 @@ func getNewActiveGateSpec() activegate.Spec { "activegate-node-selector-key": "activegate-node-selector-value", }, Image: "activegate-image", - Replicas: address.Of(int32(42)), + Replicas: ptr.To(int32(42)), Group: "activegate-group", CustomProperties: &value.Source{ Value: "activegate-cp-value", diff --git a/pkg/api/v1beta1/dynakube/convert_to.go b/pkg/api/v1beta1/dynakube/convert_to.go index de9411a5ef..89c46c2cf7 100644 --- a/pkg/api/v1beta1/dynakube/convert_to.go +++ b/pkg/api/v1beta1/dynakube/convert_to.go @@ -8,7 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/conversion" ) @@ -102,10 +102,10 @@ func (src *DynaKube) toActiveGateSpec(dst *dynakube.DynaKube) { func (src *DynaKube) toMovedFields(dst *dynakube.DynaKube) error { if src.Annotations[AnnotationFeatureMetadataEnrichment] == "false" || !src.NeedAppInjection() { - dst.Spec.MetadataEnrichment = dynakube.MetadataEnrichment{Enabled: address.Of(false)} + dst.Spec.MetadataEnrichment = dynakube.MetadataEnrichment{Enabled: ptr.To(false)} delete(dst.Annotations, AnnotationFeatureMetadataEnrichment) } else { - dst.Spec.MetadataEnrichment = dynakube.MetadataEnrichment{Enabled: address.Of(true)} + dst.Spec.MetadataEnrichment = dynakube.MetadataEnrichment{Enabled: ptr.To(true)} delete(dst.Annotations, AnnotationFeatureMetadataEnrichment) } @@ -149,10 +149,10 @@ func (src *DynaKube) convertDynatraceApiRequestThreshold(dst *dynakube.DynaKube) if duration >= 0 { if math.MaxUint16 < duration { - dst.Spec.DynatraceApiRequestThreshold = address.Of(uint16(math.MaxUint16)) + dst.Spec.DynatraceApiRequestThreshold = ptr.To(uint16(math.MaxUint16)) } else { // linting disabled, handled in if - dst.Spec.DynatraceApiRequestThreshold = address.Of(uint16(duration)) //nolint:gosec + dst.Spec.DynatraceApiRequestThreshold = ptr.To(uint16(duration)) //nolint:gosec } } diff --git a/pkg/api/v1beta1/dynakube/convert_to_test.go b/pkg/api/v1beta1/dynakube/convert_to_test.go index 5d1cc4a98c..f7d397a8f7 100644 --- a/pkg/api/v1beta1/dynakube/convert_to_test.go +++ b/pkg/api/v1beta1/dynakube/convert_to_test.go @@ -5,12 +5,12 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) var testTime = metav1.Now() @@ -172,7 +172,7 @@ func getOldHostInjectSpec() HostInjectSpec { Tolerations: []corev1.Toleration{ {Key: "host-inject-toleration-key", Operator: "In", Value: "host-inject-toleration-value"}, }, - AutoUpdate: address.Of(false), + AutoUpdate: ptr.To(false), DNSPolicy: corev1.DNSClusterFirstWithHostNet, Annotations: map[string]string{ "host-inject-annotation-key": "host-inject-annotation-value", @@ -227,7 +227,7 @@ func getOldCloudNativeSpec() CloudNativeFullStackSpec { func getOldApplicationMonitoringSpec() ApplicationMonitoringSpec { return ApplicationMonitoringSpec{ AppInjectionSpec: getOldAppInjectionSpec(), - UseCSIDriver: address.Of(true), + UseCSIDriver: ptr.To(true), Version: "app-monitoring-version", } } @@ -265,7 +265,7 @@ func getOldActiveGateSpec() ActiveGateSpec { "activegate-node-selector-key": "activegate-node-selector-value", }, Image: "activegate-image", - Replicas: address.Of(int32(42)), + Replicas: ptr.To(int32(42)), Group: "activegate-group", CustomProperties: &DynaKubeValueSource{ Value: "activegate-cp-value", diff --git a/pkg/api/v1beta2/dynakube/convert_from_test.go b/pkg/api/v1beta2/dynakube/convert_from_test.go index 50ea8678e4..35ed4dbdea 100644 --- a/pkg/api/v1beta2/dynakube/convert_from_test.go +++ b/pkg/api/v1beta2/dynakube/convert_from_test.go @@ -8,13 +8,13 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) func TestConvertFrom(t *testing.T) { @@ -261,9 +261,9 @@ func getNewDynakubeBase() dynakube.DynaKube { }, TrustedCAs: "trusted-ca", NetworkZone: "network-zone", - DynatraceApiRequestThreshold: address.Of(uint16(42)), + DynatraceApiRequestThreshold: ptr.To(uint16(42)), MetadataEnrichment: dynakube.MetadataEnrichment{ - Enabled: address.Of(true), + Enabled: ptr.To(true), NamespaceSelector: getTestNamespaceSelector(), }, }, @@ -277,7 +277,7 @@ func getNewHostInjectSpec() dynakube.HostInjectSpec { Tolerations: []corev1.Toleration{ {Key: "host-inject-toleration-key", Operator: "In", Value: "host-inject-toleration-value"}, }, - AutoUpdate: address.Of(false), + AutoUpdate: ptr.To(false), DNSPolicy: corev1.DNSClusterFirstWithHostNet, Annotations: map[string]string{ "host-inject-annotation-key": "host-inject-annotation-value", @@ -371,7 +371,7 @@ func getNewActiveGateSpec() activegate.Spec { "activegate-node-selector-key": "activegate-node-selector-value", }, Image: "activegate-image", - Replicas: address.Of(int32(42)), + Replicas: ptr.To(int32(42)), Group: "activegate-group", CustomProperties: &value.Source{ Value: "activegate-cp-value", diff --git a/pkg/api/v1beta2/dynakube/convert_to.go b/pkg/api/v1beta2/dynakube/convert_to.go index c6515a67ae..76677a69f2 100644 --- a/pkg/api/v1beta2/dynakube/convert_to.go +++ b/pkg/api/v1beta2/dynakube/convert_to.go @@ -7,7 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/conversion" ) @@ -48,10 +48,10 @@ func (src *DynaKube) toBase(dst *dynakube.DynaKube) { func (src *DynaKube) convertDynatraceApiRequestThreshold(dst *dynakube.DynaKube) { if src.Spec.DynatraceApiRequestThreshold >= 0 { if math.MaxUint16 < src.Spec.DynatraceApiRequestThreshold { - dst.Spec.DynatraceApiRequestThreshold = address.Of(uint16(math.MaxUint16)) + dst.Spec.DynatraceApiRequestThreshold = ptr.To(uint16(math.MaxUint16)) } else { // linting disabled, handled in if - dst.Spec.DynatraceApiRequestThreshold = address.Of(uint16(src.Spec.DynatraceApiRequestThreshold)) //nolint:gosec + dst.Spec.DynatraceApiRequestThreshold = ptr.To(uint16(src.Spec.DynatraceApiRequestThreshold)) //nolint:gosec } } } diff --git a/pkg/api/v1beta3/dynakube/dynakube_props_test.go b/pkg/api/v1beta3/dynakube/dynakube_props_test.go index 592db3d418..76cdc4cda1 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_props_test.go +++ b/pkg/api/v1beta3/dynakube/dynakube_props_test.go @@ -20,11 +20,11 @@ import ( "testing" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) const testAPIURL = "http://test-endpoint/api" @@ -142,37 +142,37 @@ func TestIsTokenScopeVerificationAllowed(t *testing.T) { "Do not update after 3 minutes using 5m interval": { lastRequestTimeDeltaMinutes: -3, updateExpected: false, - threshold: address.Of(uint16(5)), + threshold: ptr.To(uint16(5)), }, "Do update after 7 minutes using 5m interval": { lastRequestTimeDeltaMinutes: -7, updateExpected: true, - threshold: address.Of(uint16(5)), + threshold: ptr.To(uint16(5)), }, "Do not update after 17 minutes using 20m interval": { lastRequestTimeDeltaMinutes: -17, updateExpected: false, - threshold: address.Of(uint16(20)), + threshold: ptr.To(uint16(20)), }, "Do update after 22 minutes using 20m interval": { lastRequestTimeDeltaMinutes: -22, updateExpected: true, - threshold: address.Of(uint16(20)), + threshold: ptr.To(uint16(20)), }, "Do update immediately using 0m interval": { lastRequestTimeDeltaMinutes: 0, updateExpected: true, - threshold: address.Of(uint16(0)), + threshold: ptr.To(uint16(0)), }, "Do update after 1 minute using 0m interval": { lastRequestTimeDeltaMinutes: -1, updateExpected: true, - threshold: address.Of(uint16(0)), + threshold: ptr.To(uint16(0)), }, "Do update after 20 minutes using 0m interval": { lastRequestTimeDeltaMinutes: -20, updateExpected: true, - threshold: address.Of(uint16(0)), + threshold: ptr.To(uint16(0)), }, } diff --git a/pkg/controllers/dynakube/activegate/capability/capability.go b/pkg/controllers/dynakube/activegate/capability/capability.go index 7bdbd72d66..01259a7dbe 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability.go +++ b/pkg/controllers/dynakube/activegate/capability/capability.go @@ -7,8 +7,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "k8s.io/utils/net" + "k8s.io/utils/ptr" ) type baseFunc func() *capabilityBase @@ -80,7 +80,7 @@ func NewMultiCapability(dk *dynakube.DynaKube) Capability { mc.properties = &dk.Spec.ActiveGate.CapabilityProperties if len(dk.Spec.ActiveGate.Capabilities) == 0 && dk.IsExtensionsEnabled() { - mc.properties.Replicas = address.Of(int32(1)) + mc.properties.Replicas = ptr.To(int32(1)) } capabilityNames := []string{} diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon.go index 525aed5f89..37f787b963 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon.go @@ -5,10 +5,10 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) var _ volumeModifier = KubernetesMonitoringModifier{} @@ -123,11 +123,11 @@ func (mod KubernetesMonitoringModifier) getReadOnlyInitVolumeMounts() []corev1.V func GetSecurityContext(readOnlyRootFileSystem bool) *corev1.SecurityContext { securityContext := corev1.SecurityContext{ - Privileged: address.Of(false), - AllowPrivilegeEscalation: address.Of(false), - RunAsNonRoot: address.Of(true), - RunAsUser: address.Of(consts.DockerImageUser), - RunAsGroup: address.Of(consts.DockerImageGroup), + Privileged: ptr.To(false), + AllowPrivilegeEscalation: ptr.To(false), + RunAsNonRoot: ptr.To(true), + RunAsUser: ptr.To(consts.DockerImageUser), + RunAsGroup: ptr.To(consts.DockerImageGroup), Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{ "ALL", @@ -136,7 +136,7 @@ func GetSecurityContext(readOnlyRootFileSystem bool) *corev1.SecurityContext { SeccompProfile: &corev1.SeccompProfile{ Type: corev1.SeccompProfileTypeRuntimeDefault, }, - ReadOnlyRootFilesystem: address.Of(readOnlyRootFileSystem), + ReadOnlyRootFilesystem: ptr.To(readOnlyRootFileSystem), } return &securityContext diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/rawimage.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/rawimage.go index 20754aa7de..43b1894dd3 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/rawimage.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/rawimage.go @@ -5,11 +5,11 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" "github.com/Dynatrace/dynatrace-operator/pkg/util/prioritymap" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) var _ envModifier = RawImageModifier{} @@ -82,7 +82,7 @@ func (mod RawImageModifier) tenantUUIDEnvVar() corev1.EnvVar { Name: mod.dk.ActiveGate().GetConnectionInfoConfigMapName(), }, Key: connectioninfo.TenantUUIDKey, - Optional: address.Of(false), + Optional: ptr.To(false), }}} } @@ -94,7 +94,7 @@ func (mod RawImageModifier) communicationEndpointEnvVar() corev1.EnvVar { Name: mod.dk.ActiveGate().GetConnectionInfoConfigMapName(), }, Key: connectioninfo.CommunicationEndpointsKey, - Optional: address.Of(false), + Optional: ptr.To(false), }}, } } diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go index 938158b0ad..99d3db9e30 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go @@ -4,10 +4,10 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) var _ volumeModifier = ReadOnlyModifier{} @@ -35,7 +35,7 @@ func (mod ReadOnlyModifier) Modify(sts *appsv1.StatefulSet) error { sts.Spec.Template.Spec.Volumes = append(sts.Spec.Template.Spec.Volumes, mod.getVolumes()...) baseContainer := container.FindContainerInPodSpec(&sts.Spec.Template.Spec, consts.ActiveGateContainerName) - baseContainer.SecurityContext.ReadOnlyRootFilesystem = address.Of(true) + baseContainer.SecurityContext.ReadOnlyRootFilesystem = ptr.To(true) mod.presentMounts = baseContainer.VolumeMounts baseContainer.VolumeMounts = append(baseContainer.VolumeMounts, mod.getVolumeMounts()...) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index 7e75c2b22a..cb7dafd9b0 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -9,7 +9,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" @@ -19,6 +18,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" ) const defaultEnvPriority = prioritymap.DefaultPriority @@ -200,7 +200,7 @@ func (statefulSetBuilder Builder) buildCommonEnvs() []corev1.EnvVar { Name: deploymentmetadata.GetDeploymentMetadataConfigMapName(statefulSetBuilder.dynakube.Name), }, Key: deploymentmetadata.ActiveGateMetadataKey, - Optional: address.Of(false), + Optional: ptr.To(false), }, }}, }) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index ada84d3849..09fad29d7e 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -13,7 +13,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" agutil "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" @@ -23,6 +22,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) const ( @@ -49,7 +49,7 @@ func getTestDynakube() dynakube.DynaKube { activegate.RoutingCapability.DisplayName, }, CapabilityProperties: activegate.CapabilityProperties{ - Replicas: address.Of(testReplicas), + Replicas: ptr.To(testReplicas), }, }, }, diff --git a/pkg/controllers/dynakube/extension/eec/statefulset.go b/pkg/controllers/dynakube/extension/eec/statefulset.go index afcf6ce634..19c168b918 100644 --- a/pkg/controllers/dynakube/extension/eec/statefulset.go +++ b/pkg/controllers/dynakube/extension/eec/statefulset.go @@ -9,7 +9,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/servicename" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/tls" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/utils" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" @@ -23,6 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" ) const ( @@ -218,12 +218,12 @@ func buildSecurityContext() *corev1.SecurityContext { "ALL", }, }, - Privileged: address.Of(false), - RunAsUser: address.Of(userGroupId), - RunAsGroup: address.Of(userGroupId), - RunAsNonRoot: address.Of(true), - ReadOnlyRootFilesystem: address.Of(true), - AllowPrivilegeEscalation: address.Of(false), + Privileged: ptr.To(false), + RunAsUser: ptr.To(userGroupId), + RunAsGroup: ptr.To(userGroupId), + RunAsNonRoot: ptr.To(true), + ReadOnlyRootFilesystem: ptr.To(true), + AllowPrivilegeEscalation: ptr.To(false), SeccompProfile: &corev1.SeccompProfile{ Type: corev1.SeccompProfileTypeRuntimeDefault, }, @@ -238,7 +238,7 @@ func buildPodSecurityContext(dk *dynakube.DynaKube) *corev1.PodSecurityContext { } if !dk.Spec.Templates.ExtensionExecutionController.UseEphemeralVolume { - podSecurityContext.FSGroup = address.Of(userGroupId) + podSecurityContext.FSGroup = ptr.To(userGroupId) } return podSecurityContext diff --git a/pkg/controllers/dynakube/extension/otel/statefulset.go b/pkg/controllers/dynakube/extension/otel/statefulset.go index db84e338ec..7f4a4dc2df 100644 --- a/pkg/controllers/dynakube/extension/otel/statefulset.go +++ b/pkg/controllers/dynakube/extension/otel/statefulset.go @@ -10,7 +10,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/servicename" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/tls" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/utils" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" @@ -20,6 +19,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" ) const ( @@ -278,7 +278,7 @@ func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { Path: consts.OtelcTokenSecretKey, }, }, - DefaultMode: address.Of(int32(420)), + DefaultMode: ptr.To(int32(420)), }, }, }, diff --git a/pkg/controllers/dynakube/extension/otel/statefulset_test.go b/pkg/controllers/dynakube/extension/otel/statefulset_test.go index 4b5a95cc2e..9718bf6097 100644 --- a/pkg/controllers/dynakube/extension/otel/statefulset_test.go +++ b/pkg/controllers/dynakube/extension/otel/statefulset_test.go @@ -10,7 +10,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/tls" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/utils" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" @@ -21,6 +20,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -516,7 +516,7 @@ func TestVolumes(t *testing.T) { Path: consts.OtelcTokenSecretKey, }, }, - DefaultMode: address.Of(int32(420)), + DefaultMode: ptr.To(int32(420)), }, }, } diff --git a/pkg/controllers/dynakube/injection/reconciler_test.go b/pkg/controllers/dynakube/injection/reconciler_test.go index bf3100b0dc..85c5f782d4 100644 --- a/pkg/controllers/dynakube/injection/reconciler_test.go +++ b/pkg/controllers/dynakube/injection/reconciler_test.go @@ -15,7 +15,6 @@ import ( versions "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/version" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" controllermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/controllers" @@ -30,6 +29,7 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/interceptor" ) @@ -97,7 +97,7 @@ func TestReconciler(t *testing.T) { }, }, MetadataEnrichment: dynakube.MetadataEnrichment{ - Enabled: address.Of(true), + Enabled: ptr.To(true), NamespaceSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ testNamespaceSelectorLabel: testDynakube, @@ -389,7 +389,7 @@ func TestSetupEnrichmentInjection(t *testing.T) { }) rec.enrichmentRulesReconciler = createGenericReconcilerMock(t) rec.monitoredEntitiesReconciler = createGenericReconcilerMock(t) - rec.dk.Spec.MetadataEnrichment.Enabled = address.Of(false) + rec.dk.Spec.MetadataEnrichment.Enabled = ptr.To(false) err := rec.setupEnrichmentInjection(context.Background()) require.NoError(t, err) @@ -405,7 +405,7 @@ func TestSetupEnrichmentInjection(t *testing.T) { }) rec.enrichmentRulesReconciler = createGenericReconcilerMock(t) rec.monitoredEntitiesReconciler = createGenericReconcilerMock(t) - rec.dk.Spec.MetadataEnrichment.Enabled = address.Of(true) + rec.dk.Spec.MetadataEnrichment.Enabled = ptr.To(true) err := rec.setupEnrichmentInjection(context.Background()) require.NoError(t, err) diff --git a/pkg/controllers/dynakube/istio/reconciler_test.go b/pkg/controllers/dynakube/istio/reconciler_test.go index a5be3cc00f..9ebf9d88f3 100644 --- a/pkg/controllers/dynakube/istio/reconciler_test.go +++ b/pkg/controllers/dynakube/istio/reconciler_test.go @@ -10,7 +10,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" istiov1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" @@ -19,6 +18,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/utils/ptr" ) func TestSplitCommunicationHost(t *testing.T) { @@ -493,7 +493,7 @@ func createTestDynaKube() *dynakube.DynaKube { OneAgent: dynakube.OneAgentSpec{ CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, }, - DynatraceApiRequestThreshold: address.Of(uint16(15)), + DynatraceApiRequestThreshold: ptr.To(uint16(15)), }, Status: dynakube.DynaKubeStatus{ OneAgent: dynakube.OneAgentStatus{ diff --git a/pkg/controllers/dynakube/kspm/daemonset/container.go b/pkg/controllers/dynakube/kspm/daemonset/container.go index 3723c5fbcd..3533c927e8 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/container.go +++ b/pkg/controllers/dynakube/kspm/daemonset/container.go @@ -2,9 +2,9 @@ package daemonset import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/resources" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) const ( @@ -33,12 +33,12 @@ func getContainer(dk dynakube.DynaKube, tenantUUID string) corev1.Container { func getSecurityContext() corev1.SecurityContext { securityContext := corev1.SecurityContext{ - Privileged: address.Of(false), - AllowPrivilegeEscalation: address.Of(false), - RunAsUser: address.Of(runAs), - RunAsGroup: address.Of(runAs), - RunAsNonRoot: address.Of(false), - ReadOnlyRootFilesystem: address.Of(true), + Privileged: ptr.To(false), + AllowPrivilegeEscalation: ptr.To(false), + RunAsUser: ptr.To(runAs), + RunAsGroup: ptr.To(runAs), + RunAsNonRoot: ptr.To(false), + ReadOnlyRootFilesystem: ptr.To(true), Capabilities: &corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}, } diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go index 145a6f5d2e..6f0b0658e1 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go @@ -2,8 +2,8 @@ package daemonset import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) const ( @@ -63,12 +63,12 @@ func getInitContainer(dk dynakube.DynaKube) corev1.Container { func getBaseSecurityContext(dk dynakube.DynaKube) corev1.SecurityContext { securityContext := corev1.SecurityContext{ - Privileged: address.Of(false), - ReadOnlyRootFilesystem: address.Of(true), - AllowPrivilegeEscalation: address.Of(false), - RunAsUser: address.Of(runAs), - RunAsGroup: address.Of(runAs), - RunAsNonRoot: address.Of(true), + Privileged: ptr.To(false), + ReadOnlyRootFilesystem: ptr.To(true), + AllowPrivilegeEscalation: ptr.To(false), + RunAsUser: ptr.To(runAs), + RunAsGroup: ptr.To(runAs), + RunAsNonRoot: ptr.To(true), Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{"ALL"}, }, diff --git a/pkg/controllers/dynakube/metadata/rules/reconciler_test.go b/pkg/controllers/dynakube/metadata/rules/reconciler_test.go index e034dca635..3b56ea18b1 100644 --- a/pkg/controllers/dynakube/metadata/rules/reconciler_test.go +++ b/pkg/controllers/dynakube/metadata/rules/reconciler_test.go @@ -8,7 +8,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" @@ -16,6 +15,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) func TestReconcile(t *testing.T) { @@ -23,7 +23,7 @@ func TestReconcile(t *testing.T) { t.Run("no error if not enabled", func(t *testing.T) { dk := createDynaKube() - dk.Spec.MetadataEnrichment.Enabled = address.Of(false) + dk.Spec.MetadataEnrichment.Enabled = ptr.To(false) reconciler := NewReconciler(nil, &dk) @@ -34,7 +34,7 @@ func TestReconcile(t *testing.T) { t.Run("clean-up if previously enabled", func(t *testing.T) { dk := createDynaKube() - dk.Spec.MetadataEnrichment.Enabled = address.Of(false) + dk.Spec.MetadataEnrichment.Enabled = ptr.To(false) dk.Status.MetadataEnrichment.Rules = createRules() conditions.SetStatusUpdated(dk.Conditions(), conditionType, "TESTING") @@ -127,7 +127,7 @@ func createDynaKube() dynakube.DynaKube { }, Spec: dynakube.DynaKubeSpec{ MetadataEnrichment: dynakube.MetadataEnrichment{ - Enabled: address.Of(true), + Enabled: ptr.To(true), }, }, Status: dynakube.DynaKubeStatus{ diff --git a/pkg/controllers/dynakube/monitoredentities/reconciler_test.go b/pkg/controllers/dynakube/monitoredentities/reconciler_test.go index d9314a7e55..ad76dfe185 100644 --- a/pkg/controllers/dynakube/monitoredentities/reconciler_test.go +++ b/pkg/controllers/dynakube/monitoredentities/reconciler_test.go @@ -6,11 +6,11 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) func TestReconcile(t *testing.T) { @@ -21,7 +21,7 @@ func TestReconcile(t *testing.T) { clt.On("GetMonitoredEntitiesForKubeSystemUUID", mock.AnythingOfType("context.backgroundCtx"), "kube-system-uuid").Return([]dtclient.MonitoredEntity{{EntityId: "KUBERNETES_CLUSTER-0E30FE4BF2007587", DisplayName: "operator test entity 1", LastSeenTms: 1639483869085}}, nil) dk := createDynaKube() - dk.Spec.MetadataEnrichment.Enabled = address.Of(false) + dk.Spec.MetadataEnrichment.Enabled = ptr.To(false) reconciler := NewReconciler(clt, &dk) @@ -66,7 +66,7 @@ func createDynaKube() dynakube.DynaKube { }, Spec: dynakube.DynaKubeSpec{ MetadataEnrichment: dynakube.MetadataEnrichment{ - Enabled: address.Of(true), + Enabled: ptr.To(true), }, }, Status: dynakube.DynaKubeStatus{ diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go index 6c3e569f85..1a724f4d58 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go @@ -4,7 +4,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/dtversion" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" @@ -15,6 +14,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" ) const ( @@ -221,7 +221,7 @@ func (b *builder) podSpec() (corev1.PodSpec, error) { DNSPolicy: dnsPolicy, Volumes: volumes, Affinity: affinity, - TerminationGracePeriodSeconds: address.Of(defaultTerminationGracePeriod), + TerminationGracePeriodSeconds: ptr.To(defaultTerminationGracePeriod), } if b.dk.NeedsOneAgentProbe() { @@ -313,16 +313,16 @@ func (b *builder) imagePullSecrets() []corev1.LocalObjectReference { func (b *builder) securityContext() *corev1.SecurityContext { var securityContext corev1.SecurityContext if b.dk != nil && b.dk.UseReadOnlyOneAgents() { - securityContext.RunAsNonRoot = address.Of(true) - securityContext.RunAsUser = address.Of(int64(1000)) - securityContext.RunAsGroup = address.Of(int64(1000)) - securityContext.ReadOnlyRootFilesystem = address.Of(b.isRootFsReadonly()) + securityContext.RunAsNonRoot = ptr.To(true) + securityContext.RunAsUser = ptr.To(int64(1000)) + securityContext.RunAsGroup = ptr.To(int64(1000)) + securityContext.ReadOnlyRootFilesystem = ptr.To(b.isRootFsReadonly()) } else { - securityContext.ReadOnlyRootFilesystem = address.Of(false) + securityContext.ReadOnlyRootFilesystem = ptr.To(false) } if b.dk != nil && b.dk.NeedsOneAgentPrivileged() { - securityContext.Privileged = address.Of(true) + securityContext.Privileged = ptr.To(true) } else { securityContext.Capabilities = defaultSecurityContextCapabilities() diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go index 483bac5b3b..bd3e42865b 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go @@ -8,7 +8,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/version" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" @@ -18,6 +17,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) const ( @@ -270,9 +270,9 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { securityContext := ds.Spec.Template.Spec.Containers[0].SecurityContext assert.NotNil(t, securityContext) - assert.Equal(t, address.Of(int64(1000)), securityContext.RunAsUser) - assert.Equal(t, address.Of(int64(1000)), securityContext.RunAsGroup) - assert.Equal(t, address.Of(true), securityContext.RunAsNonRoot) + assert.Equal(t, ptr.To(int64(1000)), securityContext.RunAsUser) + assert.Equal(t, ptr.To(int64(1000)), securityContext.RunAsGroup) + assert.Equal(t, ptr.To(true), securityContext.RunAsNonRoot) assert.NotEmpty(t, securityContext.Capabilities) assert.Nil(t, securityContext.SeccompProfile) require.NotNil(t, securityContext.ReadOnlyRootFilesystem) @@ -360,10 +360,10 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { securityContext := ds.Spec.Template.Spec.Containers[0].SecurityContext assert.NotNil(t, securityContext) - assert.Equal(t, address.Of(int64(1000)), securityContext.RunAsUser) - assert.Equal(t, address.Of(int64(1000)), securityContext.RunAsGroup) - assert.Equal(t, address.Of(true), securityContext.RunAsNonRoot) - assert.Equal(t, address.Of(true), securityContext.Privileged) + assert.Equal(t, ptr.To(int64(1000)), securityContext.RunAsUser) + assert.Equal(t, ptr.To(int64(1000)), securityContext.RunAsGroup) + assert.Equal(t, ptr.To(true), securityContext.RunAsNonRoot) + assert.Equal(t, ptr.To(true), securityContext.Privileged) assert.Empty(t, securityContext.Capabilities) assert.Nil(t, securityContext.SeccompProfile) }) @@ -394,7 +394,7 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { assert.Nil(t, securityContext.RunAsUser) assert.Nil(t, securityContext.RunAsGroup) assert.Nil(t, securityContext.RunAsNonRoot) - assert.Equal(t, address.Of(true), securityContext.Privileged) + assert.Equal(t, ptr.To(true), securityContext.Privileged) assert.Empty(t, securityContext.Capabilities) assert.Nil(t, securityContext.SeccompProfile) }) @@ -459,7 +459,7 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { assert.Nil(t, securityContext.RunAsUser) assert.Nil(t, securityContext.RunAsGroup) assert.Nil(t, securityContext.RunAsNonRoot) - assert.Equal(t, address.Of(true), securityContext.Privileged) + assert.Equal(t, ptr.To(true), securityContext.Privileged) assert.Empty(t, securityContext.Capabilities) assert.Nil(t, securityContext.SeccompProfile) }) diff --git a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go index e6c23321dd..0771bd4d52 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go @@ -5,11 +5,11 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/prioritymap" "github.com/Dynatrace/dynatrace-operator/pkg/version" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) const ( @@ -70,7 +70,7 @@ func (b *builder) addDeploymentMetadataEnv(envVarMap *prioritymap.Map) { Name: deploymentmetadata.GetDeploymentMetadataConfigMapName(b.dk.Name), }, Key: deploymentmetadata.OneAgentMetadataKey, - Optional: address.Of(false), + Optional: ptr.To(false), }}) } @@ -80,7 +80,7 @@ func (b *builder) addOperatorVersionInfoEnv(envVarMap *prioritymap.Map) { Name: deploymentmetadata.GetDeploymentMetadataConfigMapName(b.dk.Name), }, Key: deploymentmetadata.OperatorVersionKey, - Optional: address.Of(false), + Optional: ptr.To(false), }}) } @@ -90,14 +90,14 @@ func (b *builder) addConnectionInfoEnvs(envVarMap *prioritymap.Map) { Name: b.dk.OneAgentConnectionInfoConfigMapName(), }, Key: connectioninfo.TenantUUIDKey, - Optional: address.Of(false), + Optional: ptr.To(false), }}) addDefaultValueSource(envVarMap, connectioninfo.EnvDtServer, &corev1.EnvVarSource{ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ LocalObjectReference: corev1.LocalObjectReference{ Name: b.dk.OneAgentConnectionInfoConfigMapName(), }, Key: connectioninfo.CommunicationEndpointsKey, - Optional: address.Of(false), + Optional: ptr.To(false), }}) } diff --git a/pkg/controllers/dynakube/version/oneagent_test.go b/pkg/controllers/dynakube/version/oneagent_test.go index f362592c59..3544068c34 100644 --- a/pkg/controllers/dynakube/version/oneagent_test.go +++ b/pkg/controllers/dynakube/version/oneagent_test.go @@ -8,13 +8,13 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) func TestOneAgentUpdater(t *testing.T) { @@ -29,7 +29,7 @@ func TestOneAgentUpdater(t *testing.T) { Spec: dynakube.DynaKubeSpec{ OneAgent: dynakube.OneAgentSpec{ ClassicFullStack: &dynakube.HostInjectSpec{ - AutoUpdate: address.Of(false), + AutoUpdate: ptr.To(false), Image: testImage.String(), Version: testImage.Tag, }, diff --git a/pkg/controllers/edgeconnect/deployment/deployment.go b/pkg/controllers/edgeconnect/deployment/deployment.go index a40d3eb649..eac5b13e19 100644 --- a/pkg/controllers/edgeconnect/deployment/deployment.go +++ b/pkg/controllers/edgeconnect/deployment/deployment.go @@ -3,7 +3,6 @@ package deployment import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/edgeconnect/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/resources" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" @@ -12,6 +11,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) const ( @@ -55,7 +55,7 @@ func create(ec *edgeconnect.EdgeConnect) *appsv1.Deployment { ImagePullSecrets: prepareImagePullSecrets(ec), ServiceAccountName: ec.GetServiceAccountName(), DeprecatedServiceAccount: ec.GetServiceAccountName(), - TerminationGracePeriodSeconds: address.Of(int64(30)), + TerminationGracePeriodSeconds: ptr.To(int64(30)), Volumes: prepareVolumes(ec), NodeSelector: ec.Spec.NodeSelector, Tolerations: ec.Spec.Tolerations, @@ -110,12 +110,12 @@ func edgeConnectContainer(ec *edgeconnect.EdgeConnect) corev1.Container { Env: ec.Spec.Env, Resources: prepareResourceRequirements(ec), SecurityContext: &corev1.SecurityContext{ - AllowPrivilegeEscalation: address.Of(false), - Privileged: address.Of(false), - ReadOnlyRootFilesystem: address.Of(true), - RunAsGroup: address.Of(unprivilegedGroup), - RunAsUser: address.Of(unprivilegedUser), - RunAsNonRoot: address.Of(true), + AllowPrivilegeEscalation: ptr.To(false), + Privileged: ptr.To(false), + ReadOnlyRootFilesystem: ptr.To(true), + RunAsGroup: ptr.To(unprivilegedGroup), + RunAsUser: ptr.To(unprivilegedUser), + RunAsNonRoot: ptr.To(true), }, VolumeMounts: prepareVolumeMounts(ec), } diff --git a/pkg/controllers/edgeconnect/version/updater_test.go b/pkg/controllers/edgeconnect/version/updater_test.go index a43a682723..991ca81d19 100644 --- a/pkg/controllers/edgeconnect/version/updater_test.go +++ b/pkg/controllers/edgeconnect/version/updater_test.go @@ -10,13 +10,13 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" "github.com/Dynatrace/dynatrace-operator/pkg/oci/registry" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" registrymock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/oci/registry" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) const fakeDigest = "sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc" @@ -121,7 +121,7 @@ func TestReconcileRequired(t *testing.T) { edgeConnectTime := metav1.Now() edgeConnect.Status.Version.LastProbeTimestamp = &edgeConnectTime - edgeConnect.Spec.AutoUpdate = address.Of(true) + edgeConnect.Spec.AutoUpdate = ptr.To(true) edgeConnect.Status.Version.ImageID = edgeConnect.Image() assert.False(t, updater.RequiresReconcile()) @@ -133,7 +133,7 @@ func TestReconcileRequired(t *testing.T) { edgeConnectTime := metav1.NewTime(currentTime.Now().Add(-time.Hour)) edgeConnect.Status.Version.LastProbeTimestamp = &edgeConnectTime - edgeConnect.Spec.AutoUpdate = address.Of(true) + edgeConnect.Spec.AutoUpdate = ptr.To(true) edgeConnect.Status.Version.ImageID = edgeConnect.Image() assert.True(t, updater.RequiresReconcile()) diff --git a/pkg/injection/namespace/ingestendpoint/secret_test.go b/pkg/injection/namespace/ingestendpoint/secret_test.go index 48433a24d7..367f08a3d3 100644 --- a/pkg/injection/namespace/ingestendpoint/secret_test.go +++ b/pkg/injection/namespace/ingestendpoint/secret_test.go @@ -9,13 +9,13 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -222,7 +222,7 @@ func TestGenerateMetadataEnrichmentSecret_ForDynakube(t *testing.T) { { dk := buildTestDynakube() - dk.Spec.MetadataEnrichment.Enabled = address.Of(false) + dk.Spec.MetadataEnrichment.Enabled = ptr.To(false) testGenerateEndpointsSecret(t, dk, fakeClient) @@ -304,7 +304,7 @@ func updatedTestDynakube() *dynakube.DynaKube { }, Spec: dynakube.DynaKubeSpec{ APIURL: testUpdatedApiUrl, - MetadataEnrichment: dynakube.MetadataEnrichment{Enabled: address.Of(true)}, + MetadataEnrichment: dynakube.MetadataEnrichment{Enabled: ptr.To(true)}, }, } } @@ -320,7 +320,7 @@ func updatedTestDynakubeWithMetricsIngestCapability(capabilities []activegate.Ca Capabilities: capabilities, }, APIURL: testUpdatedApiUrl, - MetadataEnrichment: dynakube.MetadataEnrichment{Enabled: address.Of(true)}, + MetadataEnrichment: dynakube.MetadataEnrichment{Enabled: ptr.To(true)}, }, } } @@ -344,7 +344,7 @@ func buildTestDynakube() *dynakube.DynaKube { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - MetadataEnrichment: dynakube.MetadataEnrichment{Enabled: address.Of(true)}, + MetadataEnrichment: dynakube.MetadataEnrichment{Enabled: ptr.To(true)}, }, } } @@ -361,7 +361,7 @@ func buildTestDynakubeWithMetricsIngestCapability(capabilities []activegate.Capa }, APIURL: testApiUrl, MetadataEnrichment: dynakube.MetadataEnrichment{ - Enabled: address.Of(true), + Enabled: ptr.To(true), }, }, } diff --git a/pkg/util/address/address.go b/pkg/util/address/address.go deleted file mode 100644 index eded0f6c75..0000000000 --- a/pkg/util/address/address.go +++ /dev/null @@ -1,5 +0,0 @@ -package address - -func Of[T any](i T) *T { - return &i -} diff --git a/pkg/util/address/address_test.go b/pkg/util/address/address_test.go deleted file mode 100644 index 9b755ec036..0000000000 --- a/pkg/util/address/address_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package address - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestOf(t *testing.T) { - t.Run("bool", func(t *testing.T) { - assert.True(t, *Of(true)) - assert.False(t, *Of(false)) - - const constantBool = true - - assert.True(t, *Of(constantBool)) - - mutableBool := true - assert.True(t, *Of(mutableBool)) - - mutableBool = false - assert.False(t, *Of(mutableBool)) - }) - - t.Run("int64", func(t *testing.T) { - assert.Equal(t, 23, *Of(23)) - - const constantInt = 27 - - assert.Equal(t, 27, *Of(constantInt)) - - mutableInt := int64(4) - assert.Equal(t, int64(4), *Of(mutableInt)) - }) -} diff --git a/pkg/util/kubeobjects/statefulset/builder.go b/pkg/util/kubeobjects/statefulset/builder.go index 27d505caac..9356a64687 100644 --- a/pkg/util/kubeobjects/statefulset/builder.go +++ b/pkg/util/kubeobjects/statefulset/builder.go @@ -1,12 +1,12 @@ package statefulset import ( - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/internal/builder" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) var ( @@ -31,7 +31,7 @@ func Build(owner metav1.Object, name string, container corev1.Container, options func SetReplicas(replicas int32) builder.Option[*appsv1.StatefulSet] { return func(s *appsv1.StatefulSet) { - s.Spec.Replicas = address.Of(replicas) + s.Spec.Replicas = ptr.To(replicas) } } diff --git a/pkg/webhook/mutation/pod/init_container.go b/pkg/webhook/mutation/pod/init_container.go index 65a5be9e8d..545625369f 100644 --- a/pkg/webhook/mutation/pod/init_container.go +++ b/pkg/webhook/mutation/pod/init_container.go @@ -7,7 +7,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" k8spod "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/pod" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/resources" @@ -16,6 +15,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/metadata" oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) func createInstallInitContainerBase(webhookImage, clusterID string, pod *corev1.Pod, dk dynakube.DynaKube) *corev1.Container { @@ -60,9 +60,9 @@ func defaultInitContainerResources() corev1.ResourceRequirements { func securityContextForInitContainer(pod *corev1.Pod, dk dynakube.DynaKube) *corev1.SecurityContext { initSecurityCtx := corev1.SecurityContext{ - ReadOnlyRootFilesystem: address.Of(true), - AllowPrivilegeEscalation: address.Of(false), - Privileged: address.Of(false), + ReadOnlyRootFilesystem: ptr.To(true), + AllowPrivilegeEscalation: ptr.To(false), + Privileged: ptr.To(false), Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{ "ALL", @@ -81,8 +81,8 @@ func combineSecurityContexts(baseSecurityCtx corev1.SecurityContext, pod corev1. containerSecurityCtx := pod.Spec.Containers[0].SecurityContext podSecurityCtx := pod.Spec.SecurityContext - baseSecurityCtx.RunAsUser = address.Of(defaultUser) - baseSecurityCtx.RunAsGroup = address.Of(defaultGroup) + baseSecurityCtx.RunAsUser = ptr.To(defaultUser) + baseSecurityCtx.RunAsGroup = ptr.To(defaultGroup) if hasPodUserSet(podSecurityCtx) { baseSecurityCtx.RunAsUser = podSecurityCtx.RunAsUser @@ -100,7 +100,7 @@ func combineSecurityContexts(baseSecurityCtx corev1.SecurityContext, pod corev1. baseSecurityCtx.RunAsGroup = containerSecurityCtx.RunAsGroup } - baseSecurityCtx.RunAsNonRoot = address.Of(isNonRoot(&baseSecurityCtx)) + baseSecurityCtx.RunAsNonRoot = ptr.To(isNonRoot(&baseSecurityCtx)) return &baseSecurityCtx } diff --git a/pkg/webhook/mutation/pod/init_container_test.go b/pkg/webhook/mutation/pod/init_container_test.go index 0b8a0bdaf0..7b240c39bb 100644 --- a/pkg/webhook/mutation/pod/init_container_test.go +++ b/pkg/webhook/mutation/pod/init_container_test.go @@ -4,13 +4,13 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) func TestCreateInstallInitContainerBase(t *testing.T) { @@ -51,7 +51,7 @@ func TestCreateInstallInitContainerBase(t *testing.T) { t.Run("should overwrite partially", func(t *testing.T) { dk := getTestDynakube() pod := getTestPod() - testUser := address.Of(int64(420)) + testUser := ptr.To(int64(420)) pod.Spec.Containers[0].SecurityContext.RunAsUser = nil pod.Spec.Containers[0].SecurityContext.RunAsGroup = testUser webhookImage := "test-image" @@ -71,8 +71,8 @@ func TestCreateInstallInitContainerBase(t *testing.T) { t.Run("container SecurityContext overrules defaults", func(t *testing.T) { dk := getTestDynakube() pod := getTestPod() - overruledUser := address.Of(int64(420)) - testUser := address.Of(int64(420)) + overruledUser := ptr.To(int64(420)) + testUser := ptr.To(int64(420)) pod.Spec.SecurityContext = &corev1.PodSecurityContext{} pod.Spec.SecurityContext.RunAsUser = overruledUser pod.Spec.SecurityContext.RunAsGroup = overruledUser @@ -93,7 +93,7 @@ func TestCreateInstallInitContainerBase(t *testing.T) { }) t.Run("PodSecurityContext overrules defaults", func(t *testing.T) { dk := getTestDynakube() - testUser := address.Of(int64(420)) + testUser := ptr.To(int64(420)) pod := getTestPod() pod.Spec.Containers[0].SecurityContext = nil pod.Spec.SecurityContext = &corev1.PodSecurityContext{} @@ -116,8 +116,8 @@ func TestCreateInstallInitContainerBase(t *testing.T) { t.Run("should set RunAsNonRoot if root user is used", func(t *testing.T) { dk := getTestDynakube() pod := getTestPod() - pod.Spec.Containers[0].SecurityContext.RunAsUser = address.Of(rootUserGroup) - pod.Spec.Containers[0].SecurityContext.RunAsGroup = address.Of(rootUserGroup) + pod.Spec.Containers[0].SecurityContext.RunAsUser = ptr.To(rootUserGroup) + pod.Spec.Containers[0].SecurityContext.RunAsGroup = ptr.To(rootUserGroup) webhookImage := "test-image" clusterID := "id" diff --git a/pkg/webhook/mutation/pod/metadata/mutator_test.go b/pkg/webhook/mutation/pod/metadata/mutator_test.go index bf35f478cb..af93e4c8cf 100644 --- a/pkg/webhook/mutation/pod/metadata/mutator_test.go +++ b/pkg/webhook/mutation/pod/metadata/mutator_test.go @@ -10,13 +10,13 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -44,7 +44,7 @@ func TestEnabled(t *testing.T) { t.Run("off by feature flag", func(t *testing.T) { mutator := createTestPodMutator(nil) request := createTestMutationRequest(nil, nil, false) - request.DynaKube.Spec.MetadataEnrichment.Enabled = address.Of(true) + request.DynaKube.Spec.MetadataEnrichment.Enabled = ptr.To(true) request.DynaKube.Annotations = map[string]string{dynakube.AnnotationFeatureAutomaticInjection: "false"} enabled := mutator.Enabled(request.BaseRequest) @@ -55,7 +55,7 @@ func TestEnabled(t *testing.T) { mutator := createTestPodMutator(nil) dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - MetadataEnrichment: dynakube.MetadataEnrichment{Enabled: address.Of(true)}, + MetadataEnrichment: dynakube.MetadataEnrichment{Enabled: ptr.To(true)}, }, } request := createTestMutationRequest(&dk, nil, false) @@ -70,7 +70,7 @@ func TestEnabled(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ MetadataEnrichment: dynakube.MetadataEnrichment{ - Enabled: address.Of(true), + Enabled: ptr.To(true), NamespaceSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ testLabelKeyMatching: testLabelValue, @@ -91,7 +91,7 @@ func TestEnabled(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ MetadataEnrichment: dynakube.MetadataEnrichment{ - Enabled: address.Of(true), + Enabled: ptr.To(true), NamespaceSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ testLabelKeyNotMatching: testLabelValue, diff --git a/pkg/webhook/mutation/pod/metadata/workload_test.go b/pkg/webhook/mutation/pod/metadata/workload_test.go index 2095a75362..09c533f255 100644 --- a/pkg/webhook/mutation/pod/metadata/workload_test.go +++ b/pkg/webhook/mutation/pod/metadata/workload_test.go @@ -5,13 +5,13 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/interceptor" ) @@ -29,7 +29,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { APIVersion: "apps/v1", Kind: "Deployment", Name: "test", - Controller: address.Of(true), + Controller: ptr.To(true), }, }, Name: resourceName, @@ -44,7 +44,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { APIVersion: "apps/v1", Kind: "DaemonSet", Name: "test", - Controller: address.Of(true), + Controller: ptr.To(true), }, }, Name: resourceName, @@ -105,7 +105,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { APIVersion: "v1", Kind: "Secret", Name: "test", - Controller: address.Of(true), + Controller: ptr.To(true), }, }, Name: resourceName, @@ -135,8 +135,8 @@ func TestFindRootOwnerOfPod(t *testing.T) { APIVersion: "some.unknown.kind.com/v1alpha1", Kind: "SomeUnknownKind", Name: "some-owner", - Controller: address.Of(false), - BlockOwnerDeletion: address.Of(false), + Controller: ptr.To(false), + BlockOwnerDeletion: ptr.To(false), }, }, Name: resourceName, @@ -156,7 +156,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { APIVersion: "apps/v1", Kind: "Deployment", Name: "test", - Controller: address.Of(true), + Controller: ptr.To(true), }, }, Name: resourceName, @@ -175,7 +175,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { APIVersion: "v1", Kind: "Secret", Name: "test", - Controller: address.Of(true), + Controller: ptr.To(true), }, }, Name: resourceName, @@ -214,7 +214,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { APIVersion: "some.unknown.kind.com/v1alpha1", Kind: "SomeUnknownKind", Name: "some-owner", - Controller: address.Of(true), + Controller: ptr.To(true), }, }, Name: resourceName, diff --git a/pkg/webhook/mutation/pod/oneagent/volumes.go b/pkg/webhook/mutation/pod/oneagent/volumes.go index dd21940128..29c38f2045 100644 --- a/pkg/webhook/mutation/pod/oneagent/volumes.go +++ b/pkg/webhook/mutation/pod/oneagent/volumes.go @@ -9,8 +9,8 @@ import ( dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csivolumes "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver/volumes" appvolumes "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver/volumes/app" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) func (mut *Mutator) addVolumes(pod *corev1.Pod, dk dynakube.DynaKube) { @@ -164,7 +164,7 @@ func getInstallerVolumeSource(dk dynakube.DynaKube) corev1.VolumeSource { if dk.IsCSIAvailable() { volumeSource.CSI = &corev1.CSIVolumeSource{ Driver: dtcsi.DriverName, - ReadOnly: address.Of(dk.FeatureReadOnlyCsiVolume()), + ReadOnly: ptr.To(dk.FeatureReadOnlyCsiVolume()), VolumeAttributes: map[string]string{ csivolumes.CSIVolumeAttributeModeField: appvolumes.Mode, csivolumes.CSIVolumeAttributeDynakubeField: dk.Name, diff --git a/pkg/webhook/mutation/pod/request_test.go b/pkg/webhook/mutation/pod/request_test.go index d6a14dd2ca..c8704c63fb 100644 --- a/pkg/webhook/mutation/pod/request_test.go +++ b/pkg/webhook/mutation/pod/request_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,6 +13,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) @@ -22,8 +22,8 @@ const testUser int64 = 420 func getTestSecurityContext() *corev1.SecurityContext { return &corev1.SecurityContext{ - RunAsUser: address.Of(testUser), - RunAsGroup: address.Of(testUser), + RunAsUser: ptr.To(testUser), + RunAsGroup: ptr.To(testUser), } } diff --git a/test/features/applicationmonitoring/without_csi.go b/test/features/applicationmonitoring/without_csi.go index 8f36d510c7..59386ddcbf 100644 --- a/test/features/applicationmonitoring/without_csi.go +++ b/test/features/applicationmonitoring/without_csi.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" @@ -15,6 +14,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/e2e-framework/pkg/envconf" "sigs.k8s.io/e2e-framework/pkg/features" ) @@ -52,8 +52,8 @@ func WithoutCSI(t *testing.T) features.Feature { sample.WithName("random-user"), sample.AsDeployment(), sample.WithSecurityContext(corev1.PodSecurityContext{ - RunAsUser: address.Of[int64](1234), - RunAsGroup: address.Of[int64](1234), + RunAsUser: ptr.To[int64](1234), + RunAsGroup: ptr.To[int64](1234), }), ) builder.Assess("install sample app with random users set", randomUserSample.Install()) diff --git a/test/helpers/components/dynakube/options.go b/test/helpers/components/dynakube/options.go index b8effdc108..0a623ee2cf 100644 --- a/test/helpers/components/dynakube/options.go +++ b/test/helpers/components/dynakube/options.go @@ -7,9 +7,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) type Option func(dk *dynakube.DynaKube) @@ -71,7 +71,7 @@ func WithActiveGate() Option { func WithMetadataEnrichment() Option { return func(dk *dynakube.DynaKube) { - dk.Spec.MetadataEnrichment.Enabled = address.Of(true) + dk.Spec.MetadataEnrichment.Enabled = ptr.To(true) } } diff --git a/test/helpers/kubeobjects/namespace/namespace.go b/test/helpers/kubeobjects/namespace/namespace.go index a1af00e080..49e178f7fa 100644 --- a/test/helpers/kubeobjects/namespace/namespace.go +++ b/test/helpers/kubeobjects/namespace/namespace.go @@ -7,12 +7,12 @@ import ( "testing" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/e2e-framework/klient/wait" "sigs.k8s.io/e2e-framework/klient/wait/conditions" "sigs.k8s.io/e2e-framework/pkg/env" @@ -65,7 +65,7 @@ func Delete(namespaceName string) features.Func { } err := envConfig.Client().Resources().Delete(ctx, &namespace, func(options *metav1.DeleteOptions) { - options.GracePeriodSeconds = address.Of[int64](0) + options.GracePeriodSeconds = ptr.To[int64](0) }) if err != nil { diff --git a/test/helpers/sample/app.go b/test/helpers/sample/app.go index 8e5819b9ec..829239e151 100644 --- a/test/helpers/sample/app.go +++ b/test/helpers/sample/app.go @@ -9,7 +9,6 @@ import ( "testing" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/util/address" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/deployment" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/manifests" @@ -22,6 +21,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/e2e-framework/klient/k8s" "sigs.k8s.io/e2e-framework/klient/k8s/resources" "sigs.k8s.io/e2e-framework/klient/wait" @@ -215,7 +215,7 @@ func (app *App) asDeployment() *appsv1.Deployment { return &appsv1.Deployment{ ObjectMeta: app.base.ObjectMeta, Spec: appsv1.DeploymentSpec{ - Replicas: address.Of(int32(2)), + Replicas: ptr.To(int32(2)), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ selectorKey: selectorValue, From 5e0d393d77753cbaffdb33175e6644c6c4f9fc50 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:00:12 +0100 Subject: [PATCH 005/426] [Automatic] Update because new branch created release-1.4 (#4104) Co-authored-by: andriisoldatenko Co-authored-by: Andrii Soldatenko --- .github/renovate.json5 | 4 ++-- .github/workflows/e2e-tests-ondemand.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index a2a18f2afe..593a7677e9 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -11,9 +11,9 @@ }, baseBranches: [ "$default", - "release-1.1", "release-1.2", "release-1.3", + "release-1.4", ], enabledManagers: [ "regex", @@ -62,9 +62,9 @@ { matchBaseBranches: [ "$default", - "release-1.1", "release-1.2", "release-1.3", + "release-1.4", ], matchUpdateTypes: [ "major", diff --git a/.github/workflows/e2e-tests-ondemand.yaml b/.github/workflows/e2e-tests-ondemand.yaml index e65fbe13dc..ea9ddcff5c 100644 --- a/.github/workflows/e2e-tests-ondemand.yaml +++ b/.github/workflows/e2e-tests-ondemand.yaml @@ -6,7 +6,7 @@ on: - cron: 0 3 * * 1,3,5 env: - branch: 'release-1.3' + branch: release-1.4 permissions: checks: write From 7dcfbe555acaaa1f7374d3a2c8a7249deefd11d4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:30:16 +0000 Subject: [PATCH 006/426] chore(deps): update dependency json5 to v0.10.0 (main) (#4113) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/requirements.txt b/hack/requirements.txt index ed487d3843..5612512238 100644 --- a/hack/requirements.txt +++ b/hack/requirements.txt @@ -1,4 +1,4 @@ argparse==1.4.0 pyyaml==6.0.2 -json5==0.9.28 +json5==0.10.0 ruamel.yaml==0.18.6 From 112ae9179059373a9fbc84edcc0cd5d60be13ddf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Nov 2024 04:38:55 +0000 Subject: [PATCH 007/426] chore(deps): update module github.com/vektra/mockery to v2.49.1 (main) (#4114) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 3a041dd9ed..c712574740 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.27.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.49.0 +mockery_version=v2.49.1 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest From fa7c9ac4b4344da80cb90d98541a4fa318f58c66 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Wed, 27 Nov 2024 18:26:21 +0100 Subject: [PATCH 008/426] Add new pipelins to on-demand E2E tests. (#4117) --- .github/workflows/e2e-tests-ondemand.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/e2e-tests-ondemand.yaml b/.github/workflows/e2e-tests-ondemand.yaml index ea9ddcff5c..36e1aaddf1 100644 --- a/.github/workflows/e2e-tests-ondemand.yaml +++ b/.github/workflows/e2e-tests-ondemand.yaml @@ -33,6 +33,8 @@ jobs: platform: k8s - version: 1-29 platform: k8s + - version: 1-30 + platform: k8s - version: 4-10 platform: ocp - version: 4-11 @@ -45,6 +47,8 @@ jobs: platform: ocp - version: 4-15 platform: ocp + - version: 4-16 + platform: ocp environment: E2E runs-on: - self-hosted From 6fa8b5278333b04d2540a31a4fe5c0d7f9272201 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 28 Nov 2024 08:23:05 +0100 Subject: [PATCH 009/426] Remove standalone logMonitoring nodeSelector validation (#4109) --- pkg/api/validation/dynakube/oneagent.go | 10 +--- pkg/api/validation/dynakube/oneagent_test.go | 57 -------------------- 2 files changed, 1 insertion(+), 66 deletions(-) diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index 7eb441404a..e78f015591 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -60,7 +60,7 @@ func conflictingOneAgentConfiguration(_ context.Context, _ *Validator, dk *dynak } func conflictingOneAgentNodeSelector(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { - if !dk.LogMonitoring().IsStandalone() && !dk.NeedsOneAgent() { + if !dk.NeedsOneAgent() { return "" } @@ -86,14 +86,6 @@ func conflictingOneAgentNodeSelector(ctx context.Context, dv *Validator, dk *dyn conflictingDynakubes[item.Name] = true } } - - if item.LogMonitoring().IsStandalone() { - if hasConflictingMatchLabels(oneAgentNodeSelector, item.OneAgentNodeSelector()) { - log.Info("requested dynakube has conflicting LogMonitoring nodeSelector", "name", dk.Name, "namespace", dk.Namespace) - - conflictingDynakubes[item.Name] = true - } - } } if len(conflictingDynakubes) > 0 { diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index 3461b07137..a526d35a2e 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -76,28 +75,6 @@ func TestConflictingOneAgentConfiguration(t *testing.T) { } func TestConflictingNodeSelector(t *testing.T) { - newCloudNativeDynakube := func(name string, annotations map[string]string, nodeSelectorValue string) *dynakube.DynaKube { - return &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: testNamespace, - Annotations: annotations, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ - NodeSelector: map[string]string{ - "node": nodeSelectorValue, - }, - }, - }, - }, - }, - } - } - t.Run("valid dynakube specs", func(t *testing.T) { assertAllowedWithoutWarnings(t, &dynakube.DynaKube{ @@ -162,20 +139,6 @@ func TestConflictingNodeSelector(t *testing.T) { }, }, }) - - assertAllowedWithoutWarnings(t, newCloudNativeDynakube("dk1", map[string]string{}, "1"), - &dynakube.DynaKube{ - ObjectMeta: defaultDynakubeObjectMeta, - Spec: dynakube.DynaKubeSpec{ - APIURL: testApiUrl, - LogMonitoring: &logmonitoring.Spec{}, - Templates: dynakube.TemplatesSpec{ - LogMonitoring: &logmonitoring.TemplateSpec{ - NodeSelector: map[string]string{"node": "12"}, - }, - }, - }, - }) }) t.Run(`invalid dynakube specs`, func(t *testing.T) { assertDenied(t, @@ -212,26 +175,6 @@ func TestConflictingNodeSelector(t *testing.T) { }, }) }) - t.Run(`invalid dynakube specs with existing log module`, func(t *testing.T) { - assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, "dk-lm")}, - newCloudNativeDynakube("dk-cm", map[string]string{}, "1"), - createStandaloneLogMonitoringDynakube("dk-lm", "1")) - - assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, ""), "dk-lm", "dk-cm2"}, - newCloudNativeDynakube("dk-cm1", map[string]string{}, "1"), - createStandaloneLogMonitoringDynakube("dk-lm", ""), - newCloudNativeDynakube("dk-cm2", map[string]string{}, "1")) - - assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, "dk-lm")}, - newCloudNativeDynakube("dk-cn", map[string]string{}, "1"), - createStandaloneLogMonitoringDynakube("dk-lm", "1")) - assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, "dk-cn")}, - createStandaloneLogMonitoringDynakube("dk-lm", "1"), - newCloudNativeDynakube("dk-cn", map[string]string{}, "1")) - assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, "dk-lm2")}, - createStandaloneLogMonitoringDynakube("dk-lm1", "1"), - createStandaloneLogMonitoringDynakube("dk-lm2", "1")) - }) } func setupDisabledCSIEnv(t *testing.T) { From c282f37b3e82d6d63156534d0a13e90822205156 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Thu, 28 Nov 2024 09:00:49 +0100 Subject: [PATCH 010/426] Allow custom version for cloudnative (#4110) Co-authored-by: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> --- pkg/api/v1beta3/dynakube/oneagent_props.go | 4 ---- pkg/controllers/dynakube/version/updater.go | 5 ++--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/pkg/api/v1beta3/dynakube/oneagent_props.go b/pkg/api/v1beta3/dynakube/oneagent_props.go index ce8752faa6..e1471af4ce 100644 --- a/pkg/api/v1beta3/dynakube/oneagent_props.go +++ b/pkg/api/v1beta3/dynakube/oneagent_props.go @@ -163,10 +163,6 @@ func (dk *DynaKube) CustomCodeModulesImage() string { // CustomCodeModulesVersion provides the version for the CodeModules provided in the Spec. func (dk *DynaKube) CustomCodeModulesVersion() string { - if !dk.ApplicationMonitoringMode() { - return "" - } - return dk.CustomOneAgentVersion() } diff --git a/pkg/controllers/dynakube/version/updater.go b/pkg/controllers/dynakube/version/updater.go index 68804c5c6e..6b674ed690 100644 --- a/pkg/controllers/dynakube/version/updater.go +++ b/pkg/controllers/dynakube/version/updater.go @@ -40,10 +40,9 @@ func (r *reconciler) run(ctx context.Context, updater StatusUpdater) error { } }() - customImage := updater.CustomImage() - if customImage != "" { + if currentSource == status.CustomImageVersionSource { log.Info("updating version status according to custom image", "updater", updater.Name()) - setImageIDToCustomImage(updater.Target(), customImage) + setImageIDToCustomImage(updater.Target(), updater.CustomImage()) return nil } From b12cb0cf69d304c04d915a0cbe9ebf73c10c15a9 Mon Sep 17 00:00:00 2001 From: Lukas Hinterreiter <90035514+luhi-DT@users.noreply.github.com> Date: Thu, 28 Nov 2024 13:49:03 +0100 Subject: [PATCH 011/426] Remove OLM upper-bound version limit (#4120) --- hack/build/bundle.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hack/build/bundle.sh b/hack/build/bundle.sh index ea414ad1a9..cf4db051fa 100755 --- a/hack/build/bundle.sh +++ b/hack/build/bundle.sh @@ -62,12 +62,12 @@ grep -v '# Labels for testing.' "./config/olm/${PLATFORM}/bundle-${VERSION}.Dock mv "./config/olm/${PLATFORM}/bundle-${VERSION}.Dockerfile.output" "./config/olm/${PLATFORM}/bundle-${VERSION}.Dockerfile" if [ "${PLATFORM}" = "openshift" ]; then # shellcheck disable=SC2129 - echo 'LABEL com.redhat.openshift.versions="v4.9-v4.16"' >> "./config/olm/${PLATFORM}/bundle-${VERSION}.Dockerfile" + echo 'LABEL com.redhat.openshift.versions="v4.9-"' >> "./config/olm/${PLATFORM}/bundle-${VERSION}.Dockerfile" echo 'LABEL com.redhat.delivery.operator.bundle=true' >> "./config/olm/${PLATFORM}/bundle-${VERSION}.Dockerfile" echo 'LABEL com.redhat.delivery.backport=true' >> "./config/olm/${PLATFORM}/bundle-${VERSION}.Dockerfile" sed 's/\bkubectl\b/oc/g' "./config/olm/${PLATFORM}/${VERSION}/manifests/dynatrace-operator.v${VERSION}.clusterserviceversion.yaml" > "./config/olm/${PLATFORM}/${VERSION}/manifests/dynatrace-operator.v${VERSION}.clusterserviceversion.yaml.output" mv "./config/olm/${PLATFORM}/${VERSION}/manifests/dynatrace-operator.v${VERSION}.clusterserviceversion.yaml.output" "./config/olm/${PLATFORM}/${VERSION}/manifests/dynatrace-operator.v${VERSION}.clusterserviceversion.yaml" - echo ' com.redhat.openshift.versions: v4.9-v4.16' >> "./config/olm/${PLATFORM}/${VERSION}/metadata/annotations.yaml" + echo ' com.redhat.openshift.versions: v4.9-' >> "./config/olm/${PLATFORM}/${VERSION}/metadata/annotations.yaml" fi grep -v 'scorecard' "./config/olm/${PLATFORM}/${VERSION}/metadata/annotations.yaml" > "./config/olm/${PLATFORM}/${VERSION}/metadata/annotations.yaml.output" grep -v ' # Annotations for testing.' "./config/olm/${PLATFORM}/${VERSION}/metadata/annotations.yaml.output" > "./config/olm/${PLATFORM}/${VERSION}/metadata/annotations.yaml" From 359796f7fb49705c19b4c40af5bea21a4e0e00f4 Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:13:26 +0100 Subject: [PATCH 012/426] Fixes 'make manifests' bug caused by overwritten generate_manifest definition (#4116) --- hack/make/manifests/kubernetes.mk | 8 ++++---- hack/make/manifests/openshift.mk | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hack/make/manifests/kubernetes.mk b/hack/make/manifests/kubernetes.mk index 8f43b999b1..8efc6d4fe2 100644 --- a/hack/make/manifests/kubernetes.mk +++ b/hack/make/manifests/kubernetes.mk @@ -1,4 +1,4 @@ -define generate_manifest +define generate_k8s_manifest helm template dynatrace-operator config/helm/chart/default \ --namespace dynatrace \ --set csidriver.enabled=$(1) \ @@ -11,15 +11,15 @@ endef ## Generates a Kubernetes manifest including CRD and CSI driver manifests/kubernetes/csi: manifests/crd/helm - $(call generate_manifest,true,$(KUBERNETES_CSIDRIVER_YAML)) + $(call generate_k8s_manifest,true,$(KUBERNETES_CSIDRIVER_YAML)) ## Generates a Kubernetes manifest including CRD without CSI driver manifests/kubernetes/core: manifests/crd/helm - $(call generate_manifest,false,$(KUBERNETES_CORE_YAML)) + $(call generate_k8s_manifest,false,$(KUBERNETES_CORE_YAML)) ## Generates a Kubernetes manifest including CRD and CSI driver with OLM set to true manifests/kubernetes/olm: manifests/crd/helm - OLM=true $(call generate_manifest,true,$(KUBERNETES_OLM_YAML)) + OLM=true $(call generate_k8s_manifest,true,$(KUBERNETES_OLM_YAML)) ## Generates a manifest for Kubernetes including a CRD, a CSI driver deployment manifests/kubernetes: manifests/kubernetes/core manifests/kubernetes/csi diff --git a/hack/make/manifests/openshift.mk b/hack/make/manifests/openshift.mk index c3116ee03f..b7665113f8 100644 --- a/hack/make/manifests/openshift.mk +++ b/hack/make/manifests/openshift.mk @@ -1,4 +1,4 @@ -define generate_manifest +define generate_openshift_manifest helm template dynatrace-operator config/helm/chart/default \ --namespace dynatrace \ --set csidriver.enabled=$(1) \ @@ -11,15 +11,15 @@ endef ## Generates an Openshift manifest including CRD and CSI driver manifests/openshift/csi: manifests/crd/helm - $(call generate_manifest,true,$(OPENSHIFT_CSIDRIVER_YAML)) + $(call generate_openshift_manifest,true,$(OPENSHIFT_CSIDRIVER_YAML)) ## Generates a Openshift manifest including CRD without CSI driver manifests/openshift/core: manifests/crd/helm - $(call generate_manifest,false,$(OPENSHIFT_CORE_YAML)) + $(call generate_openshift_manifest,false,$(OPENSHIFT_CORE_YAML)) ## Generates an Openshift manifest including CRD and CSI driver with OLM set to true manifests/openshift/olm: manifests/crd/helm - OLM=true $(call generate_manifest,true,$(OPENSHIFT_OLM_YAML)) + OLM=true $(call generate_openshift_manifest,true,$(OPENSHIFT_OLM_YAML)) ## Generates a manifest for OpenShift including a CRD and a CSI driver deployment manifests/openshift: manifests/openshift/core manifests/openshift/csi From 12cb27ea466d0034b660097a7c9e2ff45eeacb3f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 18:23:59 +0000 Subject: [PATCH 013/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1732804088 (main) (#4121) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f1bf6ffc31..c85d6e9a7d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS=" -o ./build/_output/bin/dynatrace-operator ./cmd/ FROM registry.access.redhat.com/ubi9-micro:9.5-1731934928@sha256:31f00ba1d79523e182624c96e05b2f5ca66ea35d64959d84acdc8b670429415f AS base -FROM registry.access.redhat.com/ubi9:9.5-1731517889@sha256:2bae9062eddbbc18e76555972e7026ffe02cef560a0076e6d7f72bed2c05723f AS dependency +FROM registry.access.redhat.com/ubi9:9.5-1732804088@sha256:1057dab827c782abcfb9bda0c3900c0966b5066e671d54976a7bcb3a2d1a5e53 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 4d01742c31c7cde41484d0b6ca92d060567f2240 Mon Sep 17 00:00:00 2001 From: Lukas Hinterreiter <90035514+luhi-DT@users.noreply.github.com> Date: Fri, 29 Nov 2024 11:53:43 +0100 Subject: [PATCH 014/426] Create kubernetes-monitoring rbac's if only KSPM is enabled (#4125) (#4126) --- .../clusterrole-kubernetes-monitoring.yaml | 2 +- .../serviceaccount-kubernetes-monitoring.yaml | 2 +- .../clusterrole-kubernetes-monitoring_test.yaml | 10 +++++++++- .../serviceaccount-kubernetes-monitoring_test.yaml | 10 +++++++++- pkg/api/validation/dynakube/modules.go | 2 +- pkg/controllers/dynakube/kspm/daemonset/reconciler.go | 1 - 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring.yaml b/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring.yaml index a4192ca841..3a46b5a891 100644 --- a/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring.yaml +++ b/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring.yaml @@ -1,4 +1,4 @@ -{{- if .Values.rbac.activeGate.create }} +{{- if or (eq .Values.rbac.activeGate.create true) (eq .Values.rbac.kspm.create true) }} # Copyright 2021 Dynatrace LLC # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/config/helm/chart/default/templates/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring.yaml b/config/helm/chart/default/templates/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring.yaml index 6116bb5924..49c4f06843 100644 --- a/config/helm/chart/default/templates/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring.yaml +++ b/config/helm/chart/default/templates/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring.yaml @@ -1,4 +1,4 @@ -{{- if .Values.rbac.activeGate.create }} +{{- if or (eq .Values.rbac.activeGate.create true) (eq .Values.rbac.kspm.create true) }} # Copyright 2021 Dynatrace LLC # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring_test.yaml b/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring_test.yaml index 2950220666..54f0431ece 100644 --- a/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring_test.yaml +++ b/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring_test.yaml @@ -149,9 +149,17 @@ tests: kind: ServiceAccount name: dynatrace-kubernetes-monitoring namespace: NAMESPACE + - it: should exist if only kspm is turned on + set: + rbac.activeGate.create: false + rbac.kspm.create: true + asserts: + - hasDocuments: + count: 2 - it: shouldn't exist if turned off set: rbac.activeGate.create: false + rbac.kspm.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring_test.yaml b/config/helm/chart/default/tests/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring_test.yaml index 064948045a..8a08f1fcad 100644 --- a/config/helm/chart/default/tests/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring_test.yaml +++ b/config/helm/chart/default/tests/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring_test.yaml @@ -28,9 +28,17 @@ tests: path: metadata.annotations value: test: test + - it: should exist if only kspm is turned on + set: + rbac.activeGate.create: false + rbac.kspm.create: true + asserts: + - isKind: + of: ServiceAccount - it: shouldn't exist if turned off set: rbac.activeGate.create: false + rbac.kspm.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/pkg/api/validation/dynakube/modules.go b/pkg/api/validation/dynakube/modules.go index 3117319bc0..83526a49bb 100644 --- a/pkg/api/validation/dynakube/modules.go +++ b/pkg/api/validation/dynakube/modules.go @@ -25,7 +25,7 @@ func isOneAgentModuleDisabled(_ context.Context, v *Validator, dk *dynakube.Dyna } func isActiveGateModuleDisabled(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { - if dk.ActiveGate().IsEnabled() && !v.modules.ActiveGate { + if dk.ActiveGate().IsEnabled() && !v.modules.ActiveGate && !v.modules.KSPM { return errorActiveGateModuleDisabled } diff --git a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go index ff06fb3305..87ac0655f4 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go @@ -18,7 +18,6 @@ import ( ) const ( - nameSuffix = "-node-config-collector" serviceAccountName = "dynatrace-node-config-collector" ) From f85df8f8f7fb174496f39f32bc94cba84c8656cd Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 29 Nov 2024 12:30:53 +0100 Subject: [PATCH 015/426] Remove arch param where necessary (#4065) --- pkg/clients/dynatrace/activegate_version.go | 3 +- pkg/clients/dynatrace/agent_version.go | 31 +++++--- pkg/clients/dynatrace/agent_version_test.go | 4 +- pkg/clients/dynatrace/client.go | 2 +- .../dynatrace/dynatrace_client_test.go | 10 +-- pkg/clients/dynatrace/endpoints.go | 24 ++++-- .../internal/statefulset/statefulset.go | 22 +++--- .../internal/statefulset/statefulset_test.go | 29 ++++++- .../dynakube/extension/eec/reconciler_test.go | 15 +--- .../dynakube/extension/eec/statefulset.go | 12 +-- .../dynakube/extension/otel/statefulset.go | 12 +-- .../extension/otel/statefulset_test.go | 14 +--- .../dynakube/kspm/daemonset/reconciler.go | 2 +- .../dynakube/oneagent/daemonset/affinity.go | 26 ++----- .../oneagent/daemonset/affinity_test.go | 77 +++++++++++++------ .../codemodule/installer/url/download.go | 1 - pkg/util/kubeobjects/node/affinity.go | 16 ++-- pkg/util/kubeobjects/node/affinity_test.go | 27 ++++++- pkg/webhook/mutation/pod/oneagent/env.go | 2 +- test/mocks/pkg/clients/dynatrace/client.go | 30 ++++---- 20 files changed, 200 insertions(+), 159 deletions(-) diff --git a/pkg/clients/dynatrace/activegate_version.go b/pkg/clients/dynatrace/activegate_version.go index 639ed3e4df..e7fb579e64 100644 --- a/pkg/clients/dynatrace/activegate_version.go +++ b/pkg/clients/dynatrace/activegate_version.go @@ -3,7 +3,6 @@ package dynatrace import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/arch" "github.com/pkg/errors" ) @@ -13,7 +12,7 @@ func (dtc *dynatraceClient) GetLatestActiveGateVersion(ctx context.Context, os s LatestGatewayVersion string `json:"latestGatewayVersion"` }{} - url := dtc.getLatestActiveGateVersionUrl(os, arch.Arch) + url := dtc.getLatestActiveGateVersionUrl(os) err := dtc.makeRequestAndUnmarshal(ctx, url, dynatracePaaSToken, &response) return response.LatestGatewayVersion, errors.WithStack(err) diff --git a/pkg/clients/dynatrace/agent_version.go b/pkg/clients/dynatrace/agent_version.go index 8f5f05c2a7..38d37b7063 100644 --- a/pkg/clients/dynatrace/agent_version.go +++ b/pkg/clients/dynatrace/agent_version.go @@ -53,23 +53,32 @@ func (dtc *dynatraceClient) GetLatestAgentVersion(ctx context.Context, os, insta return "", errors.New("os or installerType is empty") } - var flavor string - // Default installer type has no "multidistro" flavor - // so the default flavor is always needed in that case + url := dtc.getLatestAgentVersionUrl(os, installerType, determineFlavor(installerType), determineArch(installerType)) + err := dtc.makeRequestAndUnmarshal(ctx, url, dynatracePaaSToken, &response) + + return response.LatestAgentVersion, errors.WithStack(err) +} + +// determineArch gives you the proper arch value, because the OSAgent and ActiveGate images on the tenant-image-registry only have AMD images. +func determineArch(installerType string) string { if installerType == InstallerTypeDefault { - flavor = arch.FlavorDefault - } else { - flavor = arch.Flavor + return "" } - url := dtc.getLatestAgentVersionUrl(os, installerType, flavor, arch.Arch) - err := dtc.makeRequestAndUnmarshal(ctx, url, dynatracePaaSToken, &response) + return arch.Arch +} - return response.LatestAgentVersion, errors.WithStack(err) +// determineFlavor gives you the proper flavor value, because the default installer type has no "multidistro" flavor so the default flavor is always needed in that case. +func determineFlavor(installerType string) string { + if installerType == InstallerTypeDefault { + return arch.FlavorDefault + } + + return arch.Flavor } // GetAgentVersions gets available agent versions for the given OS and installer type. -func (dtc *dynatraceClient) GetAgentVersions(ctx context.Context, os, installerType, flavor, arch string) ([]string, error) { +func (dtc *dynatraceClient) GetAgentVersions(ctx context.Context, os, installerType, flavor string) ([]string, error) { response := struct { AvailableVersions []string `json:"availableVersions"` }{} @@ -78,7 +87,7 @@ func (dtc *dynatraceClient) GetAgentVersions(ctx context.Context, os, installerT return nil, errors.New("os or installerType is empty") } - url := dtc.getAgentVersionsUrl(os, installerType, flavor, arch) + url := dtc.getAgentVersionsUrl(os, installerType, flavor, determineArch(installerType)) err := dtc.makeRequestAndUnmarshal(ctx, url, dynatracePaaSToken, &response) return response.AvailableVersions, errors.WithStack(err) diff --git a/pkg/clients/dynatrace/agent_version_test.go b/pkg/clients/dynatrace/agent_version_test.go index c2c2019b30..94594d6795 100644 --- a/pkg/clients/dynatrace/agent_version_test.go +++ b/pkg/clients/dynatrace/agent_version_test.go @@ -214,7 +214,7 @@ func TestDynatraceClient_GetAgentVersions(t *testing.T) { dynatraceServer, dtc := createTestDynatraceClientWithFunc(t, versionsRequestHandler) defer dynatraceServer.Close() - availableVersions, err := dtc.GetAgentVersions(ctx, OsUnix, InstallerTypePaaS, "", "") + availableVersions, err := dtc.GetAgentVersions(ctx, OsUnix, InstallerTypePaaS, "") require.NoError(t, err) assert.Len(t, availableVersions, 4) @@ -227,7 +227,7 @@ func TestDynatraceClient_GetAgentVersions(t *testing.T) { dynatraceServer, dtc := createTestDynatraceClientWithFunc(t, errorHandler) defer dynatraceServer.Close() - availableVersions, err := dtc.GetAgentVersions(ctx, OsUnix, InstallerTypePaaS, "", "") + availableVersions, err := dtc.GetAgentVersions(ctx, OsUnix, InstallerTypePaaS, "") require.EqualError(t, err, "dynatrace server error 400: test-error") assert.Empty(t, availableVersions) diff --git a/pkg/clients/dynatrace/client.go b/pkg/clients/dynatrace/client.go index b4b3e36e8d..d51f0c7873 100644 --- a/pkg/clients/dynatrace/client.go +++ b/pkg/clients/dynatrace/client.go @@ -44,7 +44,7 @@ type Client interface { // GetAgentVersions on success returns an array of versions that can be used with GetAgent to // download a specific agent version - GetAgentVersions(ctx context.Context, os, installerType, flavor, arch string) ([]string, error) + GetAgentVersions(ctx context.Context, os, installerType, flavor string) ([]string, error) GetOneAgentConnectionInfo(ctx context.Context) (OneAgentConnectionInfo, error) diff --git a/pkg/clients/dynatrace/dynatrace_client_test.go b/pkg/clients/dynatrace/dynatrace_client_test.go index 6596d79c61..bd95a620ff 100644 --- a/pkg/clients/dynatrace/dynatrace_client_test.go +++ b/pkg/clients/dynatrace/dynatrace_client_test.go @@ -17,19 +17,19 @@ import ( var ( flavorUri = fmt.Sprintf("/v1/deployment/installer/agent/%s/%s/latest/metainfo?bitness=64&flavor=%s&arch=%s", - OsUnix, InstallerTypeDefault, arch.FlavorDefault+"a", arch.Arch) + OsUnix, InstallerTypePaaS, arch.FlavorMultidistro+"a", arch.Arch) flavourUriResponse = `{"error":{"code":400,"message":"Constraints violated.","constraintViolations":[{"path":"flavor","message":"'defaulta' must be any of [default, multidistro, musl]","parameterLocation":"QUERY","location":null}]}}` archUri = fmt.Sprintf("/v1/deployment/installer/agent/%s/%s/latest/metainfo?bitness=64&flavor=%s&arch=%s", - OsUnix, InstallerTypeDefault, arch.FlavorDefault, arch.Arch+"a") + OsUnix, InstallerTypePaaS, arch.FlavorMultidistro, arch.Arch+"a") archUriResponse = `{"error":{"code":400,"message":"Constraints violated.","constraintViolations":[{"path":"arch","message":"'x86a' must be any of [all, arm, ppc, ppcle, s390, sparc, x86, zos]","parameterLocation":"QUERY","location":null}]}}` flavorArchUri = fmt.Sprintf("/v1/deployment/installer/agent/%s/%s/latest/metainfo?bitness=64&flavor=%s&arch=%s", - OsUnix, InstallerTypeDefault, arch.FlavorDefault+"a", arch.Arch+"a") + OsUnix, InstallerTypePaaS, arch.FlavorMultidistro+"a", arch.Arch+"a") flavourArchUriResponse = `{"error":{"code":400,"message":"Constraints violated.","constraintViolations":[{"path":"flavor","message":"'defaulta' must be any of [default, multidistro, musl]","parameterLocation":"QUERY","location":null},{"path":"arch","message":"'x86a' must be any of [all, arm, ppc, ppcle, s390, sparc, x86, zos]","parameterLocation":"QUERY","location":null}]}}` oaLatestMetainfoUri = fmt.Sprintf("/v1/deployment/installer/agent/%s/%s/latest/metainfo?bitness=64&flavor=%s&arch=%s", - "aix", InstallerTypeDefault, arch.FlavorDefault, arch.Arch) + "aix", InstallerTypePaaS, arch.FlavorMultidistro, arch.Arch) oaLatestMetainfoUriResponse = `{"error":{"code":404,"message":"non supported architecture on OS "}}` ) @@ -315,7 +315,7 @@ func testServerErrors(t *testing.T) { }) t.Run("GetLatestAgentVersion - invalid architecture", func(t *testing.T) { - _, err = dtc.GetLatestAgentVersion(context.Background(), "aix", InstallerTypeDefault) + _, err = dtc.GetLatestAgentVersion(context.Background(), "aix", InstallerTypePaaS) assert.Equal(t, "dynatrace server error 404: non supported architecture on OS ", err.Error()) }) } diff --git a/pkg/clients/dynatrace/endpoints.go b/pkg/clients/dynatrace/endpoints.go index 7b56d8b5d9..387ad10dac 100644 --- a/pkg/clients/dynatrace/endpoints.go +++ b/pkg/clients/dynatrace/endpoints.go @@ -17,18 +17,28 @@ func (dtc *dynatraceClient) getLatestAgentUrl(os, installerType, flavor, arch st } func (dtc *dynatraceClient) getLatestAgentVersionUrl(os, installerType, flavor, arch string) string { - return fmt.Sprintf("%s/v1/deployment/installer/agent/%s/%s/latest/metainfo?bitness=64&flavor=%s&arch=%s", - dtc.url, os, installerType, flavor, arch) + if arch != "" { + return fmt.Sprintf("%s/v1/deployment/installer/agent/%s/%s/latest/metainfo?bitness=64&flavor=%s&arch=%s", + dtc.url, os, installerType, flavor, arch) + } + + return fmt.Sprintf("%s/v1/deployment/installer/agent/%s/%s/latest/metainfo?bitness=64&flavor=%s", + dtc.url, os, installerType, flavor) } -func (dtc *dynatraceClient) getLatestActiveGateVersionUrl(os, arch string) string { - return fmt.Sprintf("%s/v1/deployment/installer/gateway/%s/latest/metainfo?arch=%s", - dtc.url, os, arch) +func (dtc *dynatraceClient) getLatestActiveGateVersionUrl(os string) string { + return fmt.Sprintf("%s/v1/deployment/installer/gateway/%s/latest/metainfo", + dtc.url, os) } func (dtc *dynatraceClient) getAgentVersionsUrl(os, installerType, flavor, arch string) string { - return fmt.Sprintf("%s/v1/deployment/installer/agent/versions/%s/%s?flavor=%s&arch=%s", - dtc.url, os, installerType, flavor, arch) + if arch != "" { + return fmt.Sprintf("%s/v1/deployment/installer/agent/versions/%s/%s?flavor=%s&arch=%s", + dtc.url, os, installerType, flavor, arch) + } + + return fmt.Sprintf("%s/v1/deployment/installer/agent/versions/%s/%s?flavor=%s", + dtc.url, os, installerType, flavor) } func (dtc *dynatraceClient) getOneAgentConnectionInfoUrl() string { diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index cb7dafd9b0..472460a291 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -3,6 +3,7 @@ package statefulset import ( "strconv" + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" @@ -116,7 +117,7 @@ func (statefulSetBuilder Builder) addTemplateSpec(sts *appsv1.StatefulSet) { Containers: statefulSetBuilder.buildBaseContainer(), NodeSelector: statefulSetBuilder.capability.Properties().NodeSelector, ServiceAccountName: statefulSetBuilder.dynakube.ActiveGate().GetServiceAccountName(), - Affinity: nodeAffinity(), + Affinity: statefulSetBuilder.nodeAffinity(), Tolerations: statefulSetBuilder.capability.Properties().Tolerations, SecurityContext: &corev1.PodSecurityContext{ SeccompProfile: &corev1.SeccompProfile{ @@ -222,16 +223,13 @@ func (statefulSetBuilder Builder) buildCommonEnvs() []corev1.EnvVar { return statefulSetBuilder.envMap.AsEnvVars() } -func nodeAffinity() *corev1.Affinity { - return &corev1.Affinity{ - NodeAffinity: &corev1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ - NodeSelectorTerms: []corev1.NodeSelectorTerm{ - { - MatchExpressions: node.AffinityNodeRequirementForSupportedArches(), - }, - }, - }, - }, +func (statefulSetBuilder Builder) nodeAffinity() *corev1.Affinity { + var affinity corev1.Affinity + if statefulSetBuilder.dynakube.Status.ActiveGate.Source == status.TenantRegistryVersionSource || statefulSetBuilder.dynakube.Status.ActiveGate.Source == status.CustomVersionVersionSource { + affinity = node.AMDOnlyAffinity() + } else { + affinity = node.Affinity() } + + return &affinity } diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index 09fad29d7e..63bd7a3c52 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -86,7 +86,34 @@ func TestGetBaseObjectMeta(t *testing.T) { require.NotEmpty(t, sts.Spec.Template.Labels) assert.Equal(t, expectedTemplateAnnotations, sts.Spec.Template.Annotations) }) - t.Run("has default node affinity", func(t *testing.T) { + t.Run("has default(tenant-registry) node affinity", func(t *testing.T) { + dk := getTestDynakube() + dk.Status.ActiveGate.VersionStatus.Source = status.TenantRegistryVersionSource + multiCapability := capability.NewMultiCapability(&dk) + builder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) + sts, _ := builder.CreateStatefulSet(nil) + expectedNodeSelectorTerms := []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "kubernetes.io/arch", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"amd64"}, + }, + { + Key: "kubernetes.io/os", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"linux"}, + }, + }, + }} + + require.NotEmpty(t, sts.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms) + assert.Contains(t, sts.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, expectedNodeSelectorTerms[0]) + }) + t.Run("has none tenant-registry node affinity", func(t *testing.T) { + dk := getTestDynakube() + dk.Status.ActiveGate.VersionStatus.Source = status.CustomImageVersionSource multiCapability := capability.NewMultiCapability(&dk) builder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) sts, _ := builder.CreateStatefulSet(nil) diff --git a/pkg/controllers/dynakube/extension/eec/reconciler_test.go b/pkg/controllers/dynakube/extension/eec/reconciler_test.go index 9c9cdd3641..90c16302e0 100644 --- a/pkg/controllers/dynakube/extension/eec/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/eec/reconciler_test.go @@ -462,19 +462,8 @@ func TestAffinity(t *testing.T) { statefulSet := getStatefulset(t, dk) - expectedAffinity := &corev1.Affinity{ - NodeAffinity: &corev1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ - NodeSelectorTerms: []corev1.NodeSelectorTerm{ - { - MatchExpressions: node.AffinityNodeRequirementForSupportedArches(), - }, - }, - }, - }, - } - - assert.Equal(t, expectedAffinity, statefulSet.Spec.Template.Spec.Affinity) + expectedAffinity := node.Affinity() + assert.Equal(t, expectedAffinity, *statefulSet.Spec.Template.Spec.Affinity) }) } diff --git a/pkg/controllers/dynakube/extension/eec/statefulset.go b/pkg/controllers/dynakube/extension/eec/statefulset.go index 19c168b918..7421b3982a 100644 --- a/pkg/controllers/dynakube/extension/eec/statefulset.go +++ b/pkg/controllers/dynakube/extension/eec/statefulset.go @@ -160,17 +160,7 @@ func buildAppLabels(dynakubeName string) *labels.AppLabels { } func buildAffinity() corev1.Affinity { - return corev1.Affinity{ - NodeAffinity: &corev1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ - NodeSelectorTerms: []corev1.NodeSelectorTerm{ - { - MatchExpressions: node.AffinityNodeRequirementForSupportedArches(), - }, - }, - }, - }, - } + return node.Affinity() } func setImagePullSecrets(imagePullSecrets []corev1.LocalObjectReference) func(o *appsv1.StatefulSet) { diff --git a/pkg/controllers/dynakube/extension/otel/statefulset.go b/pkg/controllers/dynakube/extension/otel/statefulset.go index 7f4a4dc2df..10b0ce421b 100644 --- a/pkg/controllers/dynakube/extension/otel/statefulset.go +++ b/pkg/controllers/dynakube/extension/otel/statefulset.go @@ -245,17 +245,7 @@ func buildAppLabels(dkName string) *labels.AppLabels { func buildAffinity() corev1.Affinity { // TODO: implement new attributes in CR dk.Spec.Templates.OpenTelemetryCollector.Affinity // otherwise to use defaults ones - return corev1.Affinity{ - NodeAffinity: &corev1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ - NodeSelectorTerms: []corev1.NodeSelectorTerm{ - { - MatchExpressions: node.AffinityNodeRequirementForSupportedArches(), - }, - }, - }, - }, - } + return node.Affinity() } func setImagePullSecrets(imagePullSecrets []corev1.LocalObjectReference) func(o *appsv1.StatefulSet) { diff --git a/pkg/controllers/dynakube/extension/otel/statefulset_test.go b/pkg/controllers/dynakube/extension/otel/statefulset_test.go index 9718bf6097..a70cdc6836 100644 --- a/pkg/controllers/dynakube/extension/otel/statefulset_test.go +++ b/pkg/controllers/dynakube/extension/otel/statefulset_test.go @@ -268,19 +268,9 @@ func TestAffinity(t *testing.T) { dk := getTestDynakube() statefulSet := getStatefulset(t, dk) - expectedAffinity := &corev1.Affinity{ - NodeAffinity: &corev1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ - NodeSelectorTerms: []corev1.NodeSelectorTerm{ - { - MatchExpressions: node.AffinityNodeRequirementForSupportedArches(), - }, - }, - }, - }, - } + expectedAffinity := node.Affinity() - assert.Equal(t, expectedAffinity, statefulSet.Spec.Template.Spec.Affinity) + assert.Equal(t, expectedAffinity, *statefulSet.Spec.Template.Spec.Affinity) }) } diff --git a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go index 87ac0655f4..7d36529e62 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go @@ -89,7 +89,7 @@ func (r *Reconciler) generateDaemonSet() (*appsv1.DaemonSet, error) { daemonset.SetAllLabels(labels.BuildLabels(), labels.BuildMatchLabels(), labels.BuildLabels(), r.dk.KSPM().Labels), daemonset.SetAllAnnotations(r.dk.KSPM().Annotations, templateAnnotations), daemonset.SetServiceAccount(serviceAccountName), - daemonset.SetAffinity(node.Affinity()), + daemonset.SetAffinity(node.AMDOnlyAffinity()), daemonset.SetPriorityClass(r.dk.KSPM().PriorityClassName), daemonset.SetTolerations(r.dk.KSPM().Tolerations), daemonset.SetPullSecret(r.dk.ImagePullSecretReferences()...), diff --git a/pkg/controllers/dynakube/oneagent/daemonset/affinity.go b/pkg/controllers/dynakube/oneagent/daemonset/affinity.go index d63b098614..8025aaca7e 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/affinity.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/affinity.go @@ -1,30 +1,18 @@ package daemonset import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" corev1 "k8s.io/api/core/v1" ) func (b *builder) affinity() *corev1.Affinity { - return &corev1.Affinity{ - NodeAffinity: &corev1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ - NodeSelectorTerms: b.affinityNodeSelectorTerms(), - }, - }, - } -} - -func (b *builder) affinityNodeSelectorTerms() []corev1.NodeSelectorTerm { - nodeSelectorTerms := []corev1.NodeSelectorTerm{ - kubernetesArchOsSelectorTerm(), + var affinity corev1.Affinity + if b.dk.Status.OneAgent.VersionStatus.Source == status.TenantRegistryVersionSource || b.dk.Status.OneAgent.VersionStatus.Source == status.CustomVersionVersionSource { + affinity = node.AMDOnlyAffinity() + } else { + affinity = node.Affinity() } - return nodeSelectorTerms -} - -func kubernetesArchOsSelectorTerm() corev1.NodeSelectorTerm { - return corev1.NodeSelectorTerm{ - MatchExpressions: node.AffinityNodeRequirementForSupportedArches(), - } + return &affinity } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/affinity_test.go b/pkg/controllers/dynakube/oneagent/daemonset/affinity_test.go index e16e3096ab..4019c068da 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/affinity_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/affinity_test.go @@ -3,39 +3,66 @@ package daemonset import ( "testing" + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" ) func TestAffinity(t *testing.T) { - dsBuilder := builder{} - affinity := dsBuilder.affinity() - assert.NotContains(t, affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, corev1.NodeSelectorTerm{ - MatchExpressions: []corev1.NodeSelectorRequirement{ - { - Key: "beta.kubernetes.io/arch", - Operator: corev1.NodeSelectorOpIn, - Values: []string{"amd64", "arm64", "ppc64le", "s390x"}, + t.Run("none tenant-registry DynaKube has all the architectures", func(t *testing.T) { + dk := dynakube.DynaKube{} + dk.Status.OneAgent.VersionStatus.Source = status.CustomImageVersionSource + dsBuilder := builder{dk: &dk} + affinity := dsBuilder.affinity() + assert.NotContains(t, affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, corev1.NodeSelectorTerm{ + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "beta.kubernetes.io/arch", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"amd64", "arm64", "ppc64le", "s390x"}, + }, + { + Key: "beta.kubernetes.io/os", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"linux"}, + }, }, - { - Key: "beta.kubernetes.io/os", - Operator: corev1.NodeSelectorOpIn, - Values: []string{"linux"}, + }) + assert.Contains(t, affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, corev1.NodeSelectorTerm{ + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "kubernetes.io/arch", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"amd64", "arm64", "ppc64le", "s390x"}, + }, + { + Key: "kubernetes.io/os", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"linux"}, + }, }, - }, + }) }) - assert.Contains(t, affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, corev1.NodeSelectorTerm{ - MatchExpressions: []corev1.NodeSelectorRequirement{ - { - Key: "kubernetes.io/arch", - Operator: corev1.NodeSelectorOpIn, - Values: []string{"amd64", "arm64", "ppc64le", "s390x"}, - }, - { - Key: "kubernetes.io/os", - Operator: corev1.NodeSelectorOpIn, - Values: []string{"linux"}, + + t.Run("tenant-registry DynaKube has only AMD architectures", func(t *testing.T) { + dk := dynakube.DynaKube{} + dk.Status.OneAgent.VersionStatus.Source = status.TenantRegistryVersionSource + dsBuilder := builder{dk: &dk} + affinity := dsBuilder.affinity() + assert.Contains(t, affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, corev1.NodeSelectorTerm{ + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "kubernetes.io/arch", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"amd64"}, + }, + { + Key: "kubernetes.io/os", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"linux"}, + }, }, - }, + }) }) } diff --git a/pkg/injection/codemodule/installer/url/download.go b/pkg/injection/codemodule/installer/url/download.go index 090261bb80..061b7cd777 100644 --- a/pkg/injection/codemodule/installer/url/download.go +++ b/pkg/injection/codemodule/installer/url/download.go @@ -58,7 +58,6 @@ func (installer Installer) downloadOneAgentWithVersion(ctx context.Context, tmpF installer.props.Os, installer.props.Type, installer.props.Flavor, - installer.props.Arch, ) if getVersionsError != nil { log.Info("failed to get available versions", "err", getVersionsError) diff --git a/pkg/util/kubeobjects/node/affinity.go b/pkg/util/kubeobjects/node/affinity.go index e74078785d..db39995353 100644 --- a/pkg/util/kubeobjects/node/affinity.go +++ b/pkg/util/kubeobjects/node/affinity.go @@ -11,12 +11,22 @@ const ( ) func Affinity() corev1.Affinity { + return AffinityForArches(arch.AMDImage, arch.ARMImage, arch.PPCLEImage, arch.S390Image) +} + +// AMDOnlyAffinity provides an affinity that will only allow deployment on AMD64 nodes. +// This is manly needed for the Dynatrace tenant-registry as it only has AMD64 images. +func AMDOnlyAffinity() corev1.Affinity { + return AffinityForArches(arch.AMDImage) +} + +func AffinityForArches(arches ...string) corev1.Affinity { return corev1.Affinity{ NodeAffinity: &corev1.NodeAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ NodeSelectorTerms: []corev1.NodeSelectorTerm{ { - MatchExpressions: AffinityNodeRequirementForSupportedArches(), + MatchExpressions: affinityNodeRequirementsForArches(arches...), }, }, }, @@ -24,10 +34,6 @@ func Affinity() corev1.Affinity { } } -func AffinityNodeRequirementForSupportedArches() []corev1.NodeSelectorRequirement { - return affinityNodeRequirementsForArches(arch.AMDImage, arch.ARMImage, arch.PPCLEImage, arch.S390Image) -} - func affinityNodeRequirementsForArches(arches ...string) []corev1.NodeSelectorRequirement { return []corev1.NodeSelectorRequirement{ { diff --git a/pkg/util/kubeobjects/node/affinity_test.go b/pkg/util/kubeobjects/node/affinity_test.go index b5fdd187c5..041a8b6c40 100644 --- a/pkg/util/kubeobjects/node/affinity_test.go +++ b/pkg/util/kubeobjects/node/affinity_test.go @@ -5,12 +5,33 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/arch" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" ) -func TestAffinityNodeRequirement(t *testing.T) { - assert.Equal(t, AffinityNodeRequirementForSupportedArches(), affinityNodeRequirementsForArches(arch.AMDImage, arch.ARMImage, arch.PPCLEImage, arch.S390Image)) - assert.Contains(t, AffinityNodeRequirementForSupportedArches(), linuxRequirement()) +func TestAffinity(t *testing.T) { + affinity := Affinity() + + require.NotNil(t, affinity) + require.NotNil(t, affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution) + require.Len(t, affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, 1) + + matchExpression := affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions + assert.Equal(t, matchExpression, affinityNodeRequirementsForArches(arch.AMDImage, arch.ARMImage, arch.PPCLEImage, arch.S390Image)) + assert.Contains(t, matchExpression, linuxRequirement()) +} + +func TestAffinityForArches(t *testing.T) { + expectedArches := []string{"arch1", "arch2", "arch3"} + affinity := AffinityForArches(expectedArches...) + + require.NotNil(t, affinity) + require.NotNil(t, affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution) + require.Len(t, affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, 1) + + matchExpression := affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions + assert.Equal(t, matchExpression, affinityNodeRequirementsForArches(expectedArches...)) + assert.Contains(t, matchExpression, linuxRequirement()) } func linuxRequirement() corev1.NodeSelectorRequirement { diff --git a/pkg/webhook/mutation/pod/oneagent/env.go b/pkg/webhook/mutation/pod/oneagent/env.go index bfc55f6c81..9bf9a32ec9 100644 --- a/pkg/webhook/mutation/pod/oneagent/env.go +++ b/pkg/webhook/mutation/pod/oneagent/env.go @@ -68,7 +68,7 @@ func addVersionDetectionEnvs(container *corev1.Container, labelMapping VersionLa func addInstallerInitEnvs(initContainer *corev1.Container, installer installerInfo) { initContainer.Env = append(initContainer.Env, - corev1.EnvVar{Name: consts.AgentInstallerFlavorEnv, Value: installer.flavor}, + corev1.EnvVar{Name: consts.AgentInstallerFlavorEnv, Value: installer.flavor}, // TODO: is this needed corev1.EnvVar{Name: consts.AgentInstallerTechEnv, Value: installer.technologies}, corev1.EnvVar{Name: consts.AgentInstallPathEnv, Value: installer.installPath}, corev1.EnvVar{Name: consts.AgentInstallerUrlEnv, Value: installer.installerURL}, diff --git a/test/mocks/pkg/clients/dynatrace/client.go b/test/mocks/pkg/clients/dynatrace/client.go index 0bb92f83d0..8be5525119 100644 --- a/test/mocks/pkg/clients/dynatrace/client.go +++ b/test/mocks/pkg/clients/dynatrace/client.go @@ -9,7 +9,6 @@ import ( dynatrace "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" logmonitoring "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - mock "github.com/stretchr/testify/mock" ) @@ -370,9 +369,9 @@ func (_c *Client_GetAgent_Call) RunAndReturn(run func(context.Context, string, s return _c } -// GetAgentVersions provides a mock function with given fields: ctx, os, installerType, flavor, arch -func (_m *Client) GetAgentVersions(ctx context.Context, os string, installerType string, flavor string, arch string) ([]string, error) { - ret := _m.Called(ctx, os, installerType, flavor, arch) +// GetAgentVersions provides a mock function with given fields: ctx, os, installerType, flavor +func (_m *Client) GetAgentVersions(ctx context.Context, os string, installerType string, flavor string) ([]string, error) { + ret := _m.Called(ctx, os, installerType, flavor) if len(ret) == 0 { panic("no return value specified for GetAgentVersions") @@ -380,19 +379,19 @@ func (_m *Client) GetAgentVersions(ctx context.Context, os string, installerType var r0 []string var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string) ([]string, error)); ok { - return rf(ctx, os, installerType, flavor, arch) + if rf, ok := ret.Get(0).(func(context.Context, string, string, string) ([]string, error)); ok { + return rf(ctx, os, installerType, flavor) } - if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string) []string); ok { - r0 = rf(ctx, os, installerType, flavor, arch) + if rf, ok := ret.Get(0).(func(context.Context, string, string, string) []string); ok { + r0 = rf(ctx, os, installerType, flavor) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]string) } } - if rf, ok := ret.Get(1).(func(context.Context, string, string, string, string) error); ok { - r1 = rf(ctx, os, installerType, flavor, arch) + if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok { + r1 = rf(ctx, os, installerType, flavor) } else { r1 = ret.Error(1) } @@ -410,14 +409,13 @@ type Client_GetAgentVersions_Call struct { // - os string // - installerType string // - flavor string -// - arch string -func (_e *Client_Expecter) GetAgentVersions(ctx interface{}, os interface{}, installerType interface{}, flavor interface{}, arch interface{}) *Client_GetAgentVersions_Call { - return &Client_GetAgentVersions_Call{Call: _e.mock.On("GetAgentVersions", ctx, os, installerType, flavor, arch)} +func (_e *Client_Expecter) GetAgentVersions(ctx interface{}, os interface{}, installerType interface{}, flavor interface{}) *Client_GetAgentVersions_Call { + return &Client_GetAgentVersions_Call{Call: _e.mock.On("GetAgentVersions", ctx, os, installerType, flavor)} } -func (_c *Client_GetAgentVersions_Call) Run(run func(ctx context.Context, os string, installerType string, flavor string, arch string)) *Client_GetAgentVersions_Call { +func (_c *Client_GetAgentVersions_Call) Run(run func(ctx context.Context, os string, installerType string, flavor string)) *Client_GetAgentVersions_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(string), args[4].(string)) + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(string)) }) return _c } @@ -427,7 +425,7 @@ func (_c *Client_GetAgentVersions_Call) Return(_a0 []string, _a1 error) *Client_ return _c } -func (_c *Client_GetAgentVersions_Call) RunAndReturn(run func(context.Context, string, string, string, string) ([]string, error)) *Client_GetAgentVersions_Call { +func (_c *Client_GetAgentVersions_Call) RunAndReturn(run func(context.Context, string, string, string) ([]string, error)) *Client_GetAgentVersions_Call { _c.Call.Return(run) return _c } From e24d46cfe8e8183a16d26439ea322d05e825e79e Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Mon, 2 Dec 2024 09:05:11 +0100 Subject: [PATCH 016/426] Consider logmonitoring in the node-selector check (#4124) (#4130) --- .../validation/dynakube/logmonitoring_test.go | 23 +++-- pkg/api/validation/dynakube/oneagent.go | 16 +++- pkg/api/validation/dynakube/oneagent_test.go | 89 +++++++++++++++++-- 3 files changed, 115 insertions(+), 13 deletions(-) diff --git a/pkg/api/validation/dynakube/logmonitoring_test.go b/pkg/api/validation/dynakube/logmonitoring_test.go index 5a906ed598..9d87857f3c 100644 --- a/pkg/api/validation/dynakube/logmonitoring_test.go +++ b/pkg/api/validation/dynakube/logmonitoring_test.go @@ -11,33 +11,44 @@ import ( func TestIgnoredLogMonitoringTemplate(t *testing.T) { t.Run("no warning if logMonitoring template section is empty", func(t *testing.T) { - dk := createStandaloneLogMonitoringDynakube(testName, "") + dk := createStandaloneLogMonitoringDynakube(testName, testApiUrl, "") dk.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} + dk.Spec.Templates.LogMonitoring = nil assertAllowedWithoutWarnings(t, dk) }) t.Run("warning if logMonitoring template section is not empty", func(t *testing.T) { - dk := createStandaloneLogMonitoringDynakube(testName, "something") + dk := createStandaloneLogMonitoringDynakube(testName, testApiUrl, "something") dk.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} assertAllowedWithWarnings(t, 1, dk) }) } -func createStandaloneLogMonitoringDynakube(name, nodeSelector string) *dynakube.DynaKube { +func createStandaloneLogMonitoringDynakube(name, apiUrl, nodeSelector string) *dynakube.DynaKube { dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: testNamespace, }, Spec: dynakube.DynaKubeSpec{ - APIURL: testApiUrl, + APIURL: apiUrl, LogMonitoring: &logmonitoring.Spec{}, + Templates: dynakube.TemplatesSpec{ + LogMonitoring: &logmonitoring.TemplateSpec{ + ImageRef: image.Ref{ + Repository: "repo/image", + Tag: "version", + }, + }, + }, }, } if nodeSelector != "" { - dk.Spec.Templates.LogMonitoring = &logmonitoring.TemplateSpec{ - NodeSelector: map[string]string{"node": nodeSelector}, + if dk.Spec.Templates.LogMonitoring == nil { + dk.Spec.Templates.LogMonitoring = &logmonitoring.TemplateSpec{} } + + dk.Spec.Templates.LogMonitoring.NodeSelector = map[string]string{"node": nodeSelector} } return dk diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index e78f015591..8df06d5cfb 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -60,7 +60,7 @@ func conflictingOneAgentConfiguration(_ context.Context, _ *Validator, dk *dynak } func conflictingOneAgentNodeSelector(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { - if !dk.NeedsOneAgent() { + if !dk.NeedsOneAgent() && !dk.LogMonitoring().IsStandalone() { return "" } @@ -79,7 +79,7 @@ func conflictingOneAgentNodeSelector(ctx context.Context, dv *Validator, dk *dyn continue } - if item.NeedsOneAgent() { + if hasLogMonitoringSelectorConflict(dk, &item) || hasOneAgentSelectorConflict(dk, &item) { if hasConflictingMatchLabels(oneAgentNodeSelector, item.OneAgentNodeSelector()) { log.Info("requested dynakube has conflicting OneAgent nodeSelector", "name", dk.Name, "namespace", dk.Namespace) @@ -95,6 +95,18 @@ func conflictingOneAgentNodeSelector(ctx context.Context, dv *Validator, dk *dyn return "" } +func hasLogMonitoringSelectorConflict(dk1, dk2 *dynakube.DynaKube) bool { + return dk1.LogMonitoring().IsStandalone() && dk1.ApiUrl() == dk2.ApiUrl() && + (dk2.NeedsOneAgent() || dk2.LogMonitoring().IsStandalone()) && + hasConflictingMatchLabels(dk1.OneAgentNodeSelector(), dk2.OneAgentNodeSelector()) +} + +func hasOneAgentSelectorConflict(dk1, dk2 *dynakube.DynaKube) bool { + return dk1.NeedsOneAgent() && + (dk2.NeedsOneAgent() || dk2.LogMonitoring().IsStandalone() && dk1.ApiUrl() == dk2.ApiUrl()) && + hasConflictingMatchLabels(dk1.OneAgentNodeSelector(), dk2.OneAgentNodeSelector()) +} + func mapKeysToString(m map[string]bool, sep string) string { keys := make([]string, 0, len(m)) for k := range m { diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index a526d35a2e..5359077cd5 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -75,7 +75,28 @@ func TestConflictingOneAgentConfiguration(t *testing.T) { } func TestConflictingNodeSelector(t *testing.T) { - t.Run("valid dynakube specs", func(t *testing.T) { + newCloudNativeDynakube := func(name, apiUrl, nodeSelectorValue string) *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: apiUrl, + OneAgent: dynakube.OneAgentSpec{ + CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ + HostInjectSpec: dynakube.HostInjectSpec{ + NodeSelector: map[string]string{ + "node": nodeSelectorValue, + }, + }, + }, + }, + }, + } + } + + t.Run("valid dynakube specs - 2 host-monitoring DK, different nodes", func(t *testing.T) { assertAllowedWithoutWarnings(t, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, @@ -106,7 +127,8 @@ func TestConflictingNodeSelector(t *testing.T) { }, }, }) - + }) + t.Run("valid dynakube specs - 1 cloud-native + 1 host-monitoring DK, different nodes", func(t *testing.T) { assertAllowedWithoutWarnings(t, &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ @@ -140,13 +162,37 @@ func TestConflictingNodeSelector(t *testing.T) { }, }) }) - t.Run(`invalid dynakube specs`, func(t *testing.T) { + + t.Run("valid dynakube specs - 1 cloud-native + 1 log-monitoring DK, same tenant, different nodes", func(t *testing.T) { + api1 := "https://f1.q.d.n/api" + + assertAllowedWithoutWarnings(t, newCloudNativeDynakube("dk1", api1, "1"), + createStandaloneLogMonitoringDynakube("dk-lm", api1, "12")) + }) + + t.Run("valid dynakube specs - 1 cloud-native + 1 log-monitoring DK, different tenant, same nodes", func(t *testing.T) { + api1 := "https://f1.q.d.n/api" + api2 := "https://f2.q.d.n/api" + assertAllowedWithoutWarnings(t, newCloudNativeDynakube("dk1", api1, "1"), + createStandaloneLogMonitoringDynakube("dk-lm", api2, "1")) + }) + + t.Run("valid dynakube specs - 2 log-monitoring DK, different tenant, same nodes", func(t *testing.T) { + api1 := "https://f1.q.d.n/api" + api2 := "https://f2.q.d.n/api" + assertAllowedWithoutWarnings(t, createStandaloneLogMonitoringDynakube("dk1", api1, "1"), + createStandaloneLogMonitoringDynakube("dk-lm", api2, "1")) + }) + + t.Run("invalid dynakube specs - 1 cloud-native + 1 host-monitoring DK, SAME nodes, different tenant", func(t *testing.T) { + api1 := "https://f1.q.d.n/api" + api2 := "https://f2.q.d.n/api" assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, "conflicting-dk")}, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ - APIURL: testApiUrl, + APIURL: api1, OneAgent: dynakube.OneAgentSpec{ CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ HostInjectSpec: dynakube.HostInjectSpec{ @@ -164,7 +210,7 @@ func TestConflictingNodeSelector(t *testing.T) { Namespace: testNamespace, }, Spec: dynakube.DynaKubeSpec{ - APIURL: testApiUrl, + APIURL: api2, OneAgent: dynakube.OneAgentSpec{ HostMonitoring: &dynakube.HostInjectSpec{ NodeSelector: map[string]string{ @@ -174,6 +220,39 @@ func TestConflictingNodeSelector(t *testing.T) { }, }, }) + t.Run("invalid dynakube specs - 1 cloud-native + 1 log-monitoring DK, same tenant, same nodes", func(t *testing.T) { + api1 := "https://f1.q.d.n/api" + + assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, "dk-lm")}, + newCloudNativeDynakube("dk-cm", api1, "1"), + createStandaloneLogMonitoringDynakube("dk-lm", api1, "1")) + }) + t.Run("multiple invalid dynakube specs - 2 cloud-native + 1 log-monitoring DK, same tenant, same nodes", func(t *testing.T) { + api1 := "https://f1.q.d.n/api" + + assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, ""), "dk-lm", "dk-cm2"}, + newCloudNativeDynakube("dk-cm1", api1, "1"), + createStandaloneLogMonitoringDynakube("dk-lm", api1, ""), + newCloudNativeDynakube("dk-cm2", api1, "1")) + }) + + t.Run("invalid dynakube specs - 1 log-monitoring DK + 1 cloud-native, same tenant, same nodes", func(t *testing.T) { + api1 := "https://f1.q.d.n/api" + + assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, "dk-cn")}, + createStandaloneLogMonitoringDynakube("dk-lm", api1, "1"), + newCloudNativeDynakube("dk-cn", api1, "1")) + }) + + t.Run("some invalid dynakube specs - 2 log-monitoring DK + 1 cloud-native, 2 tenants, same nodes", func(t *testing.T) { + api1 := "https://f1.q.d.n/api" + api2 := "https://f2.q.d.n/api" + + assertDenied(t, []string{fmt.Sprintf(errorNodeSelectorConflict, "dk-lm2")}, + createStandaloneLogMonitoringDynakube("dk-lm1", api1, "1"), + newCloudNativeDynakube("dk-cm1", api2, "1"), + createStandaloneLogMonitoringDynakube("dk-lm2", api1, "1")) + }) }) } From 4cad134bf6a21f51952b14d8fae18744e9c2ce9a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:50:34 +0000 Subject: [PATCH 017/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1733126338 (main) (#4134) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c85d6e9a7d..985ca80df3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS=" go build -tags "${GO_BUILD_TAGS}" -trimpath -ldflags="${GO_LINKER_ARGS}" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ -FROM registry.access.redhat.com/ubi9-micro:9.5-1731934928@sha256:31f00ba1d79523e182624c96e05b2f5ca66ea35d64959d84acdc8b670429415f AS base +FROM registry.access.redhat.com/ubi9-micro:9.5-1733126338@sha256:a410623c2b8e9429f9606af821be0231fef2372bd0f5f853fbe9743a0ddf7b34 AS base FROM registry.access.redhat.com/ubi9:9.5-1732804088@sha256:1057dab827c782abcfb9bda0c3900c0966b5066e671d54976a7bcb3a2d1a5e53 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From 02c26a2f55546f7aca5dfd0b54010a2eeca611d9 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Mon, 2 Dec 2024 13:52:49 +0100 Subject: [PATCH 018/426] Remove flaky ARM test (#4132) (#4136) --- pkg/clients/dynatrace/agent_version.go | 2 +- pkg/clients/dynatrace/dynatrace_client_test.go | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/pkg/clients/dynatrace/agent_version.go b/pkg/clients/dynatrace/agent_version.go index 38d37b7063..78a973ab0d 100644 --- a/pkg/clients/dynatrace/agent_version.go +++ b/pkg/clients/dynatrace/agent_version.go @@ -69,7 +69,7 @@ func determineArch(installerType string) string { } // determineFlavor gives you the proper flavor value, because the default installer type has no "multidistro" flavor so the default flavor is always needed in that case. -func determineFlavor(installerType string) string { +func determineFlavor(installerType string) string { //nolint:nolintlint,unparam if installerType == InstallerTypeDefault { return arch.FlavorDefault } diff --git a/pkg/clients/dynatrace/dynatrace_client_test.go b/pkg/clients/dynatrace/dynatrace_client_test.go index bd95a620ff..8316fa068d 100644 --- a/pkg/clients/dynatrace/dynatrace_client_test.go +++ b/pkg/clients/dynatrace/dynatrace_client_test.go @@ -313,11 +313,6 @@ func testServerErrors(t *testing.T) { err = dtc.makeRequestAndUnmarshal(context.Background(), dtc.url+flavorArchUri, dynatracePaaSToken, &response) assert.Equal(t, "dynatrace server error 400: Constraints violated.\n\t- flavor: 'defaulta' must be any of [default, multidistro, musl]\n\t- arch: 'x86a' must be any of [all, arm, ppc, ppcle, s390, sparc, x86, zos]", err.Error()) }) - - t.Run("GetLatestAgentVersion - invalid architecture", func(t *testing.T) { - _, err = dtc.GetLatestAgentVersion(context.Background(), "aix", InstallerTypePaaS) - assert.Equal(t, "dynatrace server error 404: non supported architecture on OS ", err.Error()) - }) } func dynatraceServerErrorsHandler() http.HandlerFunc { From 3a1dd4f900b040e064e2a2e0562f8270905f0f49 Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Mon, 2 Dec 2024 14:31:39 +0100 Subject: [PATCH 019/426] Recreate EEC statefulset for PVC changes only (#4131) --- .../dynakube/extension/eec/reconciler_test.go | 4 ++-- pkg/util/kubeobjects/statefulset/builder.go | 20 +++++++++++++++++++ pkg/util/kubeobjects/statefulset/query.go | 7 ++++--- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/pkg/controllers/dynakube/extension/eec/reconciler_test.go b/pkg/controllers/dynakube/extension/eec/reconciler_test.go index 90c16302e0..d527949b22 100644 --- a/pkg/controllers/dynakube/extension/eec/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/eec/reconciler_test.go @@ -545,7 +545,7 @@ func TestAnnotations(t *testing.T) { t.Run("the default annotations", func(t *testing.T) { statefulSet := getStatefulset(t, getTestDynakube()) - assert.Len(t, statefulSet.ObjectMeta.Annotations, 1) + assert.Len(t, statefulSet.ObjectMeta.Annotations, 2) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 1) assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[consts.ExtensionsAnnotationSecretHash]) }) @@ -559,7 +559,7 @@ func TestAnnotations(t *testing.T) { statefulSet := getStatefulset(t, dk) - assert.Len(t, statefulSet.ObjectMeta.Annotations, 1) + assert.Len(t, statefulSet.ObjectMeta.Annotations, 2) assert.Empty(t, statefulSet.ObjectMeta.Annotations["a"]) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 2) assert.Equal(t, "b", statefulSet.Spec.Template.ObjectMeta.Annotations["a"]) diff --git a/pkg/util/kubeobjects/statefulset/builder.go b/pkg/util/kubeobjects/statefulset/builder.go index 9356a64687..1665926cbe 100644 --- a/pkg/util/kubeobjects/statefulset/builder.go +++ b/pkg/util/kubeobjects/statefulset/builder.go @@ -1,6 +1,8 @@ package statefulset import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api" + "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/internal/builder" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" appsv1 "k8s.io/api/apps/v1" @@ -9,6 +11,10 @@ import ( "k8s.io/utils/ptr" ) +const ( + pvcAnnotationHash = api.InternalFlagPrefix + "pvc-hash" +) + var ( // Mandatory fields, provided in constructor as named params setName = builder.SetName[*appsv1.StatefulSet] @@ -26,6 +32,8 @@ func Build(owner metav1.Object, name string, container corev1.Container, options } neededOpts = append(neededOpts, options...) + neededOpts = append(neededOpts, setPVCAnnotation()) + return builder.Build(owner, &appsv1.StatefulSet{}, neededOpts...) } @@ -111,3 +119,15 @@ func SetUpdateStrategy(updateStartegy appsv1.StatefulSetUpdateStrategy) builder. s.Spec.UpdateStrategy = updateStartegy } } + +func setPVCAnnotation() builder.Option[*appsv1.StatefulSet] { + return func(s *appsv1.StatefulSet) { + if s.Spec.VolumeClaimTemplates != nil { + if s.ObjectMeta.Annotations == nil { + s.ObjectMeta.Annotations = map[string]string{} + } + + s.ObjectMeta.Annotations[pvcAnnotationHash], _ = hasher.GenerateHash(s.Spec.VolumeClaimTemplates) + } + } +} diff --git a/pkg/util/kubeobjects/statefulset/query.go b/pkg/util/kubeobjects/statefulset/query.go index 65568feff7..39a841f4d8 100644 --- a/pkg/util/kubeobjects/statefulset/query.go +++ b/pkg/util/kubeobjects/statefulset/query.go @@ -1,8 +1,6 @@ package statefulset import ( - "reflect" - "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/internal/query" @@ -37,5 +35,8 @@ func isEqual(current, desired *appsv1.StatefulSet) bool { } func mustRecreate(current, desired *appsv1.StatefulSet) bool { - return labels.NotEqual(current.Spec.Selector.MatchLabels, desired.Spec.Selector.MatchLabels) || !reflect.DeepEqual(current.Spec.VolumeClaimTemplates, desired.Spec.VolumeClaimTemplates) + currentHash := current.Annotations[pvcAnnotationHash] + desiredHash := desired.Annotations[pvcAnnotationHash] + + return labels.NotEqual(current.Spec.Selector.MatchLabels, desired.Spec.Selector.MatchLabels) || currentHash != desiredHash } From fcab2dccc93684e56908c4d5aa2ba7775bc0104c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 21:29:11 +0000 Subject: [PATCH 020/426] fix(deps): update module sigs.k8s.io/controller-runtime to v0.19.3 (main) (#4142) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 3 +-- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 73f632da39..9ccece926b 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( k8s.io/client-go v0.31.3 k8s.io/mount-utils v0.31.3 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 - sigs.k8s.io/controller-runtime v0.19.2 + sigs.k8s.io/controller-runtime v0.19.3 sigs.k8s.io/e2e-framework v0.3.0 sigs.k8s.io/yaml v1.4.0 ) @@ -49,7 +49,6 @@ require ( github.com/docker/docker-credential-helpers v0.8.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect diff --git a/go.sum b/go.sum index d6745dada5..ba69e0db96 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,6 @@ github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lSh github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= @@ -264,8 +262,8 @@ k8s.io/mount-utils v0.31.3 h1:CANy3prUYvvDCc2X7ZKgpjpDhAidx4gjGh/WwDrCPq8= k8s.io/mount-utils v0.31.3/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.19.2 h1:3sPrF58XQEPzbE8T81TN6selQIMGbtYwuaJ6eDssDF8= -sigs.k8s.io/controller-runtime v0.19.2/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= +sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw= +sigs.k8s.io/controller-runtime v0.19.3/go.mod h1:j4j87DqtsThvwTv5/Tc5NFRyyF/RF0ip4+62tbTSIUM= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= From f9b9def1a5af5111d3345d8260a32117e58bb3fe Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Tue, 3 Dec 2024 08:23:31 +0100 Subject: [PATCH 021/426] [cherry-pick] Warning if multiple Dyankubes with extensions are enabled for same ApiURL (#4128) (#4137) --- pkg/api/validation/dynakube/eec.go | 29 +++++++ pkg/api/validation/dynakube/eec_test.go | 100 ++++++++++++++++++++++ pkg/api/validation/dynakube/validation.go | 1 + 3 files changed, 130 insertions(+) diff --git a/pkg/api/validation/dynakube/eec.go b/pkg/api/validation/dynakube/eec.go index ab84e0eba8..4308060375 100644 --- a/pkg/api/validation/dynakube/eec.go +++ b/pkg/api/validation/dynakube/eec.go @@ -1,13 +1,17 @@ package validation import ( + "fmt" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "golang.org/x/net/context" + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( errorExtensionExecutionControllerImageNotSpecified = `DynaKube's specification enables the Prometheus feature, make sure you correctly specify the ExtensionExecutionController image.` errorExtensionExecutionControllerInvalidPVCConfiguration = `DynaKube specifies a PVC for the extension controller while ephemeral volume is also enabled. These settings are mutually exclusive, please choose only one.` + warningConflictingApiUrlForExtensions = `You are already using a Dynakube ('%s') that enables extensions. Having multiple Dynakubes with same '.spec.apiUrl' and '.spec.extensions' enabled can have severe side-effects on “sum” and “count” metrics and cause double-billing.` ) func extensionControllerImage(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { @@ -24,6 +28,31 @@ func extensionControllerImage(_ context.Context, _ *Validator, dk *dynakube.Dyna return "" } +func conflictingApiUrlForExtensions(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { + if !dk.IsExtensionsEnabled() { + return "" + } + + validDynakubes := &dynakube.DynaKubeList{} + if err := dv.apiReader.List(ctx, validDynakubes, &client.ListOptions{Namespace: dk.Namespace}); err != nil { + log.Info("error occurred while listing dynakubes", "err", err.Error()) + + return "" + } + + for _, item := range validDynakubes.Items { + if item.Name == dk.Name { + continue + } + + if item.IsExtensionsEnabled() && (dk.ApiUrl() == item.ApiUrl()) { + return fmt.Sprintf(warningConflictingApiUrlForExtensions, item.Name) + } + } + + return "" +} + func extensionControllerPVCStorageDevice(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { if !dk.IsExtensionsEnabled() { return "" diff --git a/pkg/api/validation/dynakube/eec_test.go b/pkg/api/validation/dynakube/eec_test.go index 641b9d5be3..638aa99d42 100644 --- a/pkg/api/validation/dynakube/eec_test.go +++ b/pkg/api/validation/dynakube/eec_test.go @@ -1,11 +1,17 @@ package validation import ( + "fmt" "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestExtensionExecutionControllerImage(t *testing.T) { @@ -141,3 +147,97 @@ func TestExtensionExecutionControllerPVCSettings(t *testing.T) { }) }) } + +func TestWarnIfmultiplyDKwithExtensionsEnabled(t *testing.T) { + imgRef := image.Ref{ + Repository: "a", + Tag: "b", + } + // we want to exclude AG resources warning. + agSpec := activegate.Spec{ + CapabilityProperties: activegate.CapabilityProperties{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + }, + }, + }, + } + dk1 := &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + Extensions: &dynakube.ExtensionsSpec{}, + Templates: dynakube.TemplatesSpec{ + ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ + ImageRef: imgRef, + }, + }, + ActiveGate: agSpec, + }, + } + + t.Run("no warning different ApiUrls", func(t *testing.T) { + dk2 := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName + "second", + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: "https://f.q.d.n/123", + Extensions: &dynakube.ExtensionsSpec{}, + Templates: dynakube.TemplatesSpec{ + ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ + ImageRef: imgRef, + }, + }, + ActiveGate: agSpec, + }, + } + assertAllowedWithoutWarnings(t, dk1, dk2) + }) + t.Run("warning same ApiUrls", func(t *testing.T) { + dk2 := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName + "second", + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + Extensions: &dynakube.ExtensionsSpec{}, + Templates: dynakube.TemplatesSpec{ + ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ + ImageRef: imgRef, + }, + }, + ActiveGate: agSpec, + }, + } + warnings, err := assertAllowed(t, dk1, dk2) + require.NoError(t, err) + require.Len(t, warnings, 1) + + expected := fmt.Sprintf(warningConflictingApiUrlForExtensions, dk2.Name) + assert.Equal(t, expected, warnings[0]) + }) + + t.Run("no warning same ApiUrls and for second dk: extensions feature is disabled", func(t *testing.T) { + dk2 := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName + "second", + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + Extensions: nil, + Templates: dynakube.TemplatesSpec{ + ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ + ImageRef: imgRef, + }, + }, + ActiveGate: agSpec, + }, + } + assertAllowedWithoutWarnings(t, dk1, dk2) + }) +} diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 734802224e..bcc8e1af88 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -59,6 +59,7 @@ var ( conflictingHostGroupSettings, deprecatedFeatureFlag, ignoredLogMonitoringTemplate, + conflictingApiUrlForExtensions, } updateValidatorErrorFuncs = []updateValidatorFunc{ IsMutatedApiUrl, From 33368c3ce8d16340a25cfd9dd6ac4def3f47203d Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Tue, 3 Dec 2024 09:04:09 +0100 Subject: [PATCH 022/426] Add validator to only allow 1 AG replica in combination with KSPM (#4138) (#4139) --- pkg/api/validation/dynakube/kspm.go | 9 ++++ pkg/api/validation/dynakube/kspm_test.go | 55 +++++++++++++++++++++++ pkg/api/validation/dynakube/validation.go | 1 + 3 files changed, 65 insertions(+) diff --git a/pkg/api/validation/dynakube/kspm.go b/pkg/api/validation/dynakube/kspm.go index bcfc6cd55a..a3610ec416 100644 --- a/pkg/api/validation/dynakube/kspm.go +++ b/pkg/api/validation/dynakube/kspm.go @@ -7,10 +7,19 @@ import ( ) const ( + errorTooManyAGReplicas = `The Dynakube's specification specifies KSPM, but has more than one ActiveGate replica. Only one ActiveGate replica is allowed in combination with KSPM.` errorKSPMMissingKubemon = `The Dynakube's specification specifies KSPM, but "kubernetes-monitoring" is not enabled on the Activegate.` errorKSPMMissingImage = `The Dynakube's specification specifies KSPM, but no image repository/tag is configured.` ) +func tooManyAGReplicas(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if dk.KSPM().IsEnabled() && dk.ActiveGate().GetReplicas() > 1 { + return errorTooManyAGReplicas + } + + return "" +} + func missingKSPMDependency(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { if dk.KSPM().IsEnabled() && !dk.ActiveGate().IsKubernetesMonitoringEnabled() { diff --git a/pkg/api/validation/dynakube/kspm_test.go b/pkg/api/validation/dynakube/kspm_test.go index 164fcb817a..39d8943bf2 100644 --- a/pkg/api/validation/dynakube/kspm_test.go +++ b/pkg/api/validation/dynakube/kspm_test.go @@ -9,6 +9,61 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" ) +func TestTooManyAGReplicas(t *testing.T) { + t.Run("activegate with 1 (per default) replica and kspm enabled", func(t *testing.T) { + assertAllowed(t, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + Kspm: &kspm.Spec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, + Templates: dynakube.TemplatesSpec{ + KspmNodeConfigurationCollector: kspm.NodeConfigurationCollectorSpec{ + ImageRef: image.Ref{ + Repository: "repo/image", + Tag: "version", + }, + }, + }, + }, + }) + }) + + t.Run("activegate with more than 1 replica and kspm enabled", func(t *testing.T) { + activeGate := activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + } + replicas := int32(3) + + activeGate.Replicas = &replicas + assertDenied(t, + []string{errorTooManyAGReplicas}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + Kspm: &kspm.Spec{}, + ActiveGate: activeGate, + Templates: dynakube.TemplatesSpec{ + KspmNodeConfigurationCollector: kspm.NodeConfigurationCollectorSpec{ + ImageRef: image.Ref{ + Repository: "repo/image", + Tag: "version", + }, + }, + }, + }, + }) + }) +} + func TestMissingKSPMDependency(t *testing.T) { t.Run("both kspm and kubemon enabled", func(t *testing.T) { assertAllowed(t, diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index bcc8e1af88..837a7fd76f 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -49,6 +49,7 @@ var ( imageFieldHasTenantImage, extensionControllerImage, extensionControllerPVCStorageDevice, + tooManyAGReplicas, missingKSPMDependency, missingKSPMImage, missingLogMonitoringImage, From a392119d3c6b12b29be63f8ad3bdaa63a52779df Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Tue, 3 Dec 2024 09:27:33 +0100 Subject: [PATCH 023/426] Reference official docs in SECURITY.md (#4133) --- SECURITY.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 5ffe18286f..f60ace8325 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,14 +1,6 @@ # Security Policy -## Supported Versions +Security related information can be found in the official docs: -The dynatrace-operator has not been released yet. -No version exists to be supported. - -| Version | Supported | -| ------- | ------------------ | - -## Reporting a Vulnerability - -This project is not yet released. -Currently no reporting policy exists. +- Network-traffic: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/security +- Permissions/Security-Benchmarks: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/network From 2904e524dc7219d878a89622660c316bea1f7b7f Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Tue, 3 Dec 2024 09:38:57 +0100 Subject: [PATCH 024/426] Add logmonitoring rbac to OA ServiceAccount (#4140) (#4145) --- .../clusterrole-logmonitoring.yaml | 19 +++++++++++++++- .../clusterrole-logmonitoring_test.yaml | 21 +++++++++++++----- .../dynakube/logmonitoring/daemonset/env.go | 22 +++++++++++++------ .../dynakube/oneagent/daemonset/env_vars.go | 10 +++++++++ .../oneagent/daemonset/env_vars_test.go | 13 +++++++++++ 5 files changed, 71 insertions(+), 14 deletions(-) diff --git a/config/helm/chart/default/templates/Common/logmonitoring/clusterrole-logmonitoring.yaml b/config/helm/chart/default/templates/Common/logmonitoring/clusterrole-logmonitoring.yaml index 61717eff40..8cb1ffac73 100644 --- a/config/helm/chart/default/templates/Common/logmonitoring/clusterrole-logmonitoring.yaml +++ b/config/helm/chart/default/templates/Common/logmonitoring/clusterrole-logmonitoring.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.rbac.logMonitoring.create (eq (include "dynatrace-operator.openshiftOrOlm" .) "true") }} +{{- if .Values.rbac.logMonitoring.create }} # Copyright 2021 Dynatrace LLC # Licensed under the Apache License, Version 2.0 (the "License"); @@ -48,4 +48,21 @@ subjects: - kind: ServiceAccount name: dynatrace-logmonitoring namespace: {{ .Release.Namespace }} +{{ if .Values.rbac.oneAgent.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dynatrace-logmonitoring-fullstack + labels: + {{- include "dynatrace-operator.logMonitoringLabels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: dynatrace-logmonitoring +subjects: +- kind: ServiceAccount + name: dynatrace-dynakube-oneagent + namespace: {{ .Release.Namespace }} +{{ end }} {{ end }} diff --git a/config/helm/chart/default/tests/Common/logmonitoring/clusterrole-logmonitoring_test.yaml b/config/helm/chart/default/tests/Common/logmonitoring/clusterrole-logmonitoring_test.yaml index 83dd7d3dcf..c156a00522 100644 --- a/config/helm/chart/default/tests/Common/logmonitoring/clusterrole-logmonitoring_test.yaml +++ b/config/helm/chart/default/tests/Common/logmonitoring/clusterrole-logmonitoring_test.yaml @@ -4,7 +4,8 @@ templates: tests: - it: logmonitoring ClusterRole should exist set: - platform: openshift + rbac.logMonitoring.create: true + rbac.oneagent.create: false documentIndex: 0 asserts: - isKind: @@ -28,7 +29,8 @@ tests: - it: logmonitoring ClusterRoleBinding should exist documentIndex: 1 set: - platform: openshift + rbac.logMonitoring.create: true + rbac.oneagent.create: false asserts: - isKind: of: ClusterRoleBinding @@ -37,16 +39,23 @@ tests: value: dynatrace-logmonitoring - isNotEmpty: path: metadata.labels - - it: shouldn't exist if not openshift + - it: extra binding should exist for fullstack + documentIndex: 2 set: rbac.logMonitoring.create: true - platform: NOT-openshift + rbac.oneagent.create: true asserts: - - hasDocuments: - count: 0 + - isKind: + of: ClusterRoleBinding + - equal: + path: metadata.name + value: dynatrace-logmonitoring-fullstack + - isNotEmpty: + path: metadata.labels - it: shouldn't exist if turned off set: rbac.logMonitoring.create: false + rbac.oneagent.create: true asserts: - hasDocuments: count: 0 diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/env.go b/pkg/controllers/dynakube/logmonitoring/daemonset/env.go index 1c2e6dd689..b716b887c7 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/env.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/env.go @@ -17,10 +17,10 @@ const ( entityEnv = "DT_ENTITY_KUBERNETES_CLUSTER" // main container envs - apiNodeNameEnv = "KUBELET_API_NODENAME" - apiIPAddressEnv = "KUBELET_API_ADDRESS" - dtStorageEnv = "DT_STORAGE" - ruxitConfigEnv = "APMNG_PA_CONFIG_PATH" + KubeletNodeNameEnv = "KUBELET_API_NODENAME" + KubeletIPAddressEnv = "KUBELET_API_ADDRESS" + dtStorageEnv = "DT_STORAGE" + ruxitConfigEnv = "APMNG_PA_CONFIG_PATH" dtStoragePath = "/var/lib/dynatrace/oneagent" ruxitConfigPath = "/var/lib/dynatrace/oneagent/agent/config/ruxitagentproc.conf" @@ -75,10 +75,10 @@ func getInitEnvs(dk dynakube.DynaKube) []corev1.EnvVar { } } -func getEnvs() []corev1.EnvVar { +func GetKubeletEnvs() []corev1.EnvVar { return []corev1.EnvVar{ { - Name: apiNodeNameEnv, + Name: KubeletNodeNameEnv, ValueFrom: &corev1.EnvVarSource{ FieldRef: &corev1.ObjectFieldSelector{ FieldPath: "spec.nodeName", @@ -86,13 +86,19 @@ func getEnvs() []corev1.EnvVar { }, }, { - Name: apiIPAddressEnv, + Name: KubeletIPAddressEnv, ValueFrom: &corev1.EnvVarSource{ FieldRef: &corev1.ObjectFieldSelector{ FieldPath: "status.hostIP", }, }, }, + } +} + +func getEnvs() []corev1.EnvVar { + apiEnvs := GetKubeletEnvs() + standaloneEnvs := []corev1.EnvVar{ { Name: dtStorageEnv, Value: dtStoragePath, @@ -102,4 +108,6 @@ func getEnvs() []corev1.EnvVar { Value: ruxitConfigPath, }, } + + return append(apiEnvs, standaloneEnvs...) } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go index 0771bd4d52..5de52b8eca 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go @@ -5,6 +5,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" + logmonitoring "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/daemonset" "github.com/Dynatrace/dynatrace-operator/pkg/util/prioritymap" "github.com/Dynatrace/dynatrace-operator/pkg/version" appsv1 "k8s.io/api/apps/v1" @@ -42,6 +43,7 @@ func (b *builder) environmentVariables() ([]corev1.EnvVar, error) { b.addOperatorVersionInfoEnv(envMap) b.addConnectionInfoEnvs(envMap) b.addReadOnlyEnv(envMap) + b.addLogMonitoringEnv(envMap) isProxyAsEnvDeprecated, err := isProxyAsEnvVarDeprecated(b.dk.OneAgentVersion()) if err != nil { @@ -125,6 +127,14 @@ func (b *builder) addReadOnlyEnv(envVarMap *prioritymap.Map) { } } +func (b *builder) addLogMonitoringEnv(envVarMap *prioritymap.Map) { + if b.dk != nil && b.dk.LogMonitoring().IsEnabled() { + for _, env := range logmonitoring.GetKubeletEnvs() { + prioritymap.Append(envVarMap, env) + } + } +} + func (b *hostMonitoring) appendInfraMonEnvVars(daemonset *appsv1.DaemonSet) { envVars := prioritymap.New() prioritymap.Append(envVars, daemonset.Spec.Template.Spec.Containers[0].Env) diff --git a/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go b/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go index 001de1c438..fe6580d8d9 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go @@ -6,8 +6,10 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" + logmonitoringds "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/daemonset" k8senv "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/util/prioritymap" "github.com/stretchr/testify/assert" @@ -39,6 +41,7 @@ func TestEnvironmentVariables(t *testing.T) { OneAgent: dynakube.OneAgentSpec{ CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, }, + LogMonitoring: &logmonitoring.Spec{}, }, } dsBuilder := builder{ @@ -53,6 +56,7 @@ func TestEnvironmentVariables(t *testing.T) { assertDeploymentMetadataEnv(t, envVars, dk.Name) assertReadOnlyEnv(t, envVars) + assertLogMonitoringEnv(t, envVars) }) t.Run("when injected envvars are provided then they will not be overridden", func(t *testing.T) { potentiallyOverriddenEnvVars := []corev1.EnvVar{ @@ -290,6 +294,15 @@ func assertReadOnlyEnv(t *testing.T, envs []corev1.EnvVar) { assert.Equal(t, "true", env.Value) } +func assertLogMonitoringEnv(t *testing.T, envs []corev1.EnvVar) { + env := k8senv.FindEnvVar(envs, logmonitoringds.KubeletIPAddressEnv) + require.NotNil(t, env) + assert.NotEmpty(t, env.ValueFrom) + env = k8senv.FindEnvVar(envs, logmonitoringds.KubeletNodeNameEnv) + require.NotNil(t, env) + assert.NotEmpty(t, env.ValueFrom) +} + func TestIsProxyAsEnvVarDeprecated(t *testing.T) { tests := []struct { name string From dbb7f17128fd4658aee67fd6bd2726e018de4631 Mon Sep 17 00:00:00 2001 From: Lukas Hinterreiter <90035514+luhi-DT@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:27:54 +0100 Subject: [PATCH 025/426] Add feature flag to skip oneAgent livenessprobe (#4146) (#4147) --- pkg/api/v1beta3/dynakube/feature_flags.go | 5 +++++ pkg/api/v1beta3/dynakube/oneagent_props.go | 6 +++++- .../dynakube/oneagent/daemonset/daemonset.go | 5 ++++- .../oneagent/daemonset/daemonset_test.go | 20 +++++++++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/pkg/api/v1beta3/dynakube/feature_flags.go b/pkg/api/v1beta3/dynakube/feature_flags.go index 94f0a741fd..d02560d492 100644 --- a/pkg/api/v1beta3/dynakube/feature_flags.go +++ b/pkg/api/v1beta3/dynakube/feature_flags.go @@ -58,6 +58,7 @@ const ( AnnotationFeatureOneAgentMaxUnavailable = AnnotationFeaturePrefix + "oneagent-max-unavailable" AnnotationFeatureOneAgentInitialConnectRetry = AnnotationFeaturePrefix + "oneagent-initial-connect-retry-ms" AnnotationFeatureRunOneAgentContainerPrivileged = AnnotationFeaturePrefix + "oneagent-privileged" + AnnotationFeatureOneAgentSkipLivenessProbe = AnnotationFeaturePrefix + "oneagent-skip-liveness-probe" AnnotationFeatureIgnoreUnknownState = AnnotationFeaturePrefix + "ignore-unknown-state" AnnotationFeatureIgnoredNamespaces = AnnotationFeaturePrefix + "ignored-namespaces" @@ -228,6 +229,10 @@ func (dk *DynaKube) FeatureOneAgentPrivileged() bool { return dk.getFeatureFlagRaw(AnnotationFeatureRunOneAgentContainerPrivileged) == truePhrase } +func (dk *DynaKube) FeatureOneAgentSkipLivenessProbe() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureOneAgentSkipLivenessProbe) == truePhrase +} + func (dk *DynaKube) FeatureMaxFailedCsiMountAttempts() int { maxCsiMountAttemptsValue := dk.getFeatureFlagInt(AnnotationFeatureMaxFailedCsiMountAttempts, DefaultMaxFailedCsiMountAttempts) if maxCsiMountAttemptsValue < 0 { diff --git a/pkg/api/v1beta3/dynakube/oneagent_props.go b/pkg/api/v1beta3/dynakube/oneagent_props.go index e1471af4ce..75ee227a4f 100644 --- a/pkg/api/v1beta3/dynakube/oneagent_props.go +++ b/pkg/api/v1beta3/dynakube/oneagent_props.go @@ -55,10 +55,14 @@ func (dk *DynaKube) NeedsOneAgentPrivileged() bool { return dk.FeatureOneAgentPrivileged() } -func (dk *DynaKube) NeedsOneAgentProbe() bool { +func (dk *DynaKube) NeedsOneAgentReadinessProbe() bool { return dk.Status.OneAgent.Healthcheck != nil } +func (dk *DynaKube) NeedsOneAgentLivenessProbe() bool { + return dk.Status.OneAgent.Healthcheck != nil && !dk.FeatureOneAgentSkipLivenessProbe() +} + // ShouldAutoUpdateOneAgent returns true if the Operator should update OneAgent instances automatically. func (dk *DynaKube) ShouldAutoUpdateOneAgent() bool { switch { diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go index 1a724f4d58..b8c1c11026 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go @@ -224,8 +224,11 @@ func (b *builder) podSpec() (corev1.PodSpec, error) { TerminationGracePeriodSeconds: ptr.To(defaultTerminationGracePeriod), } - if b.dk.NeedsOneAgentProbe() { + if b.dk.NeedsOneAgentReadinessProbe() { podSpec.Containers[0].ReadinessProbe = b.getReadinessProbe() + } + + if b.dk.NeedsOneAgentLivenessProbe() { podSpec.Containers[0].LivenessProbe = b.getDefaultProbeFromStatus() } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go index bd3e42865b..0735ba2a04 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go @@ -576,6 +576,26 @@ func TestPodSpecProbes(t *testing.T) { assert.Nil(t, podSpec.Containers[0].ReadinessProbe) assert.Nil(t, podSpec.Containers[0].LivenessProbe) }) + t.Run("no livenessProbe when skip featureFlag is set", func(t *testing.T) { + builder := builder{ + dk: &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + dynakube.AnnotationFeatureOneAgentSkipLivenessProbe: "true", + }, + }, + Status: dynakube.DynaKubeStatus{ + OneAgent: dynakube.OneAgentStatus{ + Healthcheck: &expectedHealthcheck, + }, + }, + }, + } + podSpec, _ := builder.podSpec() + + assert.NotNil(t, podSpec.Containers[0].ReadinessProbe) + assert.Nil(t, podSpec.Containers[0].LivenessProbe) + }) } func TestOneAgentResources(t *testing.T) { From c2a4a307dab9cebaff29641d7c9ab304b83e10db Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 12:38:03 +0000 Subject: [PATCH 026/426] chore(deps): update github/codeql-action action to v3.27.6 (main) (#4149) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 88e6b4dca9..32194725c5 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 + uses: github/codeql-action/init@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 + uses: github/codeql-action/autobuild@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 + uses: github/codeql-action/analyze@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index f73085f765..109b907651 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 + uses: github/codeql-action/upload-sarif@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 with: sarif_file: results.sarif From fd5961d14f21d76f6bb79e8adcd7de973eed9a3b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 21:04:05 +0000 Subject: [PATCH 027/426] chore(deps): update module github.com/vektra/mockery to v2.49.2 (main) (#4154) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index c712574740..747d1aed58 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.27.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.49.1 +mockery_version=v2.49.2 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest From 0df8665e4cd96f657eacf0075638b060b39d045f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 08:40:47 +0000 Subject: [PATCH 028/426] chore(deps): update golang docker tag to v1.23.4 (main) (#4156) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 985ca80df3..80820fa56e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # setup build image -FROM golang:1.23.3@sha256:d56c3e08fe5b27729ee3834854ae8f7015af48fd651cd25d1e3bcf3c19830174 AS operator-build +FROM golang:1.23.4@sha256:c25964d301e6c50174d29deadbbaa5ea6443e94b61087b6d89e8f41ef4ebca35 AS operator-build RUN --mount=type=cache,target=/var/cache/apt \ apt-get update && apt-get install -y libbtrfs-dev libdevmapper-dev From 026939eddebe658e2828f1fdfa81b9edceebd008 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:43:46 +0000 Subject: [PATCH 029/426] chore(deps): update module github.com/vektra/mockery to v2.50.0 (main) (#4161) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 747d1aed58..49a5498d9d 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.27.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.49.2 +mockery_version=v2.50.0 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest From 1a3f0ecd67aeb9bd295f7b209e13ac5aa92efcdc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:59:31 +0000 Subject: [PATCH 030/426] fix(deps): update module google.golang.org/grpc to v1.68.1 (main) (#4164) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9ccece926b..235e8cd649 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( golang.org/x/net v0.31.0 golang.org/x/oauth2 v0.24.0 golang.org/x/sys v0.27.0 - google.golang.org/grpc v1.68.0 + google.golang.org/grpc v1.68.1 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.1 istio.io/client-go v1.24.1 diff --git a/go.sum b/go.sum index ba69e0db96..2683fd72b6 100644 --- a/go.sum +++ b/go.sum @@ -223,8 +223,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1: google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= -google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= +google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0= +google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 705b1047c38afc389a3359b276117c3f5e4aac19 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 04:37:31 +0000 Subject: [PATCH 031/426] chore(deps): update module golang.org/x/tools to v0.28.0 (main) (#4166) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 49a5498d9d..3365f5040c 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -7,7 +7,7 @@ golang_ci_cmd_version=v1.62.2 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools -golang_tools_version=v0.27.0 +golang_tools_version=v0.28.0 # renovate depName=github.com/vektra/mockery mockery_version=v2.50.0 # renovate depName=github.com/igorshubovych/markdownlint-cli From 332bbebfda23fe3604fe132962f3b08a5a5d18e7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 07:38:14 +0000 Subject: [PATCH 032/426] fix(deps): update module golang.org/x/net to v0.32.0 (main) (#4165) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 235e8cd649..e73e1a8035 100644 --- a/go.mod +++ b/go.mod @@ -21,9 +21,9 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 golang.org/x/mod v0.22.0 - golang.org/x/net v0.31.0 + golang.org/x/net v0.32.0 golang.org/x/oauth2 v0.24.0 - golang.org/x/sys v0.27.0 + golang.org/x/sys v0.28.0 google.golang.org/grpc v1.68.1 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.1 @@ -88,9 +88,9 @@ require ( github.com/vladimirvivien/gexe v0.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sync v0.9.0 // indirect - golang.org/x/term v0.26.0 // indirect - golang.org/x/text v0.20.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect diff --git a/go.sum b/go.sum index 2683fd72b6..d282d778f3 100644 --- a/go.sum +++ b/go.sum @@ -183,28 +183,28 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From f3cb3848a696c5ff3e672c4535b3c59cc7628f4f Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Thu, 5 Dec 2024 09:03:37 +0100 Subject: [PATCH 033/426] Add missing SCC for OTEL sts for OCP < 4.12 (#4159) (#4163) --- ...le-extensions-opentelemetry-collector.yaml | 10 ++++++++ ...tensions-opentelemetry-collector_test.yaml | 24 ++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector.yaml b/config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector.yaml index 5924728922..3c685cee95 100644 --- a/config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector.yaml +++ b/config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector.yaml @@ -44,6 +44,16 @@ rules: - get - list - watch + {{- if (eq (include "dynatrace-operator.openshiftOrOlm" .) "true") }} + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use + {{ end }} - nonResourceURLs: - /metrics - /metrics/cadvisor diff --git a/config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector_test.yaml b/config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector_test.yaml index a84818b1dc..53d3121159 100644 --- a/config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector_test.yaml +++ b/config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector_test.yaml @@ -57,7 +57,29 @@ tests: - /metrics/cadvisor verbs: - get - + - it: ClusterRole should exist with extra permissions for openshift + documentIndex: 0 + set: + platform: openshift + asserts: + - isKind: + of: ClusterRole + - equal: + path: metadata.name + value: dynatrace-extensions-prometheus + - isNotEmpty: + path: metadata.labels + - contains: + path: rules + content: + apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use - it: ClusterRoleBinding exists documentIndex: 1 asserts: From 996e4a67f41d9f91625f356cee940ff94f899ae9 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Thu, 5 Dec 2024 12:23:39 +0100 Subject: [PATCH 034/426] Correct schemaVersion and improve error handling (#4148) (#4151) Co-authored-by: Christoph Muellner <33160506+chrismuellner@users.noreply.github.com> --- pkg/clients/dynatrace/settings_logmonitoring.go | 3 ++- .../logmonitoring/logmonsettings/conditions.go | 11 +++++++++++ .../logmonitoring/logmonsettings/reconciler.go | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pkg/clients/dynatrace/settings_logmonitoring.go b/pkg/clients/dynatrace/settings_logmonitoring.go index 5f7e0e53d2..bf6761c702 100644 --- a/pkg/clients/dynatrace/settings_logmonitoring.go +++ b/pkg/clients/dynatrace/settings_logmonitoring.go @@ -39,6 +39,7 @@ type posLogMonSettingsBody struct { const ( logMonitoringSettingsSchemaId = "builtin:logmonitoring.log-storage-settings" + schemaVersion = "1.0.16" ) func (dtc *dynatraceClient) performCreateLogMonSetting(ctx context.Context, body []posLogMonSettingsBody) (string, error) { //nolint:dupl @@ -114,7 +115,7 @@ func createBaseLogMonSettings(clusterName, schemaId string, schemaVersion string } func (dtc *dynatraceClient) CreateLogMonitoringSetting(ctx context.Context, scope, clusterName string, matchers []logmonitoring.IngestRuleMatchers) (string, error) { - settings := createBaseLogMonSettings(clusterName, logMonitoringSettingsSchemaId, "1.0.0", scope, matchers) + settings := createBaseLogMonSettings(clusterName, logMonitoringSettingsSchemaId, schemaVersion, scope, matchers) objectId, err := dtc.performCreateLogMonSetting(ctx, []posLogMonSettingsBody{settings}) if err != nil { diff --git a/pkg/controllers/dynakube/logmonitoring/logmonsettings/conditions.go b/pkg/controllers/dynakube/logmonitoring/logmonsettings/conditions.go index 27b3ff7b16..6b4d889450 100644 --- a/pkg/controllers/dynakube/logmonitoring/logmonsettings/conditions.go +++ b/pkg/controllers/dynakube/logmonitoring/logmonsettings/conditions.go @@ -7,6 +7,7 @@ import ( const ( settingsExistReason = "LogMonSettingsExist" + settingsErrorReason = "LogMonSettingsError" conditionType = "LogMonitoringSettings" ) @@ -20,3 +21,13 @@ func setLogMonitoringSettingExists(conditions *[]metav1.Condition, conditionType } _ = meta.SetStatusCondition(conditions, condition) } + +func setLogMonitoringSettingError(conditions *[]metav1.Condition, conditionType, message string) { + condition := metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + Reason: settingsErrorReason, + Message: "LogMonitoring settings could not be created: " + message, + } + _ = meta.SetStatusCondition(conditions, condition) +} diff --git a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go index 7085b668a9..dae465b8d4 100644 --- a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go @@ -56,6 +56,8 @@ func (r *reconciler) checkLogMonitoringSettings(ctx context.Context) error { logMonitoringSettings, err := r.dtc.GetSettingsForLogModule(ctx, r.dk.Status.KubernetesClusterMEID) if err != nil { + setLogMonitoringSettingError(r.dk.Conditions(), conditionType, err.Error()) + return errors.WithMessage(err, "error trying to check if setting exists") } @@ -75,6 +77,8 @@ func (r *reconciler) checkLogMonitoringSettings(ctx context.Context) error { objectId, err := r.dtc.CreateLogMonitoringSetting(ctx, r.dk.Status.KubernetesClusterMEID, r.dk.Status.KubernetesClusterName, matchers) if err != nil { + setLogMonitoringSettingError(r.dk.Conditions(), conditionType, err.Error()) + return errors.WithMessage(err, "error when creating log monitoring setting") } From 984a2e75684693d897b1350612c16c33683d788a Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:36:45 +0100 Subject: [PATCH 035/426] Transfer EC.Labels and EC.Annotations to the POD spec (#4153) --- pkg/controllers/edgeconnect/controller.go | 12 +- .../edgeconnect/deployment/deployment.go | 27 ++-- .../edgeconnect/deployment/deployment_test.go | 128 ++++++++++++++++++ 3 files changed, 150 insertions(+), 17 deletions(-) diff --git a/pkg/controllers/edgeconnect/controller.go b/pkg/controllers/edgeconnect/controller.go index 9ae6d91728..9c8a8d595f 100644 --- a/pkg/controllers/edgeconnect/controller.go +++ b/pkg/controllers/edgeconnect/controller.go @@ -377,7 +377,11 @@ func (controller *Controller) reconcileEdgeConnectRegular(ctx context.Context, e return err } - desiredDeployment.Spec.Template.Annotations = map[string]string{consts.EdgeConnectAnnotationSecretHash: secretHash} + if desiredDeployment.Spec.Template.Annotations == nil { + desiredDeployment.Spec.Template.Annotations = map[string]string{} + } + + desiredDeployment.Spec.Template.Annotations[consts.EdgeConnectAnnotationSecretHash] = secretHash _, err = k8sdeployment.Query(controller.client, controller.apiReader, log).WithOwner(ec).CreateOrUpdate(ctx, desiredDeployment) if err != nil { @@ -674,7 +678,11 @@ func (controller *Controller) createOrUpdateEdgeConnectDeploymentAndSettings(ctx desiredDeployment := deployment.New(ec) - desiredDeployment.Spec.Template.Annotations = map[string]string{consts.EdgeConnectAnnotationSecretHash: secretHash} + if desiredDeployment.Spec.Template.Annotations == nil { + desiredDeployment.Spec.Template.Annotations = map[string]string{} + } + + desiredDeployment.Spec.Template.Annotations[consts.EdgeConnectAnnotationSecretHash] = secretHash _log = _log.WithValues("deploymentName", desiredDeployment.Name) if err := controllerutil.SetControllerReference(ec, desiredDeployment, scheme.Scheme); err != nil { diff --git a/pkg/controllers/edgeconnect/deployment/deployment.go b/pkg/controllers/edgeconnect/deployment/deployment.go index eac5b13e19..29c55123e1 100644 --- a/pkg/controllers/edgeconnect/deployment/deployment.go +++ b/pkg/controllers/edgeconnect/deployment/deployment.go @@ -6,7 +6,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/resources" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" - "github.com/Dynatrace/dynatrace-operator/pkg/util/prioritymap" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -15,10 +14,8 @@ import ( ) const ( - customEnvPriority = prioritymap.HighPriority - defaultEnvPriority = prioritymap.DefaultPriority - unprivilegedUser = int64(1000) - unprivilegedGroup = int64(1000) + unprivilegedUser = int64(1000) + unprivilegedGroup = int64(1000) ) func New(ec *edgeconnect.EdgeConnect) *appsv1.Deployment { @@ -27,9 +24,11 @@ func New(ec *edgeconnect.EdgeConnect) *appsv1.Deployment { func create(ec *edgeconnect.EdgeConnect) *appsv1.Deployment { appLabels := buildAppLabels(ec) - labels := maputils.MergeMap( - ec.Labels, - appLabels.BuildLabels(), + labels := appLabels.BuildLabels() + + customPodLabels := maputils.MergeMap( + ec.Spec.Labels, + labels, // higher priority ) log.Debug("EdgeConnect deployment app labels", "labels", labels) @@ -39,7 +38,7 @@ func create(ec *edgeconnect.EdgeConnect) *appsv1.Deployment { Name: ec.Name, Namespace: ec.Namespace, Labels: labels, - Annotations: buildAnnotations(ec), + Annotations: buildAnnotations(), }, Spec: appsv1.DeploymentSpec{ Replicas: ec.Spec.Replicas, @@ -48,7 +47,8 @@ func create(ec *edgeconnect.EdgeConnect) *appsv1.Deployment { }, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: labels, + Annotations: ec.Spec.Annotations, + Labels: customPodLabels, }, Spec: corev1.PodSpec{ Containers: []corev1.Container{edgeConnectContainer(ec)}, @@ -92,14 +92,11 @@ func buildAppLabels(ec *edgeconnect.EdgeConnect) *labels.AppLabels { ec.Status.Version.Version) } -func buildAnnotations(ec *edgeconnect.EdgeConnect) map[string]string { - annotations := map[string]string{ +func buildAnnotations() map[string]string { + return map[string]string{ consts.AnnotationEdgeConnectContainerAppArmor: "runtime/default", webhook.AnnotationDynatraceInject: "false", } - annotations = maputils.MergeMap(ec.Annotations, annotations) - - return annotations } func edgeConnectContainer(ec *edgeconnect.EdgeConnect) corev1.Container { diff --git a/pkg/controllers/edgeconnect/deployment/deployment_test.go b/pkg/controllers/edgeconnect/deployment/deployment_test.go index d9d21c92d4..7b1499ca21 100644 --- a/pkg/controllers/edgeconnect/deployment/deployment_test.go +++ b/pkg/controllers/edgeconnect/deployment/deployment_test.go @@ -6,8 +6,10 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/resources" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -66,6 +68,132 @@ func Test_buildAppLabels(t *testing.T) { }) } +func TestLabels(t *testing.T) { + testObjectMetaLabelKey := "test-om-label-key" + testObjectMetaValue := "test-om-label-value" + + testLabelKey := "test-label-key" + testLabelValue := "test-label-value" + + t.Run("Check empty custom labels", func(t *testing.T) { + ec := &edgeconnect.EdgeConnect{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Labels: map[string]string{ + testObjectMetaLabelKey: testObjectMetaValue, + }, + }, + Spec: edgeconnect.EdgeConnectSpec{}, + } + + deployment := New(ec) + + require.Len(t, deployment.Spec.Template.Labels, 5) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppNameLabel) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppCreatedByLabel) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppManagedByLabel) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppVersionLabel) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppComponentLabel) + + require.Len(t, deployment.ObjectMeta.Labels, 5) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppNameLabel) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppCreatedByLabel) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppManagedByLabel) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppVersionLabel) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppComponentLabel) + }) + + t.Run("Check custom label set correctly", func(t *testing.T) { + ec := &edgeconnect.EdgeConnect{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Labels: map[string]string{ + testObjectMetaLabelKey: testObjectMetaValue, + }, + }, + Spec: edgeconnect.EdgeConnectSpec{ + Labels: map[string]string{ + testLabelKey: testLabelValue, + }, + }, + } + + deployment := New(ec) + + assert.Len(t, deployment.Spec.Template.Labels, 6) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppNameLabel) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppCreatedByLabel) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppManagedByLabel) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppVersionLabel) + assert.Contains(t, deployment.Spec.Template.Labels, labels.AppComponentLabel) + + assert.Contains(t, deployment.Spec.Template.ObjectMeta.Labels, testLabelKey) + assert.Equal(t, testLabelValue, deployment.Spec.Template.ObjectMeta.Labels[testLabelKey]) + + require.Len(t, deployment.ObjectMeta.Labels, 5) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppNameLabel) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppCreatedByLabel) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppManagedByLabel) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppVersionLabel) + assert.Contains(t, deployment.ObjectMeta.Labels, labels.AppComponentLabel) + }) +} + +func TestAnnotations(t *testing.T) { + testObjectMetaAnnotationKey := "test-om-annotation-key" + testObjectMetaAnnotationValue := "test-om-annotation-value" + + testAnnotationKey := "test-annotation-key" + testAnnotationValue := "test-annotation-value" + + t.Run("Check empty annotations", func(t *testing.T) { + ec := &edgeconnect.EdgeConnect{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Annotations: map[string]string{ + testObjectMetaAnnotationKey: testObjectMetaAnnotationValue, + }, + }, + Spec: edgeconnect.EdgeConnectSpec{}, + } + + deployment := New(ec) + + assert.Nil(t, deployment.Spec.Template.ObjectMeta.Annotations) + + assert.NotContains(t, deployment.ObjectMeta.Annotations, testObjectMetaAnnotationKey) + }) + + t.Run("Check custom annotations set correctly", func(t *testing.T) { + ec := &edgeconnect.EdgeConnect{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Annotations: map[string]string{ + testObjectMetaAnnotationKey: testObjectMetaAnnotationValue, + }, + }, + Spec: edgeconnect.EdgeConnectSpec{ + Annotations: map[string]string{ + testAnnotationKey: testAnnotationValue, + }, + }, + } + + deployment := New(ec) + + assert.Len(t, deployment.Spec.Template.Annotations, 1) + assert.Contains(t, deployment.Spec.Template.ObjectMeta.Annotations, testAnnotationKey) + assert.Equal(t, testAnnotationValue, deployment.Spec.Template.ObjectMeta.Annotations[testAnnotationKey]) + + assert.NotContains(t, deployment.ObjectMeta.Annotations, testAnnotationKey) + assert.NotContains(t, deployment.ObjectMeta.Annotations, testObjectMetaAnnotationKey) + }) +} + func Test_prepareResourceRequirements(t *testing.T) { ec := &edgeconnect.EdgeConnect{ ObjectMeta: metav1.ObjectMeta{ From 816fa0f217fd447a5e12aa788e85b8362b93cea3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 01:53:00 +0000 Subject: [PATCH 036/426] chore(deps): update codecov/codecov-action action to v5.1.1 (main) (#4170) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d7ac32cd34..e0664a7064 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -71,7 +71,7 @@ jobs: run: | make go/check-coverage - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5.0.7 + uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # v5.1.1 with: fail_ci_if_error: true verbose: true From 4215cbec27e0862dbf66d7794f80059789d454ca Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Fri, 6 Dec 2024 10:59:25 +0100 Subject: [PATCH 037/426] Bump operator prev version in upgrade e2e test to 1.3.2. (#4169) --- .github/workflows/e2e-tests-ondemand.yaml | 7 ++++--- test/features/cloudnative/upgrade/upgrade.go | 4 ++-- test/helpers/components/dynakube/dynakube.go | 8 ++++---- test/helpers/components/oneagent/daemonset.go | 13 ++++--------- test/scenarios/release/release_test.go | 2 +- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/.github/workflows/e2e-tests-ondemand.yaml b/.github/workflows/e2e-tests-ondemand.yaml index 36e1aaddf1..1cfa82d71d 100644 --- a/.github/workflows/e2e-tests-ondemand.yaml +++ b/.github/workflows/e2e-tests-ondemand.yaml @@ -82,8 +82,9 @@ jobs: - name: Notify failure in Slack uses: slackapi/slack-github-action@485a9d42d3a73031f12ec201c457e2162c45d02d # v2.0.0 with: - payload: | - message: ":x: E2E ondemand tests failed on ${{ env.branch }} branch (${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", - run_id: "${{ github.run_id }}" webhook: ${{ secrets.SLACK_WEBHOOK_URL }} webhook-type: webhook-trigger + payload-templated: true + payload: | + "message": ":red_circle: E2E ondemand tests failed on ${{ env.branch }} branch (${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" + "run_id": "${{ github.run_id }}" diff --git a/test/features/cloudnative/upgrade/upgrade.go b/test/features/cloudnative/upgrade/upgrade.go index e4eebd31d6..1ee4ccc3f7 100644 --- a/test/features/cloudnative/upgrade/upgrade.go +++ b/test/features/cloudnative/upgrade/upgrade.go @@ -5,7 +5,7 @@ package upgrade import ( "testing" - dynakubev1beta1 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta1/dynakube" //nolint:staticcheck + dynakubev1beta2 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta2/dynakube" //nolint:staticcheck "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" @@ -31,7 +31,7 @@ func Feature(t *testing.T) features.Feature { ) builder.Assess("create sample namespace", sampleApp.InstallNamespace()) - previousVersionDynakube := &dynakubev1beta1.DynaKube{} + previousVersionDynakube := &dynakubev1beta2.DynaKube{} previousVersionDynakube.ConvertFrom(&testDynakube) dynakube.InstallPreviousVersion(builder, helpers.LevelAssess, &secretConfig, *previousVersionDynakube) diff --git a/test/helpers/components/dynakube/dynakube.go b/test/helpers/components/dynakube/dynakube.go index e60b16619e..18fbc55c97 100644 --- a/test/helpers/components/dynakube/dynakube.go +++ b/test/helpers/components/dynakube/dynakube.go @@ -9,7 +9,7 @@ import ( "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - prevDynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta1/dynakube" //nolint:staticcheck + prevDynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta2/dynakube" //nolint:staticcheck "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" @@ -63,7 +63,7 @@ func CreatePreviousVersion(builder *features.FeatureBuilder, level features.Leve func VerifyStartupPreviousVersion(builder *features.FeatureBuilder, level features.Level, prevDk prevDynakube.DynaKube) { if prevDk.NeedsOneAgent() { - builder.WithStep("oneagent started", level, oneagent.WaitFromDaemonSetPrevDk(prevDk)) + builder.WithStep("oneagent started", level, oneagent.WaitForDaemonset(prevDk.OneAgentDaemonsetName(), prevDk.Namespace)) } builder.WithStep( fmt.Sprintf("'%s' dynakube phase changes to 'Running'", prevDk.Name), @@ -74,7 +74,7 @@ func VerifyStartupPreviousVersion(builder *features.FeatureBuilder, level featur func Delete(builder *features.FeatureBuilder, level features.Level, dk dynakube.DynaKube) { builder.WithStep("dynakube deleted", level, remove(dk)) if dk.NeedsOneAgent() { - builder.WithStep("oneagent pods stopped", level, oneagent.WaitForDaemonSetPodsDeletion(dk)) + builder.WithStep("oneagent pods stopped", level, oneagent.WaitForDaemonSetPodsDeletion(dk.OneAgentDaemonsetName(), dk.Namespace)) } if dk.ClassicFullStackMode() { oneagent.RunClassicUninstall(builder, level, dk) @@ -83,7 +83,7 @@ func Delete(builder *features.FeatureBuilder, level features.Level, dk dynakube. func VerifyStartup(builder *features.FeatureBuilder, level features.Level, dk dynakube.DynaKube) { if dk.NeedsOneAgent() { - builder.WithStep("oneagent started", level, oneagent.WaitForDaemonset(dk)) + builder.WithStep("oneagent started", level, oneagent.WaitForDaemonset(dk.OneAgentDaemonsetName(), dk.Namespace)) } builder.WithStep( fmt.Sprintf("'%s' dynakube phase changes to 'Running'", dk.Name), diff --git a/test/helpers/components/oneagent/daemonset.go b/test/helpers/components/oneagent/daemonset.go index c5e94a3ee5..c808bbbe3e 100644 --- a/test/helpers/components/oneagent/daemonset.go +++ b/test/helpers/components/oneagent/daemonset.go @@ -5,7 +5,6 @@ package oneagent import ( "context" - dynakubev1beta1 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta1/dynakube" //nolint dynakubev1beta3 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/daemonset" @@ -16,16 +15,12 @@ import ( "sigs.k8s.io/e2e-framework/pkg/features" ) -func WaitForDaemonset(dk dynakubev1beta3.DynaKube) features.Func { - return helpers.ToFeatureFunc(daemonset.WaitFor(dk.OneAgentDaemonsetName(), dk.Namespace), true) +func WaitForDaemonset(dsName, namespace string) features.Func { + return helpers.ToFeatureFunc(daemonset.WaitFor(dsName, namespace), true) } -func WaitFromDaemonSetPrevDk(prevDk dynakubev1beta1.DynaKube) features.Func { - return helpers.ToFeatureFunc(daemonset.WaitFor(prevDk.OneAgentDaemonsetName(), prevDk.Namespace), true) -} - -func WaitForDaemonSetPodsDeletion(dk dynakubev1beta3.DynaKube) features.Func { - return pod.WaitForPodsDeletionWithOwner(dk.OneAgentDaemonsetName(), dk.Namespace) +func WaitForDaemonSetPodsDeletion(dsName, namespace string) features.Func { + return pod.WaitForPodsDeletionWithOwner(dsName, namespace) } func Get(ctx context.Context, resource *resources.Resources, dk dynakubev1beta3.DynaKube) (appsv1.DaemonSet, error) { diff --git a/test/scenarios/release/release_test.go b/test/scenarios/release/release_test.go index c6d29aaf98..4b74884363 100644 --- a/test/scenarios/release/release_test.go +++ b/test/scenarios/release/release_test.go @@ -20,7 +20,7 @@ var ( cfg *envconf.Config ) -const releaseTag = "1.2.2" +const releaseTag = "1.3.2" func TestMain(m *testing.M) { cfg = environment.GetStandardKubeClusterEnvConfig() From 69904aaf64bbd042bb431a1ce79c048c3a98e706 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:49:43 +0100 Subject: [PATCH 038/426] [Automatic] Update index for refs/tags/v1.4.0 release (#4173) Co-authored-by: StefanHauth --- config/helm/repos/stable/index.yaml | 24 ++++- config/helm/repos/stable/index.yaml.previous | 106 +++++++++++++++++-- 2 files changed, 120 insertions(+), 10 deletions(-) diff --git a/config/helm/repos/stable/index.yaml b/config/helm/repos/stable/index.yaml index 739353b5dc..ad5f93fb80 100644 --- a/config/helm/repos/stable/index.yaml +++ b/config/helm/repos/stable/index.yaml @@ -1,6 +1,28 @@ apiVersion: v1 entries: dynatrace-operator: + - apiVersion: v2 + appVersion: 1.4.0 + created: '2024-12-09T09:04:42.588691061Z' + description: The Dynatrace Operator Helm chart for Kubernetes and OpenShift + digest: d09c178806648400d76955a4c0af249cf769016eda768899f4ba5a700e1cdc58 + home: https://www.dynatrace.com/ + icon: https://assets.dynatrace.com/global/resources/Signet_Logo_RGB_CP_512x512px.png + kubeVersion: '>=1.19.0-0' + maintainers: + - email: marcell.sevcsik@dynatrace.com + name: 0sewa0 + - email: christoph.muellner@dynatrace.com + name: chrismuellner + - email: lukas.hinterreiter@dynatrace.com + name: luhi-DT + name: dynatrace-operator + sources: + - https://github.com/Dynatrace/dynatrace-operator + type: application + urls: + - https://github.com/Dynatrace/dynatrace-operator/releases/download/v1.4.0/dynatrace-operator-1.4.0.tgz + version: 1.4.0 - apiVersion: v2 appVersion: 1.3.2 created: '2024-10-24T11:28:10.332056983Z' @@ -1038,4 +1060,4 @@ entries: urls: - https://raw.githubusercontent.com/Dynatrace/helm-charts/master/repos/stable/dynatrace-operator-0.1.0.tgz version: 0.1.0 -generated: '2024-10-31T07:13:31.055858571Z' +generated: '2024-12-09T09:04:42.585436968Z' diff --git a/config/helm/repos/stable/index.yaml.previous b/config/helm/repos/stable/index.yaml.previous index 60252e85b7..739353b5dc 100644 --- a/config/helm/repos/stable/index.yaml.previous +++ b/config/helm/repos/stable/index.yaml.previous @@ -1,6 +1,94 @@ apiVersion: v1 entries: dynatrace-operator: + - apiVersion: v2 + appVersion: 1.3.2 + created: '2024-10-24T11:28:10.332056983Z' + description: The Dynatrace Operator Helm chart for Kubernetes and OpenShift + digest: 81d6a0741113147b425fb41ce38933fb0697a56bb8f65bb9c67dccda33ae4507 + home: https://www.dynatrace.com/ + icon: https://assets.dynatrace.com/global/resources/Signet_Logo_RGB_CP_512x512px.png + kubeVersion: '>=1.19.0-0' + maintainers: + - email: marcell.sevcsik@dynatrace.com + name: 0sewa0 + - email: christoph.muellner@dynatrace.com + name: chrismuellner + - email: lukas.hinterreiter@dynatrace.com + name: luhi-DT + name: dynatrace-operator + sources: + - https://github.com/Dynatrace/dynatrace-operator + type: application + urls: + - https://github.com/Dynatrace/dynatrace-operator/releases/download/v1.3.2/dynatrace-operator-1.3.2.tgz + version: 1.3.2 + - apiVersion: v2 + appVersion: 1.3.1 + created: '2024-10-14T06:47:34.922235129Z' + description: The Dynatrace Operator Helm chart for Kubernetes and OpenShift + digest: 3cfb2e75151a07ef484fb5b431e8d0337b9468be0803c5bfea8ba091ffdded59 + home: https://www.dynatrace.com/ + icon: https://assets.dynatrace.com/global/resources/Signet_Logo_RGB_CP_512x512px.png + kubeVersion: '>=1.19.0-0' + maintainers: + - email: marcell.sevcsik@dynatrace.com + name: 0sewa0 + - email: christoph.muellner@dynatrace.com + name: chrismuellner + - email: lukas.hinterreiter@dynatrace.com + name: luhi-DT + name: dynatrace-operator + sources: + - https://github.com/Dynatrace/dynatrace-operator + type: application + urls: + - https://github.com/Dynatrace/dynatrace-operator/releases/download/v1.3.1/dynatrace-operator-1.3.1.tgz + version: 1.3.1 + - apiVersion: v2 + appVersion: 1.3.0 + created: '2024-09-23T13:14:16.373659553Z' + description: The Dynatrace Operator Helm chart for Kubernetes and OpenShift + digest: b4e29af761babcb8fb12737d4ffca1875b45abc682085b379666a3657acc97b1 + home: https://www.dynatrace.com/ + icon: https://assets.dynatrace.com/global/resources/Signet_Logo_RGB_CP_512x512px.png + kubeVersion: '>=1.19.0-0' + maintainers: + - email: marcell.sevcsik@dynatrace.com + name: 0sewa0 + - email: christoph.muellner@dynatrace.com + name: chrismuellner + - email: lukas.hinterreiter@dynatrace.com + name: luhi-DT + name: dynatrace-operator + sources: + - https://github.com/Dynatrace/dynatrace-operator + type: application + urls: + - https://github.com/Dynatrace/dynatrace-operator/releases/download/v1.3.0/dynatrace-operator-1.3.0.tgz + version: 1.3.0 + - apiVersion: v2 + appVersion: 1.2.3 + created: '2024-10-31T07:13:31.057866792Z' + description: The Dynatrace Operator Helm chart for Kubernetes and OpenShift + digest: d2e190574c30372f9d9c799ea6100d773a6ccfc581ba1fca163afba1ea114519 + home: https://www.dynatrace.com/ + icon: https://assets.dynatrace.com/global/resources/Signet_Logo_RGB_CP_512x512px.png + kubeVersion: '>=1.19.0-0' + maintainers: + - email: marcell.sevcsik@dynatrace.com + name: 0sewa0 + - email: christoph.muellner@dynatrace.com + name: chrismuellner + - email: lukas.hinterreiter@dynatrace.com + name: luhi-DT + name: dynatrace-operator + sources: + - https://github.com/Dynatrace/dynatrace-operator + type: application + urls: + - https://github.com/Dynatrace/dynatrace-operator/releases/download/v1.2.3/dynatrace-operator-1.2.3.tgz + version: 1.2.3 - apiVersion: v2 appVersion: 1.2.2 created: '2024-08-08T11:38:53.628185919Z' @@ -98,18 +186,18 @@ entries: icon: https://assets.dynatrace.com/global/resources/Signet_Logo_RGB_CP_512x512px.png kubeVersion: '>=1.19.0-0' maintainers: - - email: marcell.sevcsik@dynatrace.com - name: 0sewa0 - - email: christoph.muellner@dynatrace.com - name: chrismuellner - - email: lukas.hinterreiter@dynatrace.com - name: luhi-DT + - email: marcell.sevcsik@dynatrace.com + name: 0sewa0 + - email: christoph.muellner@dynatrace.com + name: chrismuellner + - email: lukas.hinterreiter@dynatrace.com + name: luhi-DT name: dynatrace-operator sources: - - https://github.com/Dynatrace/dynatrace-operator + - https://github.com/Dynatrace/dynatrace-operator type: application urls: - - https://github.com/Dynatrace/dynatrace-operator/releases/download/v1.1.0/dynatrace-operator-1.1.0.tgz + - https://github.com/Dynatrace/dynatrace-operator/releases/download/v1.1.0/dynatrace-operator-1.1.0.tgz version: 1.1.0 - apiVersion: v2 appVersion: 1.0.1 @@ -950,4 +1038,4 @@ entries: urls: - https://raw.githubusercontent.com/Dynatrace/helm-charts/master/repos/stable/dynatrace-operator-0.1.0.tgz version: 0.1.0 -generated: '2024-08-08T11:38:53.625316605Z' +generated: '2024-10-31T07:13:31.055858571Z' From 2c0444e6957416288183d7752f6f32e0e7cfe765 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 18:47:55 +0000 Subject: [PATCH 039/426] chore(deps): update dependency redhat-openshift-ecosystem/openshift-preflight to v1.11.0 (main) (#4177) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/preflight/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/preflight/action.yaml b/.github/actions/preflight/action.yaml index 232a386734..e817781b79 100644 --- a/.github/actions/preflight/action.yaml +++ b/.github/actions/preflight/action.yaml @@ -29,7 +29,7 @@ runs: RHCC_APITOKEN: ${{ inputs.pyxis-api-token }} RHCC_PROJECT_ID: ${{ inputs.redhat-project-id }} # renovate depName=redhat-openshift-ecosystem/openshift-preflight - PREFLIGHT_VERSION: 1.10.2 + PREFLIGHT_VERSION: 1.11.0 IMAGE_URI: ${{ inputs.registry }}/${{ inputs.repository }}:${{ inputs.version }} run: | hack/build/ci/preflight.sh "${{ env.PREFLIGHT_VERSION }}" "${{ env.IMAGE_URI}}" "${{ inputs.report-name }}" From 8a4259621ad8dbe9a4e93537c47416063c4354ef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:33:35 +0000 Subject: [PATCH 040/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1733767087 (main) (#4179) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 80820fa56e..a993e0ff3e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS=" go build -tags "${GO_BUILD_TAGS}" -trimpath -ldflags="${GO_LINKER_ARGS}" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ -FROM registry.access.redhat.com/ubi9-micro:9.5-1733126338@sha256:a410623c2b8e9429f9606af821be0231fef2372bd0f5f853fbe9743a0ddf7b34 AS base +FROM registry.access.redhat.com/ubi9-micro:9.5-1733767087@sha256:111395a0b54d220c4ad821602a4a28807d6c4fb2feb19b43a6468a9d5f257463 AS base FROM registry.access.redhat.com/ubi9:9.5-1732804088@sha256:1057dab827c782abcfb9bda0c3900c0966b5066e671d54976a7bcb3a2d1a5e53 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From accd1c77604868160db53147c53048fac11356d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 01:52:03 +0000 Subject: [PATCH 041/426] fix(deps): update module github.com/docker/cli to v27.4.0+incompatible (main) (#4178) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e73e1a8035..417c9ba78b 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.3 require ( github.com/container-storage-interface/spec v1.11.0 - github.com/docker/cli v27.3.1+incompatible + github.com/docker/cli v27.4.0+incompatible github.com/evanphx/json-patch v5.9.0+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.2 diff --git a/go.sum b/go.sum index d282d778f3..47ac354faf 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= -github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.4.0+incompatible h1:/nJzWkcI1MDMN+U+px/YXnQWJqnu4J+QKGTfD6ptiTc= +github.com/docker/cli v27.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= From bb134cb76670b4fd640af6b50d999e72da78eb97 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Tue, 10 Dec 2024 08:53:03 +0100 Subject: [PATCH 042/426] Add automountServiceAccountToken: true to fullstack OA serviceAccount (#4176) --- .../oneagent/serviceaccount-oneagent.yaml | 2 +- .../serviceaccount-oneagent_test.yaml | 29 +++++++++++++++---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/config/helm/chart/default/templates/Common/oneagent/serviceaccount-oneagent.yaml b/config/helm/chart/default/templates/Common/oneagent/serviceaccount-oneagent.yaml index bad574c2bb..bae5afe682 100644 --- a/config/helm/chart/default/templates/Common/oneagent/serviceaccount-oneagent.yaml +++ b/config/helm/chart/default/templates/Common/oneagent/serviceaccount-oneagent.yaml @@ -23,5 +23,5 @@ metadata: {{- end }} labels: {{- include "dynatrace-operator.oneagentLabels" . | nindent 4 }} -automountServiceAccountToken: false +automountServiceAccountToken: {{.Values.rbac.logMonitoring.create}} {{ end }} diff --git a/config/helm/chart/default/tests/Common/oneagent/serviceaccount-oneagent_test.yaml b/config/helm/chart/default/tests/Common/oneagent/serviceaccount-oneagent_test.yaml index 021b1f83f2..ca37b2a6c9 100644 --- a/config/helm/chart/default/tests/Common/oneagent/serviceaccount-oneagent_test.yaml +++ b/config/helm/chart/default/tests/Common/oneagent/serviceaccount-oneagent_test.yaml @@ -2,7 +2,7 @@ suite: test serviceaccount for oneagent templates: - Common/oneagent/serviceaccount-oneagent.yaml tests: - - it: should exist + - it: should exist on kubernetes set: platform: kubernetes asserts: @@ -16,8 +16,7 @@ tests: value: NAMESPACE - isNull: path: imagePullSecrets - - - it: should exist + - it: should exist on openshift set: platform: openshift asserts: @@ -26,9 +25,9 @@ tests: - equal: path: metadata.name value: dynatrace-dynakube-oneagent - - - it: should exist + - it: should add user annotations set: + rbac.oneAgent.create: true rbac.oneAgent.annotations: test: test asserts: @@ -44,3 +43,23 @@ tests: asserts: - hasDocuments: count: 0 + - it: should have automountServiceAccountToken set to TRUE, incase of log-monitoring is available + set: + rbac.oneAgent.create: true + rbac.logMonitoring.create: true + asserts: + - isKind: + of: ServiceAccount + - equal: + path: automountServiceAccountToken + value: true + - it: should have automountServiceAccountToken set to FALSE, incase of log-monitoring is NOT available + set: + rbac.oneAgent.create: true + rbac.logMonitoring.create: false + asserts: + - isKind: + of: ServiceAccount + - equal: + path: automountServiceAccountToken + value: false From 72ba762fdfcec6323a628e77c22ff07bfc2249f3 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Tue, 10 Dec 2024 15:05:10 +0100 Subject: [PATCH 043/426] Check that generated docs and mocks are up-to-date (#4172) --- .github/workflows/ci.yaml | 37 +- .mockery.yaml | 1 + doc/api/dynakube-api-ref.md | 26 +- doc/api/feature-flags.md | 4 +- doc/e2e/features.md | 346 +++++++++--------- hack/doc/gen_e2e_features.sh | 5 +- hack/doc/gen_feature_flags.sh | 2 +- test/mocks/cmd/config/provider.go | 2 +- test/mocks/pkg/clients/dynatrace/client.go | 3 +- test/mocks/pkg/clients/edgeconnect/client.go | 2 +- .../dynakube/dynatraceclient/builder.go | 2 +- .../dynakube/version/status_updater.go | 16 +- test/mocks/pkg/util/builder/modifier.go | 12 +- .../controller-runtime/pkg/manager/manager.go | 24 +- 14 files changed, 244 insertions(+), 238 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e0664a7064..d0c0374925 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -113,11 +113,27 @@ jobs: - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 with: go-version-file: "${{ github.workspace }}/go.mod" - - name: Check deepcopy files + - name: Set up Helm + uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + - name: Check deepcopy files are up-to-date id: deepcopy run: | make manifests/deepcopy git diff --exit-code + - name: Check automatic generated docs are up-to-date + id: doc + run: | + make doc + git diff --exit-code + - name: Check mocks are up-to-date + id: mockery + run: | + make prerequisites/mockery + make go/gen_mocks + git diff --exit-code security: name: Code security scanning alerts @@ -145,25 +161,6 @@ jobs: # renovate depName=github.com/igorshubovych/markdownlint-cli version: v0.43.0 - check-uncommitted-doc-changes: - name: Check uncommitted changes in api docs action - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 - with: - go-version-file: "${{ github.workspace }}/go.mod" - - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - - name: Run make doc to see uncommitted changes - run: make doc - - name: Check for uncommitted changes - id: check-changes - uses: mskri/check-uncommitted-changes-action@2b152539dd033c3a26e0dd1d8b9a0c8e4d3a8a19 # v1.0.1 - - name: Evaluate if there are changes - if: steps.check-changes.outputs.outcome == failure() - run: echo "There are uncommitted changes" - prepare: name: Prepare properties runs-on: ubuntu-latest diff --git a/.mockery.yaml b/.mockery.yaml index 5b7a2e4aa2..6810b6859e 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -1,6 +1,7 @@ quiet: False disable-version-string: True with-expecter: True +issue-845-fix: True mockname: "{{.InterfaceName}}" filename: "{{.InterfaceName | snakecase}}.go" outpkg: mocks diff --git a/doc/api/dynakube-api-ref.md b/doc/api/dynakube-api-ref.md index b7b913e9de..9a28cdcdfe 100644 --- a/doc/api/dynakube-api-ref.md +++ b/doc/api/dynakube-api-ref.md @@ -10,7 +10,6 @@ |`enableIstio`|When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding
VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate.
Disabled by default.|-|boolean| |`extensions`|When an (empty) ExtensionsSpec is provided, the extensions related components (extensions controller and extensions collector)
are deployed by the operator.|-|object| |`kspm`|General configuration about the KSPM feature.|-|object| -|`logMonitoring`|General configuration about the LogMonitoring feature.|-|object| |`networkZone`|Sets a network zone for the OneAgent and ActiveGate pods.|-|string| |`proxy`|Set custom proxy settings either directly or from a secret with the field proxy.
Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents.|-|object| |`skipCertCheck`|Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster.
Set to true if you want to skip certification validation checks.|-|boolean| @@ -43,6 +42,12 @@ |`tolerations`|Set tolerations for the ActiveGate pods|-|array| |`topologySpreadConstraints`|Adds TopologySpreadConstraints for the ActiveGate pods|-|array| +### .spec.logMonitoring + +|Parameter|Description|Default value|Data type| +|:-|:-|:-|:-| +|`ingestRuleMatchers`||-|array| + ### .spec.metadataEnrichment |Parameter|Description|Default value|Data type| @@ -55,7 +60,7 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| |`annotations`|Add custom OneAgent annotations.|-|object| -|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().
For the list of limitations, see Limitations (For available options, see Linux custom installation ().|-|array| |`autoUpdate`|Disables automatic restarts of OneAgent pods in case a new version is available ().
Enabled by default.|-|boolean| |`dnsPolicy`|Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy ().|-|string| |`env`|Set additional environment variables for the OneAgent pods.|-|array| @@ -87,7 +92,7 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| |`annotations`|Add custom OneAgent annotations.|-|object| -|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().
For the list of limitations, see Limitations (For available options, see Linux custom installation ().|-|array| |`autoUpdate`|Disables automatic restarts of OneAgent pods in case a new version is available ().
Enabled by default.|-|boolean| |`dnsPolicy`|Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy ().|-|string| |`env`|Set additional environment variables for the OneAgent pods.|-|array| @@ -105,7 +110,7 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| |`annotations`|Add custom OneAgent annotations.|-|object| -|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().
For the list of limitations, see Limitations (For available options, see Linux custom installation ().|-|array| |`autoUpdate`|Disables automatic restarts of OneAgent pods in case a new version is available ().
Enabled by default.|-|boolean| |`codeModulesImage`|Use a custom OneAgent CodeModule image to download binaries.|-|string| |`dnsPolicy`|Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy ().|-|string| @@ -128,7 +133,6 @@ |`codeModulesImage`|Use a custom OneAgent CodeModule image to download binaries.|-|string| |`initResources`|Define resources requests and limits for the initContainer. For details, see Managing resources for containers
().|-|object| |`namespaceSelector`|Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject.
For more information, see Configure monitoring for namespaces and pods (the affinity expressions specified by this field, but it may choose
a node that violates one or more of the expressions. The node that is
most preferred is the one with the greatest sum of weights, i.e.|-|array| -|`requiredDuringSchedulingIgnoredDuringExecution`|If the affinity requirements specified by this field are not met at
scheduling time, the pod will not be scheduled onto the node.
If the affinity requirements specified by this field cease to be met
at some point during pod execution (e.g. due to an update), the system
may or may not try to eventually evict the pod from its node.|-|object| +|`requiredDuringSchedulingIgnoredDuringExecution`|If the affinity requirements specified by this field are not met at
scheduling time, the pod will not be scheduled onto the node.
If the affinity requirements specified by this field cease to be met
at some point during pod execution (e.g.|-|object| ### .spec.templates.kspmNodeConfigurationCollector.updateStrategy @@ -216,11 +220,11 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| |`accessModes`|accessModes contains the desired access modes the volume should have.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1|-|array| -|`dataSource`|dataSource field can be used to specify either:
* An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)
* An existing PVC (PersistentVolumeClaim)
If the provisioner or an external controller can support the specified data source,
it will create a new volume based on the contents of the specified data source.|-|object| -|`resources`|resources represents the minimum resources the volume should have.
If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.|-|object| +|`dataSource`|dataSource field can be used to specify either:
* An existing VolumeSnapshot object (snapshot.storage.k8s.|-|object| +|`resources`|resources represents the minimum resources the volume should have.
If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.|-|object| |`selector`|selector is a label query over volumes to consider for binding.|-|object| |`storageClassName`|storageClassName is the name of the StorageClass required by the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1|-|string| -|`volumeAttributesClassName`|volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
it can be changed after the claim is created.|-|string| +|`volumeAttributesClassName`|volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass.|-|string| |`volumeMode`|volumeMode defines what type of volume is required by the claim.
Value of Filesystem is implied when not included in claim spec.|-|string| |`volumeName`|volumeName is the binding reference to the PersistentVolume backing this claim.|-|string| @@ -228,8 +232,8 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`maxSurge`|The maximum number of nodes with an existing available DaemonSet pod that
can have an updated DaemonSet pod during during an update.
Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
This can not be 0 if MaxUnavailable is 0.
Absolute number is calculated from percentage by rounding up to a minimum of 1.|-|integer or string| -|`maxUnavailable`|The maximum number of DaemonSet pods that can be unavailable during the
update. Value can be an absolute number (ex: 5) or a percentage of total
number of DaemonSet pods at the start of the update (ex: 10%). Absolute
number is calculated from percentage by rounding up.
This cannot be 0 if MaxSurge is 0
Default value is 1.|-|integer or string| +|`maxSurge`|The maximum number of nodes with an existing available DaemonSet pod that
can have an updated DaemonSet pod during during an update.
Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
This can not be 0 if MaxUnavailable is 0.|-|integer or string| +|`maxUnavailable`|The maximum number of DaemonSet pods that can be unavailable during the
update. Value can be an absolute number (ex: 5) or a percentage of total
number of DaemonSet pods at the start of the update (ex: 10%). Absolute
number is calculated from percentage by rounding up.|-|integer or string| ### .spec.templates.extensionExecutionController.persistentVolumeClaim.dataSourceRef diff --git a/doc/api/feature-flags.md b/doc/api/feature-flags.md index 09c8560081..ebdd9d87cb 100644 --- a/doc/api/feature-flags.md +++ b/doc/api/feature-flags.md @@ -42,6 +42,7 @@ const ( AnnotationFeatureOneAgentMaxUnavailable = AnnotationFeaturePrefix + "oneagent-max-unavailable" AnnotationFeatureOneAgentInitialConnectRetry = AnnotationFeaturePrefix + "oneagent-initial-connect-retry-ms" AnnotationFeatureRunOneAgentContainerPrivileged = AnnotationFeaturePrefix + "oneagent-privileged" + AnnotationFeatureOneAgentSkipLivenessProbe = AnnotationFeaturePrefix + "oneagent-skip-liveness-probe" AnnotationFeatureIgnoreUnknownState = AnnotationFeaturePrefix + "ignore-unknown-state" AnnotationFeatureIgnoredNamespaces = AnnotationFeaturePrefix + "ignored-namespaces" @@ -50,7 +51,6 @@ const ( AnnotationInjectionFailurePolicy = AnnotationFeaturePrefix + "injection-failure-policy" AnnotationFeatureInitContainerSeccomp = AnnotationFeaturePrefix + "init-container-seccomp-profile" AnnotationFeatureEnforcementMode = AnnotationFeaturePrefix + "enforcement-mode" - AnnotationFeatureReadOnlyOneAgent = AnnotationFeaturePrefix + "oneagent-readonly-host-fs" // CSI. AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" @@ -72,7 +72,7 @@ const ( -## func [MountAttemptsToTimeout]() +## func [MountAttemptsToTimeout]() ```go func MountAttemptsToTimeout(maxAttempts int) string diff --git a/doc/e2e/features.md b/doc/e2e/features.md index e7fb8e91a1..3a0a6b1d00 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -26,100 +26,6 @@ Setup: OneAgent disabled Verification if ActiveGate is rolled out successfully. All ActiveGate capabilities are enabled in Dynakube. The test checks if ActiveGate is able to communicate over a http proxy, related *Gateway* modules are active and that the *Gateway* process is reachable via *Gateway service*. -# edgeconnect - -```go -import "github.com/Dynatrace/dynatrace-operator/test/features/edgeconnect" -``` - -## Index - -- [func AutomationModeFeature(t *testing.T) features.Feature](<#AutomationModeFeature>) -- [func NormalModeFeature(t *testing.T) features.Feature](<#NormalModeFeature>) -- [func ProvisionerModeFeature(t *testing.T) features.Feature](<#ProvisionerModeFeature>) - - - -## func [AutomationModeFeature]() - -```go -func AutomationModeFeature(t *testing.T) features.Feature -``` - - - -## func [NormalModeFeature]() - -```go -func NormalModeFeature(t *testing.T) features.Feature -``` - - - -## func [ProvisionerModeFeature]() - -```go -func ProvisionerModeFeature(t *testing.T) features.Feature -``` - -# classic - -```go -import "github.com/Dynatrace/dynatrace-operator/test/features/classic" -``` - -## Index - -- [func Feature(t *testing.T) features.Feature](<#Feature>) - - - -## func [Feature]() - -```go -func Feature(t *testing.T) features.Feature -``` - -### ClassicFullStack deployment - -Verification of classic-fullstack deployment. Sample application Deployment is installed and restarted to check if OneAgent is injected and can communicate with the *Dynatrace Cluster*. - -# switch_modes - -```go -import "github.com/Dynatrace/dynatrace-operator/test/features/classic/switch_modes" -``` - -## Index - -- [func Feature(t *testing.T) features.Feature](<#Feature>) - - - -## func [Feature]() - -```go -func Feature(t *testing.T) features.Feature -``` - -# extensions - -```go -import "github.com/Dynatrace/dynatrace-operator/test/features/extensions" -``` - -## Index - -- [func Feature(t *testing.T) features.Feature](<#Feature>) - - - -## func [Feature]() - -```go -func Feature(t *testing.T) features.Feature -``` - # applicationmonitoring ```go @@ -135,7 +41,7 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/applicationmonitor -## func [LabelVersionDetection]() +## func [LabelVersionDetection]() ```go func LabelVersionDetection(t *testing.T) features.Feature @@ -147,7 +53,7 @@ Verification that build labels are created and set accordingly. The test checks: -## func [MetadataEnrichment]() +## func [MetadataEnrichment]() ```go func MetadataEnrichment(t *testing.T) features.Feature @@ -157,7 +63,7 @@ Verification of the metadata enrichment part of the operator. The test checks th -## func [ReadOnlyCSIVolume]() +## func [ReadOnlyCSIVolume]() ```go func ReadOnlyCSIVolume(t *testing.T) features.Feature @@ -173,10 +79,10 @@ func WithoutCSI(t *testing.T) features.Feature ApplicationMonitoring deployment without CSI driver -# publicregistry +# classic ```go -import "github.com/Dynatrace/dynatrace-operator/test/features/publicregistry" +import "github.com/Dynatrace/dynatrace-operator/test/features/classic" ``` ## Index @@ -185,53 +91,34 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/publicregistry" -## func [Feature]() +## func [Feature]() ```go func Feature(t *testing.T) features.Feature ``` -Feature defines the e2e test to verify that public-registry images can be deployed by the operator and that they function This includes: - -- ActiveGate StatefulSet gets ready -- CodeModules can be downloaded and mounted -- OneAgent DaemonSet gets ready +### ClassicFullStack deployment -It determines the latest version of each image using the registry. +Verification of classic-fullstack deployment. Sample application Deployment is installed and restarted to check if OneAgent is injected and can communicate with the *Dynatrace Cluster*. -# support_archive +# switch_modes ```go -import "github.com/Dynatrace/dynatrace-operator/test/features/support_archive" +import "github.com/Dynatrace/dynatrace-operator/test/features/classic/switch_modes" ``` ## Index - [func Feature(t *testing.T) features.Feature](<#Feature>) -- [type CustomResources](<#CustomResources>) -## func [Feature]() +## func [Feature]() ```go func Feature(t *testing.T) features.Feature ``` -Setup: DTO with CSI driver - -Verification if support-archive package created by the support-archive command and printed to the standard output is a valid tar.gz package and contains required *operator-version.txt* file. - - - -## type [CustomResources]() - -```go -type CustomResources struct { - // contains filtered or unexported fields -} -``` - # cloudnative ```go @@ -286,50 +173,6 @@ func AssessSampleInitContainers(builder *features.FeatureBuilder, sampleApp *sam func DefaultCloudNativeSpec() *dynakube.CloudNativeFullStackSpec ``` -# network_problems - -```go -import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/network_problems" -``` - -## Index - -- [func ResilienceFeature(t *testing.T) features.Feature](<#ResilienceFeature>) - - - -## func [ResilienceFeature]() - -```go -func ResilienceFeature(t *testing.T) features.Feature -``` - -Prerequisites: istio service mesh - -Setup: CloudNative deployment with CSI driver - -Verification that the CSI driver is able to recover from network issues, when using cloudNative and code modules image. - -Connectivity for csi driver pods is restricted to the local k8s cluster (no outside connections allowed) and sample application is installed. The test checks if init container was attached, run successfully and that the sample pods are up and running. - -# upgrade - -```go -import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/upgrade" -``` - -## Index - -- [func Feature(t *testing.T) features.Feature](<#Feature>) - - - -## func [Feature]() - -```go -func Feature(t *testing.T) features.Feature -``` - # codemodules ```go @@ -346,7 +189,7 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/codemo -## func [InstallFromImage]() +## func [InstallFromImage]() ```go func InstallFromImage(t *testing.T) features.Feature @@ -356,7 +199,7 @@ Verification that the storage in the CSI driver directory does not increase when -## func [WithProxy]() +## func [WithProxy]() ```go func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature @@ -372,7 +215,7 @@ Connectivity in the dynatrace namespace and sample application namespace is rest -## func [WithProxyAndAGCert]() +## func [WithProxyAndAGCert]() ```go func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature @@ -380,7 +223,7 @@ func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature -## func [WithProxyCA]() +## func [WithProxyCA]() ```go func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature @@ -388,7 +231,7 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature -## func [WithProxyCAAndAGCert]() +## func [WithProxyCAAndAGCert]() ```go func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature @@ -454,6 +297,32 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/disabl func Feature(t *testing.T) features.Feature ``` +# network_problems + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/network_problems" +``` + +## Index + +- [func ResilienceFeature(t *testing.T) features.Feature](<#ResilienceFeature>) + + + +## func [ResilienceFeature]() + +```go +func ResilienceFeature(t *testing.T) features.Feature +``` + +Prerequisites: istio service mesh + +Setup: CloudNative deployment with CSI driver + +Verification that the CSI driver is able to recover from network issues, when using cloudNative and code modules image. + +Connectivity for csi driver pods is restricted to the local k8s cluster (no outside connections allowed) and sample application is installed. The test checks if init container was attached, run successfully and that the sample pods are up and running. + # switch_modes ```go @@ -472,6 +341,24 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/switch func Feature(t *testing.T) features.Feature ``` +# upgrade + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/upgrade" +``` + +## Index + +- [func Feature(t *testing.T) features.Feature](<#Feature>) + + + +## func [Feature]() + +```go +func Feature(t *testing.T) features.Feature +``` + # consts ```go @@ -497,3 +384,116 @@ const ( EecImageTag = "1.303.0.20240930-183404" ) ``` + +# edgeconnect + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/edgeconnect" +``` + +## Index + +- [func AutomationModeFeature(t *testing.T) features.Feature](<#AutomationModeFeature>) +- [func NormalModeFeature(t *testing.T) features.Feature](<#NormalModeFeature>) +- [func ProvisionerModeFeature(t *testing.T) features.Feature](<#ProvisionerModeFeature>) + + + +## func [AutomationModeFeature]() + +```go +func AutomationModeFeature(t *testing.T) features.Feature +``` + + + +## func [NormalModeFeature]() + +```go +func NormalModeFeature(t *testing.T) features.Feature +``` + + + +## func [ProvisionerModeFeature]() + +```go +func ProvisionerModeFeature(t *testing.T) features.Feature +``` + +# extensions + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/extensions" +``` + +## Index + +- [func Feature(t *testing.T) features.Feature](<#Feature>) + + + +## func [Feature]() + +```go +func Feature(t *testing.T) features.Feature +``` + +# publicregistry + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/publicregistry" +``` + +## Index + +- [func Feature(t *testing.T) features.Feature](<#Feature>) + + + +## func [Feature]() + +```go +func Feature(t *testing.T) features.Feature +``` + +Feature defines the e2e test to verify that public-registry images can be deployed by the operator and that they function This includes: + +- ActiveGate StatefulSet gets ready +- CodeModules can be downloaded and mounted +- OneAgent DaemonSet gets ready + +It determines the latest version of each image using the registry. + +# support_archive + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/support_archive" +``` + +## Index + +- [func Feature(t *testing.T) features.Feature](<#Feature>) +- [type CustomResources](<#CustomResources>) + + + +## func [Feature]() + +```go +func Feature(t *testing.T) features.Feature +``` + +Setup: DTO with CSI driver + +Verification if support-archive package created by the support-archive command and printed to the standard output is a valid tar.gz package and contains required *operator-version.txt* file. + + + +## type [CustomResources]() + +```go +type CustomResources struct { + // contains filtered or unexported fields +} +``` diff --git a/hack/doc/gen_e2e_features.sh b/hack/doc/gen_e2e_features.sh index b6a54a0120..d8346242e8 100755 --- a/hack/doc/gen_e2e_features.sh +++ b/hack/doc/gen_e2e_features.sh @@ -9,10 +9,13 @@ output="" # get dirs containing doc packages doc_dir_subdirs=$(find $doc_dir -type d) +# order dirs alphabetically +doc_dir_subdirs=$(echo "$doc_dir_subdirs" | sort) + # append all gomarkdoc outputs in a single variable for dir in $doc_dir_subdirs; do if [ "$dir" != "$doc_dir" ]; then - output="${output}$(GOARCH="e2e" gomarkdoc "${dir}" | sed 's/\\//g')" + output="${output}$(GOARCH="e2e" gomarkdoc --repository.url "https://github.com/Dynatrace/dynatrace-operator" --repository.path "/" --repository.default-branch "main" "${dir}" | sed 's/\\//g')" # remove gomarkdoc footer output=$(echo "${output}" | sed '$d') fi diff --git a/hack/doc/gen_feature_flags.sh b/hack/doc/gen_feature_flags.sh index 2c51c98e3d..cc4436725b 100755 --- a/hack/doc/gen_feature_flags.sh +++ b/hack/doc/gen_feature_flags.sh @@ -10,7 +10,7 @@ output="" mkdir ${doc_dir}/tmp cp ${doc_dir}/feature_flags.go ${doc_dir}/tmp -output="${output}$(gomarkdoc ${doc_dir}/tmp | sed 's/\\//g')" +output="${output}$(gomarkdoc --repository.url "https://github.com/Dynatrace/dynatrace-operator" --repository.path "/" --repository.default-branch "main" ${doc_dir}/tmp | sed 's/\\//g')" # remove gomarkdoc footer output=$(echo "${output}" | sed '$d') diff --git a/test/mocks/cmd/config/provider.go b/test/mocks/cmd/config/provider.go index d232aff85a..7ee35117e2 100644 --- a/test/mocks/cmd/config/provider.go +++ b/test/mocks/cmd/config/provider.go @@ -20,7 +20,7 @@ func (_m *Provider) EXPECT() *Provider_Expecter { return &Provider_Expecter{mock: &_m.Mock} } -// GetConfig provides a mock function with given fields: +// GetConfig provides a mock function with no fields func (_m *Provider) GetConfig() (*rest.Config, error) { ret := _m.Called() diff --git a/test/mocks/pkg/clients/dynatrace/client.go b/test/mocks/pkg/clients/dynatrace/client.go index 8be5525119..f251e81665 100644 --- a/test/mocks/pkg/clients/dynatrace/client.go +++ b/test/mocks/pkg/clients/dynatrace/client.go @@ -9,6 +9,7 @@ import ( dynatrace "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" logmonitoring "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + mock "github.com/stretchr/testify/mock" ) @@ -478,7 +479,7 @@ func (_c *Client_GetAgentViaInstallerUrl_Call) RunAndReturn(run func(context.Con return _c } -// GetCommunicationHostForClient provides a mock function with given fields: +// GetCommunicationHostForClient provides a mock function with no fields func (_m *Client) GetCommunicationHostForClient() (dynatrace.CommunicationHost, error) { ret := _m.Called() diff --git a/test/mocks/pkg/clients/edgeconnect/client.go b/test/mocks/pkg/clients/edgeconnect/client.go index 050448688a..e662ca436f 100644 --- a/test/mocks/pkg/clients/edgeconnect/client.go +++ b/test/mocks/pkg/clients/edgeconnect/client.go @@ -214,7 +214,7 @@ func (_c *Client_DeleteEdgeConnect_Call) RunAndReturn(run func(string) error) *C return _c } -// GetConnectionSettings provides a mock function with given fields: +// GetConnectionSettings provides a mock function with no fields func (_m *Client) GetConnectionSettings() ([]edgeconnect.EnvironmentSetting, error) { ret := _m.Called() diff --git a/test/mocks/pkg/controllers/dynakube/dynatraceclient/builder.go b/test/mocks/pkg/controllers/dynakube/dynatraceclient/builder.go index 28de949c0c..b14bff93b8 100644 --- a/test/mocks/pkg/controllers/dynakube/dynatraceclient/builder.go +++ b/test/mocks/pkg/controllers/dynakube/dynatraceclient/builder.go @@ -28,7 +28,7 @@ func (_m *Builder) EXPECT() *Builder_Expecter { return &Builder_Expecter{mock: &_m.Mock} } -// Build provides a mock function with given fields: +// Build provides a mock function with no fields func (_m *Builder) Build() (dynatrace.Client, error) { ret := _m.Called() diff --git a/test/mocks/pkg/controllers/dynakube/version/status_updater.go b/test/mocks/pkg/controllers/dynakube/version/status_updater.go index 9876280843..907c7de660 100644 --- a/test/mocks/pkg/controllers/dynakube/version/status_updater.go +++ b/test/mocks/pkg/controllers/dynakube/version/status_updater.go @@ -80,7 +80,7 @@ func (_c *StatusUpdater_CheckForDowngrade_Call) RunAndReturn(run func(string) (b return _c } -// CustomImage provides a mock function with given fields: +// CustomImage provides a mock function with no fields func (_m *StatusUpdater) CustomImage() string { ret := _m.Called() @@ -125,7 +125,7 @@ func (_c *StatusUpdater_CustomImage_Call) RunAndReturn(run func() string) *Statu return _c } -// CustomVersion provides a mock function with given fields: +// CustomVersion provides a mock function with no fields func (_m *StatusUpdater) CustomVersion() string { ret := _m.Called() @@ -170,7 +170,7 @@ func (_c *StatusUpdater_CustomVersion_Call) RunAndReturn(run func() string) *Sta return _c } -// IsAutoUpdateEnabled provides a mock function with given fields: +// IsAutoUpdateEnabled provides a mock function with no fields func (_m *StatusUpdater) IsAutoUpdateEnabled() bool { ret := _m.Called() @@ -215,7 +215,7 @@ func (_c *StatusUpdater_IsAutoUpdateEnabled_Call) RunAndReturn(run func() bool) return _c } -// IsEnabled provides a mock function with given fields: +// IsEnabled provides a mock function with no fields func (_m *StatusUpdater) IsEnabled() bool { ret := _m.Called() @@ -260,7 +260,7 @@ func (_c *StatusUpdater_IsEnabled_Call) RunAndReturn(run func() bool) *StatusUpd return _c } -// IsPublicRegistryEnabled provides a mock function with given fields: +// IsPublicRegistryEnabled provides a mock function with no fields func (_m *StatusUpdater) IsPublicRegistryEnabled() bool { ret := _m.Called() @@ -363,7 +363,7 @@ func (_c *StatusUpdater_LatestImageInfo_Call) RunAndReturn(run func(context.Cont return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *StatusUpdater) Name() string { ret := _m.Called() @@ -408,7 +408,7 @@ func (_c *StatusUpdater_Name_Call) RunAndReturn(run func() string) *StatusUpdate return _c } -// Target provides a mock function with given fields: +// Target provides a mock function with no fields func (_m *StatusUpdater) Target() *status.VersionStatus { ret := _m.Called() @@ -501,7 +501,7 @@ func (_c *StatusUpdater_UseTenantRegistry_Call) RunAndReturn(run func(context.Co return _c } -// ValidateStatus provides a mock function with given fields: +// ValidateStatus provides a mock function with no fields func (_m *StatusUpdater) ValidateStatus() error { ret := _m.Called() diff --git a/test/mocks/pkg/util/builder/modifier.go b/test/mocks/pkg/util/builder/modifier.go index 6086bedf5b..122a1b58eb 100644 --- a/test/mocks/pkg/util/builder/modifier.go +++ b/test/mocks/pkg/util/builder/modifier.go @@ -5,11 +5,11 @@ package mocks import mock "github.com/stretchr/testify/mock" // Modifier is an autogenerated mock type for the Modifier type -type Modifier[T any] struct { +type Modifier[T interface{}] struct { mock.Mock } -type Modifier_Expecter[T any] struct { +type Modifier_Expecter[T interface{}] struct { mock *mock.Mock } @@ -17,7 +17,7 @@ func (_m *Modifier[T]) EXPECT() *Modifier_Expecter[T] { return &Modifier_Expecter[T]{mock: &_m.Mock} } -// Enabled provides a mock function with given fields: +// Enabled provides a mock function with no fields func (_m *Modifier[T]) Enabled() bool { ret := _m.Called() @@ -36,7 +36,7 @@ func (_m *Modifier[T]) Enabled() bool { } // Modifier_Enabled_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Enabled' -type Modifier_Enabled_Call[T any] struct { +type Modifier_Enabled_Call[T interface{}] struct { *mock.Call } @@ -81,7 +81,7 @@ func (_m *Modifier[T]) Modify(_a0 *T) error { } // Modifier_Modify_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Modify' -type Modifier_Modify_Call[T any] struct { +type Modifier_Modify_Call[T interface{}] struct { *mock.Call } @@ -110,7 +110,7 @@ func (_c *Modifier_Modify_Call[T]) RunAndReturn(run func(*T) error) *Modifier_Mo // NewModifier creates a new instance of Modifier. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. -func NewModifier[T any](t interface { +func NewModifier[T interface{}](t interface { mock.TestingT Cleanup(func()) }) *Modifier[T] { diff --git a/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager/manager.go b/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager/manager.go index 8b8ee50c94..6c3dfa9eff 100644 --- a/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager/manager.go +++ b/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager/manager.go @@ -231,7 +231,7 @@ func (_c *Manager_AddReadyzCheck_Call) RunAndReturn(run func(string, healthz.Che return _c } -// Elected provides a mock function with given fields: +// Elected provides a mock function with no fields func (_m *Manager) Elected() <-chan struct{} { ret := _m.Called() @@ -278,7 +278,7 @@ func (_c *Manager_Elected_Call) RunAndReturn(run func() <-chan struct{}) *Manage return _c } -// GetAPIReader provides a mock function with given fields: +// GetAPIReader provides a mock function with no fields func (_m *Manager) GetAPIReader() client.Reader { ret := _m.Called() @@ -325,7 +325,7 @@ func (_c *Manager_GetAPIReader_Call) RunAndReturn(run func() client.Reader) *Man return _c } -// GetCache provides a mock function with given fields: +// GetCache provides a mock function with no fields func (_m *Manager) GetCache() cache.Cache { ret := _m.Called() @@ -372,7 +372,7 @@ func (_c *Manager_GetCache_Call) RunAndReturn(run func() cache.Cache) *Manager_G return _c } -// GetClient provides a mock function with given fields: +// GetClient provides a mock function with no fields func (_m *Manager) GetClient() client.Client { ret := _m.Called() @@ -419,7 +419,7 @@ func (_c *Manager_GetClient_Call) RunAndReturn(run func() client.Client) *Manage return _c } -// GetConfig provides a mock function with given fields: +// GetConfig provides a mock function with no fields func (_m *Manager) GetConfig() *rest.Config { ret := _m.Called() @@ -466,7 +466,7 @@ func (_c *Manager_GetConfig_Call) RunAndReturn(run func() *rest.Config) *Manager return _c } -// GetControllerOptions provides a mock function with given fields: +// GetControllerOptions provides a mock function with no fields func (_m *Manager) GetControllerOptions() config.Controller { ret := _m.Called() @@ -559,7 +559,7 @@ func (_c *Manager_GetEventRecorderFor_Call) RunAndReturn(run func(string) record return _c } -// GetFieldIndexer provides a mock function with given fields: +// GetFieldIndexer provides a mock function with no fields func (_m *Manager) GetFieldIndexer() client.FieldIndexer { ret := _m.Called() @@ -606,7 +606,7 @@ func (_c *Manager_GetFieldIndexer_Call) RunAndReturn(run func() client.FieldInde return _c } -// GetHTTPClient provides a mock function with given fields: +// GetHTTPClient provides a mock function with no fields func (_m *Manager) GetHTTPClient() *http.Client { ret := _m.Called() @@ -653,7 +653,7 @@ func (_c *Manager_GetHTTPClient_Call) RunAndReturn(run func() *http.Client) *Man return _c } -// GetLogger provides a mock function with given fields: +// GetLogger provides a mock function with no fields func (_m *Manager) GetLogger() logr.Logger { ret := _m.Called() @@ -698,7 +698,7 @@ func (_c *Manager_GetLogger_Call) RunAndReturn(run func() logr.Logger) *Manager_ return _c } -// GetRESTMapper provides a mock function with given fields: +// GetRESTMapper provides a mock function with no fields func (_m *Manager) GetRESTMapper() meta.RESTMapper { ret := _m.Called() @@ -745,7 +745,7 @@ func (_c *Manager_GetRESTMapper_Call) RunAndReturn(run func() meta.RESTMapper) * return _c } -// GetScheme provides a mock function with given fields: +// GetScheme provides a mock function with no fields func (_m *Manager) GetScheme() *runtime.Scheme { ret := _m.Called() @@ -792,7 +792,7 @@ func (_c *Manager_GetScheme_Call) RunAndReturn(run func() *runtime.Scheme) *Mana return _c } -// GetWebhookServer provides a mock function with given fields: +// GetWebhookServer provides a mock function with no fields func (_m *Manager) GetWebhookServer() webhook.Server { ret := _m.Called() From 3f07216297f62566292566e14b266f43c677a166 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 14:19:07 +0000 Subject: [PATCH 044/426] chore(deps): update github/codeql-action action to v3.27.7 (main) (#4183) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 32194725c5..131bee3f59 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 + uses: github/codeql-action/init@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 + uses: github/codeql-action/autobuild@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 + uses: github/codeql-action/analyze@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 109b907651..75aa039390 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 + uses: github/codeql-action/upload-sarif@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 with: sarif_file: results.sarif From 588d62e0c316f3c050ab205e180fe3a5b0bfff72 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 04:36:13 +0000 Subject: [PATCH 045/426] fix(deps): update kubernetes packages to v0.31.4 (main) (#4185) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 417c9ba78b..6e6f9b27af 100644 --- a/go.mod +++ b/go.mod @@ -28,11 +28,11 @@ require ( gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.1 istio.io/client-go v1.24.1 - k8s.io/api v0.31.3 - k8s.io/apiextensions-apiserver v0.31.3 - k8s.io/apimachinery v0.31.3 - k8s.io/client-go v0.31.3 - k8s.io/mount-utils v0.31.3 + k8s.io/api v0.31.4 + k8s.io/apiextensions-apiserver v0.31.4 + k8s.io/apimachinery v0.31.4 + k8s.io/client-go v0.31.4 + k8s.io/mount-utils v0.31.4 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 sigs.k8s.io/controller-runtime v0.19.3 sigs.k8s.io/e2e-framework v0.3.0 diff --git a/go.sum b/go.sum index 47ac354faf..89f5d12ad5 100644 --- a/go.sum +++ b/go.sum @@ -246,20 +246,20 @@ istio.io/api v1.24.1 h1:jF1I+ABGVS7ImVKzaAeiXHkFEbfXN2IEKDGJTw5UX0w= istio.io/api v1.24.1/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= istio.io/client-go v1.24.1 h1:m1hYt+S7zZZpiWHVnJkp9SFfQ9EApBhKL0LUaviKh9c= istio.io/client-go v1.24.1/go.mod h1:sCDBDJWQGJQz/1t3CHwUTDE5V7Nk6pFFkqBwhIg+LrI= -k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= -k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= -k8s.io/apiextensions-apiserver v0.31.3 h1:+GFGj2qFiU7rGCsA5o+p/rul1OQIq6oYpQw4+u+nciE= -k8s.io/apiextensions-apiserver v0.31.3/go.mod h1:2DSpFhUZZJmn/cr/RweH1cEVVbzFw9YBu4T+U3mf1e4= -k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= -k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= -k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= +k8s.io/api v0.31.4 h1:I2QNzitPVsPeLQvexMEsj945QumYraqv9m74isPDKhM= +k8s.io/api v0.31.4/go.mod h1:d+7vgXLvmcdT1BCo79VEgJxHHryww3V5np2OYTr6jdw= +k8s.io/apiextensions-apiserver v0.31.4 h1:FxbqzSvy92Ca9DIs5jqot883G0Ln/PGXfm/07t39LS0= +k8s.io/apiextensions-apiserver v0.31.4/go.mod h1:hIW9YU8UsqZqIWGG99/gsdIU0Ar45Qd3A12QOe/rvpg= +k8s.io/apimachinery v0.31.4 h1:8xjE2C4CzhYVm9DGf60yohpNUh5AEBnPxCryPBECmlM= +k8s.io/apimachinery v0.31.4/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.4 h1:t4QEXt4jgHIkKKlx06+W3+1JOwAFU/2OPiOo7H92eRQ= +k8s.io/client-go v0.31.4/go.mod h1:kvuMro4sFYIa8sulL5Gi5GFqUPvfH2O/dXuKstbaaeg= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/mount-utils v0.31.3 h1:CANy3prUYvvDCc2X7ZKgpjpDhAidx4gjGh/WwDrCPq8= -k8s.io/mount-utils v0.31.3/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU= +k8s.io/mount-utils v0.31.4 h1:9aWJ5BpJvs6fdIo36wWIuCC6ZMNllUT0JSFsVNJloFI= +k8s.io/mount-utils v0.31.4/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw= From 24f5bdf74010f28f5ffd5449d96a320fbcb5232f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 06:09:31 +0000 Subject: [PATCH 046/426] chore(deps): update actions/setup-go action to v5.2.0 (main) (#4187) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- .github/actions/run-e2e/action.yaml | 2 +- .github/workflows/ci.yaml | 6 +++--- .github/workflows/release.yaml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 10ec2770a7..6eb4012492 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -18,7 +18,7 @@ runs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 - name: Set up Golang - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Prepare build parameters diff --git a/.github/actions/run-e2e/action.yaml b/.github/actions/run-e2e/action.yaml index 75c2eb3a51..d72d3db996 100644 --- a/.github/actions/run-e2e/action.yaml +++ b/.github/actions/run-e2e/action.yaml @@ -50,7 +50,7 @@ runs: - name: Set up kubectl uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f # v4.0.0 - name: Set up go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: "${{ github.workspace }}/target/go.mod" - name: Set up helm diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d0c0374925..4a2061418f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -54,7 +54,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Golang - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Download dependencies @@ -86,7 +86,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Download dependencies @@ -110,7 +110,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Set up Helm diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d35b008e8c..276c469575 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -285,7 +285,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Golang - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Download dependencies From 22da5e6de558e9d14765882ab5dd1ccc4e1f63ec Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 10:26:36 +0000 Subject: [PATCH 047/426] chore(deps): update softprops/action-gh-release action to v2.2.0 (main) (#4188) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 276c469575..0e27d09180 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -361,7 +361,7 @@ jobs: mkdir -p tmp echo ${COSIGN_PUBLIC_KEY} | base64 -d > tmp/cosign.pub - name: Create pre-release - uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0 + uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.0 if: ${{ contains(github.ref, '-rc.') }} with: body_path: ./CHANGELOG.md @@ -377,7 +377,7 @@ jobs: draft: true fail_on_unmatched_files: true - name: Create release - uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0 + uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.0 if: ${{ !contains(github.ref, '-rc.') }} with: body_path: ./CHANGELOG.md From 7b6c2100b36fb26edb7b550012407156138f619a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 21:05:22 +0000 Subject: [PATCH 048/426] chore(deps): update dependency redhat-openshift-ecosystem/openshift-preflight to v1.11.1 (main) (#4192) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/preflight/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/preflight/action.yaml b/.github/actions/preflight/action.yaml index e817781b79..24d926c933 100644 --- a/.github/actions/preflight/action.yaml +++ b/.github/actions/preflight/action.yaml @@ -29,7 +29,7 @@ runs: RHCC_APITOKEN: ${{ inputs.pyxis-api-token }} RHCC_PROJECT_ID: ${{ inputs.redhat-project-id }} # renovate depName=redhat-openshift-ecosystem/openshift-preflight - PREFLIGHT_VERSION: 1.11.0 + PREFLIGHT_VERSION: 1.11.1 IMAGE_URI: ${{ inputs.registry }}/${{ inputs.repository }}:${{ inputs.version }} run: | hack/build/ci/preflight.sh "${{ env.PREFLIGHT_VERSION }}" "${{ env.IMAGE_URI}}" "${{ inputs.report-name }}" From e73ed81f90515f7ac98cef084344d5f93ecf2ef6 Mon Sep 17 00:00:00 2001 From: Christoph Muellner <33160506+chrismuellner@users.noreply.github.com> Date: Thu, 12 Dec 2024 13:34:37 +0100 Subject: [PATCH 049/426] Always lowercase workload kind in enrichment file (#4191) (#4195) --- pkg/webhook/mutation/pod/metadata/mutator.go | 5 +---- pkg/webhook/mutation/pod/metadata/mutator_test.go | 7 ++++++- pkg/webhook/mutation/pod/metadata/workload.go | 6 +++++- pkg/webhook/mutation/pod/metadata/workload_test.go | 10 +++++----- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/pkg/webhook/mutation/pod/metadata/mutator.go b/pkg/webhook/mutation/pod/metadata/mutator.go index db7b385ee9..b3a6802bb9 100644 --- a/pkg/webhook/mutation/pod/metadata/mutator.go +++ b/pkg/webhook/mutation/pod/metadata/mutator.go @@ -2,7 +2,6 @@ package metadata import ( "context" - "strings" "github.com/Dynatrace/dynatrace-operator/pkg/consts" dtingestendpoint "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/ingestendpoint" @@ -127,9 +126,7 @@ func setWorkloadAnnotations(pod *corev1.Pod, workload *workloadInfo) { pod.Annotations = make(map[string]string) } - // workload kind annotation in lower case according to dt semantic-dictionary - // https://bitbucket.lab.dynatrace.org/projects/DEUS/repos/semantic-dictionary/browse/source/fields/k8s.yaml - pod.Annotations[dtwebhook.AnnotationWorkloadKind] = strings.ToLower(workload.kind) + pod.Annotations[dtwebhook.AnnotationWorkloadKind] = workload.kind pod.Annotations[dtwebhook.AnnotationWorkloadName] = workload.name } diff --git a/pkg/webhook/mutation/pod/metadata/mutator_test.go b/pkg/webhook/mutation/pod/metadata/mutator_test.go index af93e4c8cf..30d5f08f19 100644 --- a/pkg/webhook/mutation/pod/metadata/mutator_test.go +++ b/pkg/webhook/mutation/pod/metadata/mutator_test.go @@ -223,7 +223,12 @@ func TestWorkloadAnnotations(t *testing.T) { }) t.Run("should lower case kind annotation", func(t *testing.T) { request := createTestMutationRequest(nil, nil, false) - setWorkloadAnnotations(request.Pod, &workloadInfo{name: testWorkloadInfoName, kind: "SuperWorkload"}) + objectMeta := &metav1.PartialObjectMetadata{ + ObjectMeta: metav1.ObjectMeta{Name: testWorkloadInfoName}, + TypeMeta: metav1.TypeMeta{Kind: "SuperWorkload"}, + } + + setWorkloadAnnotations(request.Pod, newWorkloadInfo(objectMeta)) assert.Contains(t, request.Pod.Annotations, dtwebhook.AnnotationWorkloadKind) assert.Equal(t, "superworkload", request.Pod.Annotations[dtwebhook.AnnotationWorkloadKind]) }) diff --git a/pkg/webhook/mutation/pod/metadata/workload.go b/pkg/webhook/mutation/pod/metadata/workload.go index 7042bda7ac..13566404eb 100644 --- a/pkg/webhook/mutation/pod/metadata/workload.go +++ b/pkg/webhook/mutation/pod/metadata/workload.go @@ -2,6 +2,7 @@ package metadata import ( "context" + "strings" kubeobjects "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/pod" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" @@ -19,7 +20,10 @@ type workloadInfo struct { func newWorkloadInfo(partialObjectMetadata *metav1.PartialObjectMetadata) *workloadInfo { return &workloadInfo{ name: partialObjectMetadata.ObjectMeta.Name, - kind: partialObjectMetadata.Kind, + + // workload kind in lower case according to dt semantic-dictionary + // https://docs.dynatrace.com/docs/discover-dynatrace/references/semantic-dictionary/fields#kubernetes + kind: strings.ToLower(partialObjectMetadata.Kind), } } diff --git a/pkg/webhook/mutation/pod/metadata/workload_test.go b/pkg/webhook/mutation/pod/metadata/workload_test.go index 09c533f255..d44dd40ed1 100644 --- a/pkg/webhook/mutation/pod/metadata/workload_test.go +++ b/pkg/webhook/mutation/pod/metadata/workload_test.go @@ -74,7 +74,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) assert.Equal(t, resourceName, workloadInfo.name) - assert.Equal(t, "DaemonSet", workloadInfo.kind) + assert.Equal(t, "daemonset", workloadInfo.kind) }) t.Run("should return Pod if owner references are empty", func(t *testing.T) { @@ -91,7 +91,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) assert.Equal(t, resourceName, workloadInfo.name) - assert.Equal(t, "Pod", workloadInfo.kind) + assert.Equal(t, "pod", workloadInfo.kind) }) t.Run("should be pod if owner is not well known", func(t *testing.T) { @@ -121,7 +121,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) assert.Equal(t, resourceName, workloadInfo.name) - assert.Equal(t, "Pod", workloadInfo.kind) + assert.Equal(t, "pod", workloadInfo.kind) }) t.Run("should be pod if no controller is the owner", func(t *testing.T) { @@ -146,7 +146,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) assert.Equal(t, namespaceName, workloadInfo.name) - assert.Equal(t, "Pod", workloadInfo.kind) + assert.Equal(t, "pod", workloadInfo.kind) }) t.Run("should find the root owner of the pod if the root owner is unknown", func(t *testing.T) { pod := corev1.Pod{ @@ -204,7 +204,7 @@ func TestFindRootOwnerOfPod(t *testing.T) { workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) assert.Equal(t, resourceName, workloadInfo.name) - assert.Equal(t, "Deployment", workloadInfo.kind) + assert.Equal(t, "deployment", workloadInfo.kind) }) t.Run("should not make an api-call if workload is not well known", func(t *testing.T) { pod := corev1.Pod{ From 860d3f8134cfaaaf49ecd2de695c76966c55005d Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:30:32 +0100 Subject: [PATCH 050/426] cherry-pick: Change logMonitoring error handling in case of no kubernetesClusterMEID (#4174) (#4194) --- .../dynakube/logmonitoring/logmonsettings/reconciler.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go index dae465b8d4..4ae30e37a0 100644 --- a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go @@ -37,9 +37,13 @@ func (r *reconciler) Reconcile(ctx context.Context) error { return nil } - if !r.dk.LogMonitoring().IsEnabled() { + if !r.dk.LogMonitoring().IsEnabled() || r.dk.Status.KubernetesClusterMEID == "" { meta.RemoveStatusCondition(r.dk.Conditions(), conditionType) + if r.dk.Status.KubernetesClusterMEID == "" { + return errors.New("the status of the DynaKube is missing information about the kubernetes monitored-entity, skipping LogMonitoring deployment") + } + return nil } @@ -79,7 +83,7 @@ func (r *reconciler) checkLogMonitoringSettings(ctx context.Context) error { if err != nil { setLogMonitoringSettingError(r.dk.Conditions(), conditionType, err.Error()) - return errors.WithMessage(err, "error when creating log monitoring setting") + return err } log.Info("logmonitoring setting created", "settings", objectId) From fd30dcfe1e1373de43a82eef81118f1ecd89f863 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 23:50:42 +0000 Subject: [PATCH 051/426] fix(deps): update module google.golang.org/grpc to v1.69.0 (main) (#4197) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 28 ++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 6e6f9b27af..aed8752498 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( golang.org/x/net v0.32.0 golang.org/x/oauth2 v0.24.0 golang.org/x/sys v0.28.0 - google.golang.org/grpc v1.68.1 + google.golang.org/grpc v1.69.0 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.1 istio.io/client-go v1.24.1 @@ -93,9 +93,9 @@ require ( golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 89f5d12ad5..98420f6e0f 100644 --- a/go.sum +++ b/go.sum @@ -32,6 +32,8 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -164,6 +166,16 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -219,14 +231,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= -google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0= -google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 h1:fVoAXEKA4+yufmbdVYv+SE73+cPZbbbe8paLsHfkK+U= +google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.69.0 h1:quSiOM1GJPmPH5XtU+BCoVXcDVJJAzNcoyfC2cCjGkI= +google.golang.org/grpc v1.69.0/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From c42d46fb682f2c31436e4ef8e5cc1280bcd4dbfb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 02:03:59 +0000 Subject: [PATCH 052/426] chore(deps): update github/codeql-action action to v3.27.9 (main) (#4198) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 131bee3f59..bb3f1015a6 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 + uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 + uses: github/codeql-action/autobuild@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 + uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 75aa039390..9be8cf3198 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 + uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 with: sarif_file: results.sarif From 169a3a119ded64a7639d8efc070aa4d8cf48135c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 08:42:00 +0100 Subject: [PATCH 053/426] fix(deps): update kubernetes packages to v0.32.0 (main) (#4193) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Andrii Soldatenko --- .mockery.yaml | 3 + cmd/support_archive/logs_test.go | 3 +- go.mod | 38 +-- go.sum | 94 +++-- .../controller-runtime/pkg/client/reader.go | 75 ---- .../kubernetes/typed/core/v1/pod_interface.go | 321 +++++++++++++++--- 6 files changed, 340 insertions(+), 194 deletions(-) delete mode 100644 pkg/util/testing/mocks/sigs.k8s.io/controller-runtime/pkg/client/reader.go rename {pkg/util/testing => test}/mocks/k8s.io/client-go/kubernetes/typed/core/v1/pod_interface.go (76%) diff --git a/.mockery.yaml b/.mockery.yaml index 6810b6859e..b1ac1510b8 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -64,3 +64,6 @@ packages: sigs.k8s.io/controller-runtime/pkg/reconcile: interfaces: Reconciler: + k8s.io/client-go/kubernetes/typed/core/v1: + interfaces: + PodInterface: diff --git a/cmd/support_archive/logs_test.go b/cmd/support_archive/logs_test.go index bc3ec74fcd..604cd40935 100644 --- a/cmd/support_archive/logs_test.go +++ b/cmd/support_archive/logs_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" - corev1mock "github.com/Dynatrace/dynatrace-operator/pkg/util/testing/mocks/k8s.io/client-go/kubernetes/typed/core/v1" + corev1mock "github.com/Dynatrace/dynatrace-operator/test/mocks/k8s.io/client-go/kubernetes/typed/core/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -97,7 +97,6 @@ func testLogCollection(t *testing.T, collectManagedLogs bool) { } } -//go:generate mockery --case=snake --srcpkg=k8s.io/client-go/kubernetes/typed/core/v1 --with-expecter --name=PodInterface --output ../../mocks/k8s.io/client-go/kubernetes/typed/core/v1 func TestLogCollectorPodListError(t *testing.T) { ctx := context.Background() logBuffer := bytes.Buffer{} diff --git a/go.mod b/go.mod index aed8752498..9d4402b8d9 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.22.0 golang.org/x/net v0.32.0 golang.org/x/oauth2 v0.24.0 @@ -28,12 +28,12 @@ require ( gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.1 istio.io/client-go v1.24.1 - k8s.io/api v0.31.4 - k8s.io/apiextensions-apiserver v0.31.4 - k8s.io/apimachinery v0.31.4 - k8s.io/client-go v0.31.4 - k8s.io/mount-utils v0.31.4 - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 + k8s.io/api v0.32.0 + k8s.io/apiextensions-apiserver v0.32.0 + k8s.io/apimachinery v0.32.0 + k8s.io/client-go v0.32.0 + k8s.io/mount-utils v0.32.0 + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.19.3 sigs.k8s.io/e2e-framework v0.3.0 sigs.k8s.io/yaml v1.4.0 @@ -43,7 +43,6 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.0 // indirect @@ -51,33 +50,29 @@ require ( github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/zapr v1.3.0 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/imdario/mergo v0.3.15 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/moby/spdystream v0.4.0 // indirect - github.com/moby/sys/mountinfo v0.7.1 // indirect + github.com/moby/spdystream v0.5.0 // indirect + github.com/moby/sys/mountinfo v0.7.2 // indirect + github.com/moby/sys/userns v0.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/image-spec v1.1.0-rc4 // indirect - github.com/opencontainers/runc v1.1.13 // indirect - github.com/opencontainers/runtime-spec v1.0.3-0.20220909204839-494a5a6aca78 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -91,16 +86,15 @@ require ( golang.org/x/sync v0.10.0 // indirect golang.org/x/term v0.27.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.5.0 // indirect + golang.org/x/time v0.7.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect ) diff --git a/go.sum b/go.sum index 98420f6e0f..d01d2e3109 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,6 @@ github.com/container-storage-interface/spec v1.11.0 h1:H/YKTOeUZwHtyPOr9raR+HgFm github.com/container-storage-interface/spec v1.11.0/go.mod h1:DtUvaQszPml1YJfIK7c00mlv6/g4wNMLanLgiUbKFRI= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -36,22 +34,18 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -64,14 +58,12 @@ github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEva github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -97,10 +89,12 @@ github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBW github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= -github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= +github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= +github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -110,18 +104,14 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.13 h1:98S2srgG9vw0zWcDpFMn5TRrh8kLxa/5OFUstuUhmRs= -github.com/opencontainers/runc v1.1.13/go.mod h1:R016aXacfp/gwQBYw2FDGa9m+n6atbLWrYY8hNMT/sA= -github.com/opencontainers/runtime-spec v1.0.3-0.20220909204839-494a5a6aca78 h1:R5M2qXZiK/mWPMT4VldCOiSL9HIAMuxQZWdG0CSM5+4= -github.com/opencontainers/runtime-spec v1.0.3-0.20220909204839-494a5a6aca78/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -185,8 +175,8 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= @@ -207,7 +197,6 @@ golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -217,14 +206,14 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -246,9 +235,6 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -258,29 +244,29 @@ istio.io/api v1.24.1 h1:jF1I+ABGVS7ImVKzaAeiXHkFEbfXN2IEKDGJTw5UX0w= istio.io/api v1.24.1/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= istio.io/client-go v1.24.1 h1:m1hYt+S7zZZpiWHVnJkp9SFfQ9EApBhKL0LUaviKh9c= istio.io/client-go v1.24.1/go.mod h1:sCDBDJWQGJQz/1t3CHwUTDE5V7Nk6pFFkqBwhIg+LrI= -k8s.io/api v0.31.4 h1:I2QNzitPVsPeLQvexMEsj945QumYraqv9m74isPDKhM= -k8s.io/api v0.31.4/go.mod h1:d+7vgXLvmcdT1BCo79VEgJxHHryww3V5np2OYTr6jdw= -k8s.io/apiextensions-apiserver v0.31.4 h1:FxbqzSvy92Ca9DIs5jqot883G0Ln/PGXfm/07t39LS0= -k8s.io/apiextensions-apiserver v0.31.4/go.mod h1:hIW9YU8UsqZqIWGG99/gsdIU0Ar45Qd3A12QOe/rvpg= -k8s.io/apimachinery v0.31.4 h1:8xjE2C4CzhYVm9DGf60yohpNUh5AEBnPxCryPBECmlM= -k8s.io/apimachinery v0.31.4/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.4 h1:t4QEXt4jgHIkKKlx06+W3+1JOwAFU/2OPiOo7H92eRQ= -k8s.io/client-go v0.31.4/go.mod h1:kvuMro4sFYIa8sulL5Gi5GFqUPvfH2O/dXuKstbaaeg= +k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= +k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= +k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0= +k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw= +k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg= +k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= +k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/mount-utils v0.31.4 h1:9aWJ5BpJvs6fdIo36wWIuCC6ZMNllUT0JSFsVNJloFI= -k8s.io/mount-utils v0.31.4/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/mount-utils v0.32.0 h1:KOQAhPzJICATXnc6XCkWoexKbkOexRnMCUW8APFfwg4= +k8s.io/mount-utils v0.32.0/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw= sigs.k8s.io/controller-runtime v0.19.3/go.mod h1:j4j87DqtsThvwTv5/Tc5NFRyyF/RF0ip4+62tbTSIUM= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/pkg/util/testing/mocks/sigs.k8s.io/controller-runtime/pkg/client/reader.go b/pkg/util/testing/mocks/sigs.k8s.io/controller-runtime/pkg/client/reader.go deleted file mode 100644 index 8391aad654..0000000000 --- a/pkg/util/testing/mocks/sigs.k8s.io/controller-runtime/pkg/client/reader.go +++ /dev/null @@ -1,75 +0,0 @@ -// Code generated by mockery v2.15.0. DO NOT EDIT. - -package mocks - -import ( - context "context" - - mock "github.com/stretchr/testify/mock" - types "k8s.io/apimachinery/pkg/types" - client "sigs.k8s.io/controller-runtime/pkg/client" -) - -// Reader is an autogenerated mock type for the Reader type -type Reader struct { - mock.Mock -} - -// Get provides a mock function with given fields: ctx, key, obj, opts -func (_m *Reader) Get(ctx context.Context, key types.NamespacedName, obj client.Object, opts ...client.GetOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - - var _ca []interface{} - _ca = append(_ca, ctx, key, obj) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, types.NamespacedName, client.Object, ...client.GetOption) error); ok { - r0 = rf(ctx, key, obj, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// List provides a mock function with given fields: ctx, list, opts -func (_m *Reader) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - - var _ca []interface{} - _ca = append(_ca, ctx, list) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, client.ObjectList, ...client.ListOption) error); ok { - r0 = rf(ctx, list, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -type mockConstructorTestingTNewReader interface { - mock.TestingT - Cleanup(func()) -} - -// NewReader creates a new instance of Reader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewReader(t mockConstructorTestingTNewReader) *Reader { - mock := &Reader{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/util/testing/mocks/k8s.io/client-go/kubernetes/typed/core/v1/pod_interface.go b/test/mocks/k8s.io/client-go/kubernetes/typed/core/v1/pod_interface.go similarity index 76% rename from pkg/util/testing/mocks/k8s.io/client-go/kubernetes/typed/core/v1/pod_interface.go rename to test/mocks/k8s.io/client-go/kubernetes/typed/core/v1/pod_interface.go index d72ccef08e..709b2d7259 100644 --- a/pkg/util/testing/mocks/k8s.io/client-go/kubernetes/typed/core/v1/pod_interface.go +++ b/test/mocks/k8s.io/client-go/kubernetes/typed/core/v1/pod_interface.go @@ -1,19 +1,27 @@ -// Code generated by mockery v2.15.0. DO NOT EDIT. +// Code generated by mockery. DO NOT EDIT. package mocks import ( context "context" - mock "github.com/stretchr/testify/mock" corev1 "k8s.io/api/core/v1" - policyv1 "k8s.io/api/policy/v1" - v1beta1 "k8s.io/api/policy/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + mock "github.com/stretchr/testify/mock" + + policyv1 "k8s.io/api/policy/v1" + + rest "k8s.io/client-go/rest" + types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" + v1 "k8s.io/client-go/applyconfigurations/core/v1" - rest "k8s.io/client-go/rest" + + v1beta1 "k8s.io/api/policy/v1beta1" + + watch "k8s.io/apimachinery/pkg/watch" ) // PodInterface is an autogenerated mock type for the PodInterface type @@ -33,7 +41,15 @@ func (_m *PodInterface) EXPECT() *PodInterface_Expecter { func (_m *PodInterface) Apply(ctx context.Context, pod *v1.PodApplyConfiguration, opts metav1.ApplyOptions) (*corev1.Pod, error) { ret := _m.Called(ctx, pod, opts) + if len(ret) == 0 { + panic("no return value specified for Apply") + } + var r0 *corev1.Pod + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *v1.PodApplyConfiguration, metav1.ApplyOptions) (*corev1.Pod, error)); ok { + return rf(ctx, pod, opts) + } if rf, ok := ret.Get(0).(func(context.Context, *v1.PodApplyConfiguration, metav1.ApplyOptions) *corev1.Pod); ok { r0 = rf(ctx, pod, opts) } else { @@ -42,7 +58,6 @@ func (_m *PodInterface) Apply(ctx context.Context, pod *v1.PodApplyConfiguration } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *v1.PodApplyConfiguration, metav1.ApplyOptions) error); ok { r1 = rf(ctx, pod, opts) } else { @@ -69,7 +84,6 @@ func (_c *PodInterface_Apply_Call) Run(run func(ctx context.Context, pod *v1.Pod _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*v1.PodApplyConfiguration), args[2].(metav1.ApplyOptions)) }) - return _c } @@ -78,11 +92,24 @@ func (_c *PodInterface_Apply_Call) Return(result *corev1.Pod, err error) *PodInt return _c } +func (_c *PodInterface_Apply_Call) RunAndReturn(run func(context.Context, *v1.PodApplyConfiguration, metav1.ApplyOptions) (*corev1.Pod, error)) *PodInterface_Apply_Call { + _c.Call.Return(run) + return _c +} + // ApplyStatus provides a mock function with given fields: ctx, pod, opts func (_m *PodInterface) ApplyStatus(ctx context.Context, pod *v1.PodApplyConfiguration, opts metav1.ApplyOptions) (*corev1.Pod, error) { ret := _m.Called(ctx, pod, opts) + if len(ret) == 0 { + panic("no return value specified for ApplyStatus") + } + var r0 *corev1.Pod + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *v1.PodApplyConfiguration, metav1.ApplyOptions) (*corev1.Pod, error)); ok { + return rf(ctx, pod, opts) + } if rf, ok := ret.Get(0).(func(context.Context, *v1.PodApplyConfiguration, metav1.ApplyOptions) *corev1.Pod); ok { r0 = rf(ctx, pod, opts) } else { @@ -91,7 +118,6 @@ func (_m *PodInterface) ApplyStatus(ctx context.Context, pod *v1.PodApplyConfigu } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *v1.PodApplyConfiguration, metav1.ApplyOptions) error); ok { r1 = rf(ctx, pod, opts) } else { @@ -118,7 +144,6 @@ func (_c *PodInterface_ApplyStatus_Call) Run(run func(ctx context.Context, pod * _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*v1.PodApplyConfiguration), args[2].(metav1.ApplyOptions)) }) - return _c } @@ -127,10 +152,19 @@ func (_c *PodInterface_ApplyStatus_Call) Return(result *corev1.Pod, err error) * return _c } +func (_c *PodInterface_ApplyStatus_Call) RunAndReturn(run func(context.Context, *v1.PodApplyConfiguration, metav1.ApplyOptions) (*corev1.Pod, error)) *PodInterface_ApplyStatus_Call { + _c.Call.Return(run) + return _c +} + // Bind provides a mock function with given fields: ctx, binding, opts func (_m *PodInterface) Bind(ctx context.Context, binding *corev1.Binding, opts metav1.CreateOptions) error { ret := _m.Called(ctx, binding, opts) + if len(ret) == 0 { + panic("no return value specified for Bind") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *corev1.Binding, metav1.CreateOptions) error); ok { r0 = rf(ctx, binding, opts) @@ -158,7 +192,6 @@ func (_c *PodInterface_Bind_Call) Run(run func(ctx context.Context, binding *cor _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*corev1.Binding), args[2].(metav1.CreateOptions)) }) - return _c } @@ -167,11 +200,24 @@ func (_c *PodInterface_Bind_Call) Return(_a0 error) *PodInterface_Bind_Call { return _c } +func (_c *PodInterface_Bind_Call) RunAndReturn(run func(context.Context, *corev1.Binding, metav1.CreateOptions) error) *PodInterface_Bind_Call { + _c.Call.Return(run) + return _c +} + // Create provides a mock function with given fields: ctx, pod, opts func (_m *PodInterface) Create(ctx context.Context, pod *corev1.Pod, opts metav1.CreateOptions) (*corev1.Pod, error) { ret := _m.Called(ctx, pod, opts) + if len(ret) == 0 { + panic("no return value specified for Create") + } + var r0 *corev1.Pod + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *corev1.Pod, metav1.CreateOptions) (*corev1.Pod, error)); ok { + return rf(ctx, pod, opts) + } if rf, ok := ret.Get(0).(func(context.Context, *corev1.Pod, metav1.CreateOptions) *corev1.Pod); ok { r0 = rf(ctx, pod, opts) } else { @@ -180,7 +226,6 @@ func (_m *PodInterface) Create(ctx context.Context, pod *corev1.Pod, opts metav1 } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *corev1.Pod, metav1.CreateOptions) error); ok { r1 = rf(ctx, pod, opts) } else { @@ -207,7 +252,6 @@ func (_c *PodInterface_Create_Call) Run(run func(ctx context.Context, pod *corev _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*corev1.Pod), args[2].(metav1.CreateOptions)) }) - return _c } @@ -216,10 +260,19 @@ func (_c *PodInterface_Create_Call) Return(_a0 *corev1.Pod, _a1 error) *PodInter return _c } +func (_c *PodInterface_Create_Call) RunAndReturn(run func(context.Context, *corev1.Pod, metav1.CreateOptions) (*corev1.Pod, error)) *PodInterface_Create_Call { + _c.Call.Return(run) + return _c +} + // Delete provides a mock function with given fields: ctx, name, opts func (_m *PodInterface) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { ret := _m.Called(ctx, name, opts) + if len(ret) == 0 { + panic("no return value specified for Delete") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string, metav1.DeleteOptions) error); ok { r0 = rf(ctx, name, opts) @@ -247,7 +300,6 @@ func (_c *PodInterface_Delete_Call) Run(run func(ctx context.Context, name strin _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(string), args[2].(metav1.DeleteOptions)) }) - return _c } @@ -256,10 +308,19 @@ func (_c *PodInterface_Delete_Call) Return(_a0 error) *PodInterface_Delete_Call return _c } +func (_c *PodInterface_Delete_Call) RunAndReturn(run func(context.Context, string, metav1.DeleteOptions) error) *PodInterface_Delete_Call { + _c.Call.Return(run) + return _c +} + // DeleteCollection provides a mock function with given fields: ctx, opts, listOpts func (_m *PodInterface) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { ret := _m.Called(ctx, opts, listOpts) + if len(ret) == 0 { + panic("no return value specified for DeleteCollection") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, metav1.DeleteOptions, metav1.ListOptions) error); ok { r0 = rf(ctx, opts, listOpts) @@ -287,7 +348,6 @@ func (_c *PodInterface_DeleteCollection_Call) Run(run func(ctx context.Context, _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(metav1.DeleteOptions), args[2].(metav1.ListOptions)) }) - return _c } @@ -296,10 +356,19 @@ func (_c *PodInterface_DeleteCollection_Call) Return(_a0 error) *PodInterface_De return _c } +func (_c *PodInterface_DeleteCollection_Call) RunAndReturn(run func(context.Context, metav1.DeleteOptions, metav1.ListOptions) error) *PodInterface_DeleteCollection_Call { + _c.Call.Return(run) + return _c +} + // Evict provides a mock function with given fields: ctx, eviction func (_m *PodInterface) Evict(ctx context.Context, eviction *v1beta1.Eviction) error { ret := _m.Called(ctx, eviction) + if len(ret) == 0 { + panic("no return value specified for Evict") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *v1beta1.Eviction) error); ok { r0 = rf(ctx, eviction) @@ -326,7 +395,6 @@ func (_c *PodInterface_Evict_Call) Run(run func(ctx context.Context, eviction *v _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*v1beta1.Eviction)) }) - return _c } @@ -335,10 +403,19 @@ func (_c *PodInterface_Evict_Call) Return(_a0 error) *PodInterface_Evict_Call { return _c } +func (_c *PodInterface_Evict_Call) RunAndReturn(run func(context.Context, *v1beta1.Eviction) error) *PodInterface_Evict_Call { + _c.Call.Return(run) + return _c +} + // EvictV1 provides a mock function with given fields: ctx, eviction func (_m *PodInterface) EvictV1(ctx context.Context, eviction *policyv1.Eviction) error { ret := _m.Called(ctx, eviction) + if len(ret) == 0 { + panic("no return value specified for EvictV1") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *policyv1.Eviction) error); ok { r0 = rf(ctx, eviction) @@ -365,7 +442,6 @@ func (_c *PodInterface_EvictV1_Call) Run(run func(ctx context.Context, eviction _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*policyv1.Eviction)) }) - return _c } @@ -374,10 +450,19 @@ func (_c *PodInterface_EvictV1_Call) Return(_a0 error) *PodInterface_EvictV1_Cal return _c } +func (_c *PodInterface_EvictV1_Call) RunAndReturn(run func(context.Context, *policyv1.Eviction) error) *PodInterface_EvictV1_Call { + _c.Call.Return(run) + return _c +} + // EvictV1beta1 provides a mock function with given fields: ctx, eviction func (_m *PodInterface) EvictV1beta1(ctx context.Context, eviction *v1beta1.Eviction) error { ret := _m.Called(ctx, eviction) + if len(ret) == 0 { + panic("no return value specified for EvictV1beta1") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *v1beta1.Eviction) error); ok { r0 = rf(ctx, eviction) @@ -404,7 +489,6 @@ func (_c *PodInterface_EvictV1beta1_Call) Run(run func(ctx context.Context, evic _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*v1beta1.Eviction)) }) - return _c } @@ -413,11 +497,24 @@ func (_c *PodInterface_EvictV1beta1_Call) Return(_a0 error) *PodInterface_EvictV return _c } +func (_c *PodInterface_EvictV1beta1_Call) RunAndReturn(run func(context.Context, *v1beta1.Eviction) error) *PodInterface_EvictV1beta1_Call { + _c.Call.Return(run) + return _c +} + // Get provides a mock function with given fields: ctx, name, opts func (_m *PodInterface) Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Pod, error) { ret := _m.Called(ctx, name, opts) + if len(ret) == 0 { + panic("no return value specified for Get") + } + var r0 *corev1.Pod + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, metav1.GetOptions) (*corev1.Pod, error)); ok { + return rf(ctx, name, opts) + } if rf, ok := ret.Get(0).(func(context.Context, string, metav1.GetOptions) *corev1.Pod); ok { r0 = rf(ctx, name, opts) } else { @@ -426,7 +523,6 @@ func (_m *PodInterface) Get(ctx context.Context, name string, opts metav1.GetOpt } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, metav1.GetOptions) error); ok { r1 = rf(ctx, name, opts) } else { @@ -453,7 +549,6 @@ func (_c *PodInterface_Get_Call) Run(run func(ctx context.Context, name string, _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(string), args[2].(metav1.GetOptions)) }) - return _c } @@ -462,10 +557,19 @@ func (_c *PodInterface_Get_Call) Return(_a0 *corev1.Pod, _a1 error) *PodInterfac return _c } +func (_c *PodInterface_Get_Call) RunAndReturn(run func(context.Context, string, metav1.GetOptions) (*corev1.Pod, error)) *PodInterface_Get_Call { + _c.Call.Return(run) + return _c +} + // GetLogs provides a mock function with given fields: name, opts func (_m *PodInterface) GetLogs(name string, opts *corev1.PodLogOptions) *rest.Request { ret := _m.Called(name, opts) + if len(ret) == 0 { + panic("no return value specified for GetLogs") + } + var r0 *rest.Request if rf, ok := ret.Get(0).(func(string, *corev1.PodLogOptions) *rest.Request); ok { r0 = rf(name, opts) @@ -494,7 +598,6 @@ func (_c *PodInterface_GetLogs_Call) Run(run func(name string, opts *corev1.PodL _c.Call.Run(func(args mock.Arguments) { run(args[0].(string), args[1].(*corev1.PodLogOptions)) }) - return _c } @@ -503,11 +606,24 @@ func (_c *PodInterface_GetLogs_Call) Return(_a0 *rest.Request) *PodInterface_Get return _c } +func (_c *PodInterface_GetLogs_Call) RunAndReturn(run func(string, *corev1.PodLogOptions) *rest.Request) *PodInterface_GetLogs_Call { + _c.Call.Return(run) + return _c +} + // List provides a mock function with given fields: ctx, opts func (_m *PodInterface) List(ctx context.Context, opts metav1.ListOptions) (*corev1.PodList, error) { ret := _m.Called(ctx, opts) + if len(ret) == 0 { + panic("no return value specified for List") + } + var r0 *corev1.PodList + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, metav1.ListOptions) (*corev1.PodList, error)); ok { + return rf(ctx, opts) + } if rf, ok := ret.Get(0).(func(context.Context, metav1.ListOptions) *corev1.PodList); ok { r0 = rf(ctx, opts) } else { @@ -516,7 +632,6 @@ func (_m *PodInterface) List(ctx context.Context, opts metav1.ListOptions) (*cor } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, metav1.ListOptions) error); ok { r1 = rf(ctx, opts) } else { @@ -542,7 +657,6 @@ func (_c *PodInterface_List_Call) Run(run func(ctx context.Context, opts metav1. _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(metav1.ListOptions)) }) - return _c } @@ -551,19 +665,31 @@ func (_c *PodInterface_List_Call) Return(_a0 *corev1.PodList, _a1 error) *PodInt return _c } +func (_c *PodInterface_List_Call) RunAndReturn(run func(context.Context, metav1.ListOptions) (*corev1.PodList, error)) *PodInterface_List_Call { + _c.Call.Return(run) + return _c +} + // Patch provides a mock function with given fields: ctx, name, pt, data, opts, subresources func (_m *PodInterface) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*corev1.Pod, error) { _va := make([]interface{}, len(subresources)) for _i := range subresources { _va[_i] = subresources[_i] } - var _ca []interface{} _ca = append(_ca, ctx, name, pt, data, opts) _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Patch") + } + var r0 *corev1.Pod + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, types.PatchType, []byte, metav1.PatchOptions, ...string) (*corev1.Pod, error)); ok { + return rf(ctx, name, pt, data, opts, subresources...) + } if rf, ok := ret.Get(0).(func(context.Context, string, types.PatchType, []byte, metav1.PatchOptions, ...string) *corev1.Pod); ok { r0 = rf(ctx, name, pt, data, opts, subresources...) } else { @@ -572,7 +698,6 @@ func (_m *PodInterface) Patch(ctx context.Context, name string, pt types.PatchTy } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, types.PatchType, []byte, metav1.PatchOptions, ...string) error); ok { r1 = rf(ctx, name, pt, data, opts, subresources...) } else { @@ -602,16 +727,13 @@ func (_e *PodInterface_Expecter) Patch(ctx interface{}, name interface{}, pt int func (_c *PodInterface_Patch_Call) Run(run func(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string)) *PodInterface_Patch_Call { _c.Call.Run(func(args mock.Arguments) { variadicArgs := make([]string, len(args)-5) - for i, a := range args[5:] { if a != nil { variadicArgs[i] = a.(string) } } - run(args[0].(context.Context), args[1].(string), args[2].(types.PatchType), args[3].([]byte), args[4].(metav1.PatchOptions), variadicArgs...) }) - return _c } @@ -620,10 +742,19 @@ func (_c *PodInterface_Patch_Call) Return(result *corev1.Pod, err error) *PodInt return _c } +func (_c *PodInterface_Patch_Call) RunAndReturn(run func(context.Context, string, types.PatchType, []byte, metav1.PatchOptions, ...string) (*corev1.Pod, error)) *PodInterface_Patch_Call { + _c.Call.Return(run) + return _c +} + // ProxyGet provides a mock function with given fields: scheme, name, port, path, params func (_m *PodInterface) ProxyGet(scheme string, name string, port string, path string, params map[string]string) rest.ResponseWrapper { ret := _m.Called(scheme, name, port, path, params) + if len(ret) == 0 { + panic("no return value specified for ProxyGet") + } + var r0 rest.ResponseWrapper if rf, ok := ret.Get(0).(func(string, string, string, string, map[string]string) rest.ResponseWrapper); ok { r0 = rf(scheme, name, port, path, params) @@ -655,7 +786,6 @@ func (_c *PodInterface_ProxyGet_Call) Run(run func(scheme string, name string, p _c.Call.Run(func(args mock.Arguments) { run(args[0].(string), args[1].(string), args[2].(string), args[3].(string), args[4].(map[string]string)) }) - return _c } @@ -664,11 +794,24 @@ func (_c *PodInterface_ProxyGet_Call) Return(_a0 rest.ResponseWrapper) *PodInter return _c } +func (_c *PodInterface_ProxyGet_Call) RunAndReturn(run func(string, string, string, string, map[string]string) rest.ResponseWrapper) *PodInterface_ProxyGet_Call { + _c.Call.Return(run) + return _c +} + // Update provides a mock function with given fields: ctx, pod, opts func (_m *PodInterface) Update(ctx context.Context, pod *corev1.Pod, opts metav1.UpdateOptions) (*corev1.Pod, error) { ret := _m.Called(ctx, pod, opts) + if len(ret) == 0 { + panic("no return value specified for Update") + } + var r0 *corev1.Pod + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *corev1.Pod, metav1.UpdateOptions) (*corev1.Pod, error)); ok { + return rf(ctx, pod, opts) + } if rf, ok := ret.Get(0).(func(context.Context, *corev1.Pod, metav1.UpdateOptions) *corev1.Pod); ok { r0 = rf(ctx, pod, opts) } else { @@ -677,7 +820,6 @@ func (_m *PodInterface) Update(ctx context.Context, pod *corev1.Pod, opts metav1 } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *corev1.Pod, metav1.UpdateOptions) error); ok { r1 = rf(ctx, pod, opts) } else { @@ -704,7 +846,6 @@ func (_c *PodInterface_Update_Call) Run(run func(ctx context.Context, pod *corev _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*corev1.Pod), args[2].(metav1.UpdateOptions)) }) - return _c } @@ -713,11 +854,24 @@ func (_c *PodInterface_Update_Call) Return(_a0 *corev1.Pod, _a1 error) *PodInter return _c } +func (_c *PodInterface_Update_Call) RunAndReturn(run func(context.Context, *corev1.Pod, metav1.UpdateOptions) (*corev1.Pod, error)) *PodInterface_Update_Call { + _c.Call.Return(run) + return _c +} + // UpdateEphemeralContainers provides a mock function with given fields: ctx, podName, pod, opts func (_m *PodInterface) UpdateEphemeralContainers(ctx context.Context, podName string, pod *corev1.Pod, opts metav1.UpdateOptions) (*corev1.Pod, error) { ret := _m.Called(ctx, podName, pod, opts) + if len(ret) == 0 { + panic("no return value specified for UpdateEphemeralContainers") + } + var r0 *corev1.Pod + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *corev1.Pod, metav1.UpdateOptions) (*corev1.Pod, error)); ok { + return rf(ctx, podName, pod, opts) + } if rf, ok := ret.Get(0).(func(context.Context, string, *corev1.Pod, metav1.UpdateOptions) *corev1.Pod); ok { r0 = rf(ctx, podName, pod, opts) } else { @@ -726,7 +880,6 @@ func (_m *PodInterface) UpdateEphemeralContainers(ctx context.Context, podName s } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, *corev1.Pod, metav1.UpdateOptions) error); ok { r1 = rf(ctx, podName, pod, opts) } else { @@ -754,7 +907,6 @@ func (_c *PodInterface_UpdateEphemeralContainers_Call) Run(run func(ctx context. _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(string), args[2].(*corev1.Pod), args[3].(metav1.UpdateOptions)) }) - return _c } @@ -763,11 +915,85 @@ func (_c *PodInterface_UpdateEphemeralContainers_Call) Return(_a0 *corev1.Pod, _ return _c } +func (_c *PodInterface_UpdateEphemeralContainers_Call) RunAndReturn(run func(context.Context, string, *corev1.Pod, metav1.UpdateOptions) (*corev1.Pod, error)) *PodInterface_UpdateEphemeralContainers_Call { + _c.Call.Return(run) + return _c +} + +// UpdateResize provides a mock function with given fields: ctx, podName, pod, opts +func (_m *PodInterface) UpdateResize(ctx context.Context, podName string, pod *corev1.Pod, opts metav1.UpdateOptions) (*corev1.Pod, error) { + ret := _m.Called(ctx, podName, pod, opts) + + if len(ret) == 0 { + panic("no return value specified for UpdateResize") + } + + var r0 *corev1.Pod + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *corev1.Pod, metav1.UpdateOptions) (*corev1.Pod, error)); ok { + return rf(ctx, podName, pod, opts) + } + if rf, ok := ret.Get(0).(func(context.Context, string, *corev1.Pod, metav1.UpdateOptions) *corev1.Pod); ok { + r0 = rf(ctx, podName, pod, opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*corev1.Pod) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, *corev1.Pod, metav1.UpdateOptions) error); ok { + r1 = rf(ctx, podName, pod, opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PodInterface_UpdateResize_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateResize' +type PodInterface_UpdateResize_Call struct { + *mock.Call +} + +// UpdateResize is a helper method to define mock.On call +// - ctx context.Context +// - podName string +// - pod *corev1.Pod +// - opts metav1.UpdateOptions +func (_e *PodInterface_Expecter) UpdateResize(ctx interface{}, podName interface{}, pod interface{}, opts interface{}) *PodInterface_UpdateResize_Call { + return &PodInterface_UpdateResize_Call{Call: _e.mock.On("UpdateResize", ctx, podName, pod, opts)} +} + +func (_c *PodInterface_UpdateResize_Call) Run(run func(ctx context.Context, podName string, pod *corev1.Pod, opts metav1.UpdateOptions)) *PodInterface_UpdateResize_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(*corev1.Pod), args[3].(metav1.UpdateOptions)) + }) + return _c +} + +func (_c *PodInterface_UpdateResize_Call) Return(_a0 *corev1.Pod, _a1 error) *PodInterface_UpdateResize_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *PodInterface_UpdateResize_Call) RunAndReturn(run func(context.Context, string, *corev1.Pod, metav1.UpdateOptions) (*corev1.Pod, error)) *PodInterface_UpdateResize_Call { + _c.Call.Return(run) + return _c +} + // UpdateStatus provides a mock function with given fields: ctx, pod, opts func (_m *PodInterface) UpdateStatus(ctx context.Context, pod *corev1.Pod, opts metav1.UpdateOptions) (*corev1.Pod, error) { ret := _m.Called(ctx, pod, opts) + if len(ret) == 0 { + panic("no return value specified for UpdateStatus") + } + var r0 *corev1.Pod + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *corev1.Pod, metav1.UpdateOptions) (*corev1.Pod, error)); ok { + return rf(ctx, pod, opts) + } if rf, ok := ret.Get(0).(func(context.Context, *corev1.Pod, metav1.UpdateOptions) *corev1.Pod); ok { r0 = rf(ctx, pod, opts) } else { @@ -776,7 +1002,6 @@ func (_m *PodInterface) UpdateStatus(ctx context.Context, pod *corev1.Pod, opts } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *corev1.Pod, metav1.UpdateOptions) error); ok { r1 = rf(ctx, pod, opts) } else { @@ -803,7 +1028,6 @@ func (_c *PodInterface_UpdateStatus_Call) Run(run func(ctx context.Context, pod _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*corev1.Pod), args[2].(metav1.UpdateOptions)) }) - return _c } @@ -812,11 +1036,24 @@ func (_c *PodInterface_UpdateStatus_Call) Return(_a0 *corev1.Pod, _a1 error) *Po return _c } +func (_c *PodInterface_UpdateStatus_Call) RunAndReturn(run func(context.Context, *corev1.Pod, metav1.UpdateOptions) (*corev1.Pod, error)) *PodInterface_UpdateStatus_Call { + _c.Call.Return(run) + return _c +} + // Watch provides a mock function with given fields: ctx, opts func (_m *PodInterface) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { ret := _m.Called(ctx, opts) + if len(ret) == 0 { + panic("no return value specified for Watch") + } + var r0 watch.Interface + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, metav1.ListOptions) (watch.Interface, error)); ok { + return rf(ctx, opts) + } if rf, ok := ret.Get(0).(func(context.Context, metav1.ListOptions) watch.Interface); ok { r0 = rf(ctx, opts) } else { @@ -825,7 +1062,6 @@ func (_m *PodInterface) Watch(ctx context.Context, opts metav1.ListOptions) (wat } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, metav1.ListOptions) error); ok { r1 = rf(ctx, opts) } else { @@ -851,7 +1087,6 @@ func (_c *PodInterface_Watch_Call) Run(run func(ctx context.Context, opts metav1 _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(metav1.ListOptions)) }) - return _c } @@ -860,13 +1095,17 @@ func (_c *PodInterface_Watch_Call) Return(_a0 watch.Interface, _a1 error) *PodIn return _c } -type mockConstructorTestingTNewPodInterface interface { - mock.TestingT - Cleanup(func()) +func (_c *PodInterface_Watch_Call) RunAndReturn(run func(context.Context, metav1.ListOptions) (watch.Interface, error)) *PodInterface_Watch_Call { + _c.Call.Return(run) + return _c } // NewPodInterface creates a new instance of PodInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewPodInterface(t mockConstructorTestingTNewPodInterface) *PodInterface { +// The first argument is typically a *testing.T value. +func NewPodInterface(t interface { + mock.TestingT + Cleanup(func()) +}) *PodInterface { mock := &PodInterface{} mock.Mock.Test(t) From a186b91e3672f9f12f9271c2745663dc22f016b6 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Mon, 16 Dec 2024 10:09:37 +0100 Subject: [PATCH 054/426] fixup: e2e test after merging #4195 (#4202) --- test/features/applicationmonitoring/metadata_enrichment.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/features/applicationmonitoring/metadata_enrichment.go b/test/features/applicationmonitoring/metadata_enrichment.go index 0dca2e818a..b699d99a0f 100644 --- a/test/features/applicationmonitoring/metadata_enrichment.go +++ b/test/features/applicationmonitoring/metadata_enrichment.go @@ -162,7 +162,7 @@ func podHasOnlyMetadataEnrichmentInitContainer(samplePod *sample.App) features.F func assessPodHasMetadataEnrichmentFile(ctx context.Context, t *testing.T, resource *resources.Resources, testPod corev1.Pod) { enrichmentMetadata := getMetadataEnrichmentMetadataFromPod(ctx, t, resource, testPod) - assert.Equal(t, "Pod", enrichmentMetadata.WorkloadKind) + assert.Equal(t, "pod", enrichmentMetadata.WorkloadKind) assert.Equal(t, testPod.Name, enrichmentMetadata.WorkloadName) } @@ -235,7 +235,7 @@ func assessDeploymentHasMetadataEnrichmentFile(ctx context.Context, t *testing.T return func(pod corev1.Pod) { enrichmentMetadata := getMetadataEnrichmentMetadataFromPod(ctx, t, resource, pod) - assert.Equal(t, "Deployment", enrichmentMetadata.WorkloadKind) + assert.Equal(t, "deployment", enrichmentMetadata.WorkloadKind) assert.Equal(t, deploymentName, enrichmentMetadata.WorkloadName) } } From 1d29927a4f2599f6fd55ef3f123553495f4f9ae6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:24:55 +0000 Subject: [PATCH 055/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1734081738 (main) (#4203) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a993e0ff3e..6739c695e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS=" -o ./build/_output/bin/dynatrace-operator ./cmd/ FROM registry.access.redhat.com/ubi9-micro:9.5-1733767087@sha256:111395a0b54d220c4ad821602a4a28807d6c4fb2feb19b43a6468a9d5f257463 AS base -FROM registry.access.redhat.com/ubi9:9.5-1732804088@sha256:1057dab827c782abcfb9bda0c3900c0966b5066e671d54976a7bcb3a2d1a5e53 AS dependency +FROM registry.access.redhat.com/ubi9:9.5-1734081738@sha256:aa149a2e32725b0ea9c8ac97d25e65a894b1a4b2f220dd7670d890e60a733a14 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From c24bb7ccd2519502570878c86a51357737bceea7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:05:33 +0000 Subject: [PATCH 056/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1734327559 (main) (#4204) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6739c695e6..7e5e7327bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS=" go build -tags "${GO_BUILD_TAGS}" -trimpath -ldflags="${GO_LINKER_ARGS}" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ -FROM registry.access.redhat.com/ubi9-micro:9.5-1733767087@sha256:111395a0b54d220c4ad821602a4a28807d6c4fb2feb19b43a6468a9d5f257463 AS base +FROM registry.access.redhat.com/ubi9-micro:9.5-1734327559@sha256:a22fffe0256af00176c8b4f22eec5d8ecb1cb1684d811c33b1f2832fd573260f AS base FROM registry.access.redhat.com/ubi9:9.5-1734081738@sha256:aa149a2e32725b0ea9c8ac97d25e65a894b1a4b2f220dd7670d890e60a733a14 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From 43e2c40cd0bb4e06432e55005d510d706e512a4a Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:11:04 +0100 Subject: [PATCH 057/426] Fix e2e test by splitting up extensive if condition (#4205) --- .../dynakube/logmonitoring/logmonsettings/reconciler.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go index 4ae30e37a0..06ecab05af 100644 --- a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go @@ -37,14 +37,12 @@ func (r *reconciler) Reconcile(ctx context.Context) error { return nil } - if !r.dk.LogMonitoring().IsEnabled() || r.dk.Status.KubernetesClusterMEID == "" { + if !r.dk.LogMonitoring().IsEnabled() { meta.RemoveStatusCondition(r.dk.Conditions(), conditionType) - if r.dk.Status.KubernetesClusterMEID == "" { - return errors.New("the status of the DynaKube is missing information about the kubernetes monitored-entity, skipping LogMonitoring deployment") - } - return nil + } else if r.dk.Status.KubernetesClusterMEID == "" { + return errors.New("the status of the DynaKube is missing information about the kubernetes monitored-entity, skipping LogMonitoring deployment") } err := r.checkLogMonitoringSettings(ctx) From a57f910c2f99cce95198596a584946b751f3b3ec Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:41:30 +0000 Subject: [PATCH 058/426] chore(deps): update docker/setup-buildx-action action to v3.8.0 (main) (#4209) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 6eb4012492..69aac8fad1 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -16,7 +16,7 @@ runs: - name: Set up QEMU uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 + uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 - name: Set up Golang uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: From d4aaf1be9082f68c0926b2206cf619a3cbf86742 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:19:16 +0100 Subject: [PATCH 059/426] cherry-pick: Update dynakube samples (#4160) (#4201) Co-authored-by: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Co-authored-by: Stefan Hauth --- .../v1beta3/applicationMonitoring.yaml | 18 +++++++ .../dynakube/v1beta3/classicFullStack.yaml | 18 +++++++ .../v1beta3/cloudNativeFullStack.yaml | 18 +++++++ .../dynakube/v1beta3/hostMonitoring.yaml | 18 +++++++ .../v1beta3/kubernetesObservability.yaml | 15 ++++++ .../kubernetesSecurityPostureManagement.yaml | 32 ++++++++++++ .../dynakube/v1beta3/logMonitoring.yaml | 24 +++++++++ .../dynakube/v1beta3/multipleDynakubes.yaml | 49 +++++++++++++++++++ 8 files changed, 192 insertions(+) create mode 100644 assets/samples/dynakube/v1beta3/applicationMonitoring.yaml create mode 100644 assets/samples/dynakube/v1beta3/classicFullStack.yaml create mode 100644 assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml create mode 100644 assets/samples/dynakube/v1beta3/hostMonitoring.yaml create mode 100644 assets/samples/dynakube/v1beta3/kubernetesObservability.yaml create mode 100644 assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml create mode 100644 assets/samples/dynakube/v1beta3/logMonitoring.yaml create mode 100644 assets/samples/dynakube/v1beta3/multipleDynakubes.yaml diff --git a/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml b/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml new file mode 100644 index 0000000000..38251f3aa6 --- /dev/null +++ b/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml @@ -0,0 +1,18 @@ +apiVersion: dynatrace.com/v1beta3 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + applicationMonitoring: {} + + activeGate: + capabilities: + - routing + - kubernetes-monitoring + - dynatrace-api diff --git a/assets/samples/dynakube/v1beta3/classicFullStack.yaml b/assets/samples/dynakube/v1beta3/classicFullStack.yaml new file mode 100644 index 0000000000..050ca5ad47 --- /dev/null +++ b/assets/samples/dynakube/v1beta3/classicFullStack.yaml @@ -0,0 +1,18 @@ +apiVersion: dynatrace.com/v1beta3 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + classicFullStack: {} + + activeGate: + capabilities: + - routing + - kubernetes-monitoring + - dynatrace-api diff --git a/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml b/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml new file mode 100644 index 0000000000..2bb9bb5db4 --- /dev/null +++ b/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml @@ -0,0 +1,18 @@ +apiVersion: dynatrace.com/v1beta3 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + cloudNativeFullStack: {} + + activeGate: + capabilities: + - routing + - kubernetes-monitoring + - dynatrace-api diff --git a/assets/samples/dynakube/v1beta3/hostMonitoring.yaml b/assets/samples/dynakube/v1beta3/hostMonitoring.yaml new file mode 100644 index 0000000000..42103677d4 --- /dev/null +++ b/assets/samples/dynakube/v1beta3/hostMonitoring.yaml @@ -0,0 +1,18 @@ +apiVersion: dynatrace.com/v1beta3 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + hostMonitoring: {} + + activeGate: + capabilities: + - routing + - kubernetes-monitoring + - dynatrace-api diff --git a/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml b/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml new file mode 100644 index 0000000000..84230e0392 --- /dev/null +++ b/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml @@ -0,0 +1,15 @@ +apiVersion: dynatrace.com/v1beta3 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace + # annotations: + # feature.dynatrace.com/k8s-app-enabled: "true" +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + activeGate: + capabilities: + - kubernetes-monitoring diff --git a/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml b/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml new file mode 100644 index 0000000000..c4719e087e --- /dev/null +++ b/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml @@ -0,0 +1,32 @@ +apiVersion: dynatrace.com/v1beta3 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + kspm: {} + + activeGate: + tlsSecretName: + + capabilities: + - kubernetes-monitoring + + customProperties: + value: | + [kubernetes_monitoring] + kubernetes_configuration_dataset_pipeline_enabled = true + kubernetes_configuration_dataset_pipeline_include_node_config = true + + templates: {} + # Required in combination with kspm enabled. + # As there is no image available in public registry yet, this field is required if you want to run kspm. + # + # kspmNodeConfigurationCollector: + # imageRef: + # repository: + # tag: diff --git a/assets/samples/dynakube/v1beta3/logMonitoring.yaml b/assets/samples/dynakube/v1beta3/logMonitoring.yaml new file mode 100644 index 0000000000..671c744492 --- /dev/null +++ b/assets/samples/dynakube/v1beta3/logMonitoring.yaml @@ -0,0 +1,24 @@ +apiVersion: dynatrace.com/v1beta3 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # The `logMonitoring` section is used to configure log collection via the OneAgent Log module. + # it can be used with any other DynaKube mode, e.g. applicationMonitoring. + # Available with Dynatrace version 1.306+ and OneAgent 1.305+ + + logMonitoring: {} + + templates: {} + # Required in combination with logMonitoring enabled. + # As there is no image available in public registry yet, this field is required if you want to run logMonitoring. + # + # logMonitoring: + # imageRef: + # repository: + # tag: diff --git a/assets/samples/dynakube/v1beta3/multipleDynakubes.yaml b/assets/samples/dynakube/v1beta3/multipleDynakubes.yaml new file mode 100644 index 0000000000..5b7d64fa1c --- /dev/null +++ b/assets/samples/dynakube/v1beta3/multipleDynakubes.yaml @@ -0,0 +1,49 @@ +apiVersion: dynatrace.com/v1beta3 +kind: DynaKube +metadata: + name: dynakube-application-monitoring + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + applicationMonitoring: + namespaceSelector: + matchLabels: + monitor: applicationMonitoring + + activeGate: + capabilities: + - kubernetes-monitoring +--- + +apiVersion: dynatrace.com/v1beta3 +kind: DynaKube +metadata: + name: dynakube-cloud-native + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + cloudNativeFullStack: + namespaceSelector: + matchLabels: + monitor: cloudNativeFullStack + + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + activeGate: + capabilities: + - routing + - dynatrace-api From 05b6f2b257e79e7837b34e43ae726fc18b4070dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 00:42:25 +0000 Subject: [PATCH 060/426] chore(deps): update actions/upload-artifact action to v4.5.0 (main) (#4217) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- .github/actions/preflight/action.yaml | 2 +- .github/workflows/openssf-scorecards.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 69aac8fad1..7966231b3f 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -45,7 +45,7 @@ runs: labels: ${{ inputs.labels }} outputs: type=docker,dest=/tmp/operator-${{ inputs.platform }}.tar - name: Upload artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 with: name: operator-${{ inputs.platform }} path: /tmp/operator-${{ inputs.platform }}.tar diff --git a/.github/actions/preflight/action.yaml b/.github/actions/preflight/action.yaml index 24d926c933..09dc8722ae 100644 --- a/.github/actions/preflight/action.yaml +++ b/.github/actions/preflight/action.yaml @@ -34,7 +34,7 @@ runs: run: | hack/build/ci/preflight.sh "${{ env.PREFLIGHT_VERSION }}" "${{ env.IMAGE_URI}}" "${{ inputs.report-name }}" - name: Upload report - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 with: name: preflight-report path: ${{ inputs.report-name }} diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 9be8cf3198..3ed9a10c5a 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -48,7 +48,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 with: name: SARIF file path: results.sarif From c1c5270662b233bde39d60ed048cccb8d1838ccb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 08:42:52 +0000 Subject: [PATCH 061/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1734495538 (main) (#4218) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7e5e7327bc..13d200ae41 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS=" -o ./build/_output/bin/dynatrace-operator ./cmd/ FROM registry.access.redhat.com/ubi9-micro:9.5-1734327559@sha256:a22fffe0256af00176c8b4f22eec5d8ecb1cb1684d811c33b1f2832fd573260f AS base -FROM registry.access.redhat.com/ubi9:9.5-1734081738@sha256:aa149a2e32725b0ea9c8ac97d25e65a894b1a4b2f220dd7670d890e60a733a14 AS dependency +FROM registry.access.redhat.com/ubi9:9.5-1734495538@sha256:38791b293262ac2169eca2717e68e626a047d2b89fbd1da544db24ed0204efeb AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 171cf9362f502844d26a878c5d354ae64e2d6cd8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:22:40 +0000 Subject: [PATCH 062/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1734513256 (main) (#4221) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 13d200ae41..177b60d294 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS=" go build -tags "${GO_BUILD_TAGS}" -trimpath -ldflags="${GO_LINKER_ARGS}" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ -FROM registry.access.redhat.com/ubi9-micro:9.5-1734327559@sha256:a22fffe0256af00176c8b4f22eec5d8ecb1cb1684d811c33b1f2832fd573260f AS base +FROM registry.access.redhat.com/ubi9-micro:9.5-1734513256@sha256:becdf7fff4509ee81df982000d0adef858a7ae7995dfb7d774b9ded6a461ebad AS base FROM registry.access.redhat.com/ubi9:9.5-1734495538@sha256:38791b293262ac2169eca2717e68e626a047d2b89fbd1da544db24ed0204efeb AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From f7392182616cccb48df8458b84e183eeeecee740 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 15:27:17 +0000 Subject: [PATCH 063/426] fix(deps): update module github.com/docker/cli to v27.4.1+incompatible (main) (#4223) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9d4402b8d9..ebc19df321 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.3 require ( github.com/container-storage-interface/spec v1.11.0 - github.com/docker/cli v27.4.0+incompatible + github.com/docker/cli v27.4.1+incompatible github.com/evanphx/json-patch v5.9.0+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.2 diff --git a/go.sum b/go.sum index d01d2e3109..15e93ae2a1 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v27.4.0+incompatible h1:/nJzWkcI1MDMN+U+px/YXnQWJqnu4J+QKGTfD6ptiTc= -github.com/docker/cli v27.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.4.1+incompatible h1:VzPiUlRJ/xh+otB75gva3r05isHMo5wXDfPRi5/b4hI= +github.com/docker/cli v27.4.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= From 933618436faeda6b1704aa8bfeb7c250429adb91 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:34:31 +0100 Subject: [PATCH 064/426] Mention new behavior of operator manifests (#4213) --- README.md | 64 +------------------------------------------------------ 1 file changed, 1 insertion(+), 63 deletions(-) diff --git a/README.md b/README.md index de23687579..a184798ca1 100644 --- a/README.md +++ b/README.md @@ -39,71 +39,9 @@ objects like permissions, custom resources and corresponding StatefulSets. ### Installation -> For install instructions on Openshift, head to the +> For install instructions, head to the > [official help page](https://www.dynatrace.com/support/help/shortlink/full-stack-dto-k8) -To create the namespace and apply the operator run the following commands - -```sh -kubectl create namespace dynatrace -kubectl apply -f https://github.com/Dynatrace/dynatrace-operator/releases/latest/download/kubernetes.yaml -``` - -If using `cloudNativeFullStack` or `applicationMonitoring` with CSI driver, the following command is required as well: - -```sh -kubectl apply -f https://github.com/Dynatrace/dynatrace-operator/releases/latest/download/kubernetes-csi.yaml -``` - -A secret holding tokens for authenticating to the Dynatrace cluster needs to be created upfront. Create access tokens of -type *Dynatrace API* and use its values in the following commands respectively. For -assistance please refer -to [Create user-generated access tokens](https://www.dynatrace.com/support/help/shortlink/token#create-api-token). - -The token scopes required by the Dynatrace Operator are documented on our [official help page](https://www.dynatrace.com/support/help/shortlink/full-stack-dto-k8#tokens) - -```sh -kubectl -n dynatrace create secret generic dynakube --from-literal="apiToken=DYNATRACE_API_TOKEN" --from-literal="dataIngestToken=DATA_INGEST_TOKEN" -``` - -#### Create `DynaKube` custom resource for ActiveGate and OneAgent rollout - -The rollout of the Dynatrace components is governed by a custom resource of type `DynaKube`. This custom resource will -contain parameters for various Dynatrace capabilities (OneAgent deployment mode, ActiveGate capabilities, etc.) - -> Note: `.spec.tokens` denotes the name of the secret holding access tokens. -> -> If not specified Dynatrace Operator searches for a secret called like the DynaKube custom resource `.metadata.name`. - -The recommended approach is using classic Fullstack injection to roll out Dynatrace to your cluster, available as [classicFullStack sample](assets/samples/dynakube/v1beta2/classicFullStack.yaml). -In case you want to have adjustments please have a look at [our DynaKube Custom Resource examples](assets/samples/dynakube). - -Save one of the sample configurations, change the API url to your environment and apply it to your cluster. - -```sh -kubectl apply -f cr.yaml -``` - -For detailed instructions see -our [official help page](https://www.dynatrace.com/support/help/shortlink/full-stack-dto-k8). - -## Uninstall dynatrace-operator - -> For instructions on how to uninstall the dynatrace-operator on Openshift, -> head to the [official help page](https://docs.dynatrace.com/docs/setup-and-configuration/setup-on-k8s/guides/operation/update-uninstall-operator#uninstall-dynatrace-operator) - -Clean-up all Dynatrace Operator specific objects: - -```sh -kubectl delete -f https://github.com/Dynatrace/dynatrace-operator/releases/latest/download/kubernetes.yaml -``` - -If the CSI driver was installed, the following command is required as well: - -```sh -kubectl delete -f https://github.com/Dynatrace/dynatrace-operator/releases/latest/download/kubernetes-csi.yaml -``` - ## Hacking See [HACKING](HACKING.md) for details on how to get started enhancing Dynatrace Operator. From 50c49aab44cb3981c4560c149dcec71a8279f6e9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:10:13 +0000 Subject: [PATCH 065/426] chore(deps): update codecov/codecov-action action to v5.1.2 (main) (#4225) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4a2061418f..aad785160b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -71,7 +71,7 @@ jobs: run: | make go/check-coverage - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # v5.1.1 + uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 # v5.1.2 with: fail_ci_if_error: true verbose: true From a76795788d0137325ba47896cc0b57a9b14046dd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 05:17:53 +0000 Subject: [PATCH 066/426] fix(deps): update module golang.org/x/net to v0.33.0 [security] (main) (#4227) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ebc19df321..186b595ea3 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.22.0 - golang.org/x/net v0.32.0 + golang.org/x/net v0.33.0 golang.org/x/oauth2 v0.24.0 golang.org/x/sys v0.28.0 google.golang.org/grpc v1.69.0 diff --git a/go.sum b/go.sum index 15e93ae2a1..32f8f4e919 100644 --- a/go.sum +++ b/go.sum @@ -185,8 +185,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 43e0cc52885dfb96b77ce8340a7fbfb2fe572b18 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 07:19:29 +0000 Subject: [PATCH 067/426] fix(deps): update module google.golang.org/grpc to v1.69.2 (main) (#4226) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 186b595ea3..d20d6f7bc6 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( golang.org/x/net v0.33.0 golang.org/x/oauth2 v0.24.0 golang.org/x/sys v0.28.0 - google.golang.org/grpc v1.69.0 + google.golang.org/grpc v1.69.2 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.1 istio.io/client-go v1.24.1 diff --git a/go.sum b/go.sum index 32f8f4e919..e30072fde3 100644 --- a/go.sum +++ b/go.sum @@ -224,8 +224,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 h1: google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.0 h1:quSiOM1GJPmPH5XtU+BCoVXcDVJJAzNcoyfC2cCjGkI= -google.golang.org/grpc v1.69.0/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= +google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 05cd9c7c685fa5d86940e7d5c0d2655e797b3fa6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 08:25:10 +0000 Subject: [PATCH 068/426] fix(deps): update module istio.io/api to v1.24.2 (main) (#4228) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d20d6f7bc6..75023d286b 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( golang.org/x/sys v0.28.0 google.golang.org/grpc v1.69.2 gopkg.in/yaml.v3 v3.0.1 - istio.io/api v1.24.1 + istio.io/api v1.24.2 istio.io/client-go v1.24.1 k8s.io/api v0.32.0 k8s.io/apiextensions-apiserver v0.32.0 diff --git a/go.sum b/go.sum index e30072fde3..508d6f9ddc 100644 --- a/go.sum +++ b/go.sum @@ -240,8 +240,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -istio.io/api v1.24.1 h1:jF1I+ABGVS7ImVKzaAeiXHkFEbfXN2IEKDGJTw5UX0w= -istio.io/api v1.24.1/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= +istio.io/api v1.24.2 h1:jYjcN6Iq0RPtQj/3KMFsybxmfqmjGN/dxhL7FGJEdIM= +istio.io/api v1.24.2/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= istio.io/client-go v1.24.1 h1:m1hYt+S7zZZpiWHVnJkp9SFfQ9EApBhKL0LUaviKh9c= istio.io/client-go v1.24.1/go.mod h1:sCDBDJWQGJQz/1t3CHwUTDE5V7Nk6pFFkqBwhIg+LrI= k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= From 035a728ff190affe164da3e5c345e1d5d543daf2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 08:37:37 +0000 Subject: [PATCH 069/426] fix(deps): update module istio.io/client-go to v1.24.2 (main) (#4229) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 75023d286b..2e1a4fd6a6 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( google.golang.org/grpc v1.69.2 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.2 - istio.io/client-go v1.24.1 + istio.io/client-go v1.24.2 k8s.io/api v0.32.0 k8s.io/apiextensions-apiserver v0.32.0 k8s.io/apimachinery v0.32.0 diff --git a/go.sum b/go.sum index 508d6f9ddc..a97d968faf 100644 --- a/go.sum +++ b/go.sum @@ -242,8 +242,8 @@ gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= istio.io/api v1.24.2 h1:jYjcN6Iq0RPtQj/3KMFsybxmfqmjGN/dxhL7FGJEdIM= istio.io/api v1.24.2/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= -istio.io/client-go v1.24.1 h1:m1hYt+S7zZZpiWHVnJkp9SFfQ9EApBhKL0LUaviKh9c= -istio.io/client-go v1.24.1/go.mod h1:sCDBDJWQGJQz/1t3CHwUTDE5V7Nk6pFFkqBwhIg+LrI= +istio.io/client-go v1.24.2 h1:JTTfBV6dv+AAW+AfccyrdX4T1f9CpsXd1Yzo1s/IYAI= +istio.io/client-go v1.24.2/go.mod h1:dgZ9EmJzh1EECzf6nQhwNL4R6RvlyeH/RXeNeNp/MRg= k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0= From a2010cf222599f4a7e009df1fdd89b2f81064170 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:59:43 +0100 Subject: [PATCH 070/426] Remove tenant image registry restriction for image fields (#4220) (#4234) --- pkg/api/validation/dynakube/image.go | 17 +--- pkg/api/validation/dynakube/image_test.go | 115 +++++++++++++++++++--- 2 files changed, 106 insertions(+), 26 deletions(-) diff --git a/pkg/api/validation/dynakube/image.go b/pkg/api/validation/dynakube/image.go index 6ce9b55113..11bbf22c2f 100644 --- a/pkg/api/validation/dynakube/image.go +++ b/pkg/api/validation/dynakube/image.go @@ -3,7 +3,6 @@ package validation import ( "context" "fmt" - "net/url" "strings" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" @@ -11,14 +10,10 @@ import ( ) const ( - errorUsingTenantImageAsCustom = `Custom %s image must not reference the Dynatrace Environment directly.` - errorUnparsableImageRef = `Custom %s image can't be parsed, make sure it's a valid image reference.` ) func imageFieldHasTenantImage(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - tenantHost := dk.ApiUrlHost() - type imageField struct { value string section string @@ -38,7 +33,7 @@ func imageFieldHasTenantImage(_ context.Context, _ *Validator, dk *dynakube.Dyna messages := []string{} for _, field := range imageFields { - message := checkImageField(field.value, field.section, tenantHost) + message := checkImageField(field.value, field.section) if message != "" { messages = append(messages, message) } @@ -47,18 +42,12 @@ func imageFieldHasTenantImage(_ context.Context, _ *Validator, dk *dynakube.Dyna return strings.Join(messages, ";") } -func checkImageField(image, section, disallowedHost string) (errorMsg string) { +func checkImageField(image, section string) (errorMsg string) { if image != "" { - ref, err := name.ParseReference(image) + _, err := name.ParseReference(image) if err != nil { return fmt.Sprintf(errorUnparsableImageRef, section) } - - refUrl, _ := url.Parse(ref.Name()) - - if refUrl.Host == disallowedHost { - return fmt.Sprintf(errorUsingTenantImageAsCustom, section) - } } return "" diff --git a/pkg/api/validation/dynakube/image_test.go b/pkg/api/validation/dynakube/image_test.go index a4b78a1429..8f5081339d 100644 --- a/pkg/api/validation/dynakube/image_test.go +++ b/pkg/api/validation/dynakube/image_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -38,13 +39,10 @@ func TestImageFieldHasTenantImage(t *testing.T) { }, }) }) - t.Run("image fields are using tenant repos", func(t *testing.T) { - expectedMessage := strings.Join([]string{ - fmt.Sprintf(errorUsingTenantImageAsCustom, "ActiveGate"), - fmt.Sprintf(errorUsingTenantImageAsCustom, "OneAgent"), - }, ";") - assertDenied(t, []string{expectedMessage}, &dynakube.DynaKube{ + t.Run("valid image fields", func(t *testing.T) { + testRegistryUrl := "my.images.com" + assertAllowed(t, &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Name: "dynakube", }, @@ -52,19 +50,19 @@ func TestImageFieldHasTenantImage(t *testing.T) { APIURL: testTenantUrl + "/api", OneAgent: dynakube.OneAgentSpec{ ClassicFullStack: &dynakube.HostInjectSpec{ - Image: testTenantUrl + "/linux/oneagent:latest", + Image: testRegistryUrl + "/linux/oneagent:latest", }, }, ActiveGate: activegate.Spec{ CapabilityProperties: activegate.CapabilityProperties{ - Image: testTenantUrl + "/linux/activegate:latest", + Image: testRegistryUrl + "/linux/activegate:latest", }, }, }, }) }) - t.Run("valid image fields", func(t *testing.T) { + t.Run("valid image fields - only OA", func(t *testing.T) { testRegistryUrl := "my.images.com" assertAllowed(t, &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ @@ -77,12 +75,105 @@ func TestImageFieldHasTenantImage(t *testing.T) { Image: testRegistryUrl + "/linux/oneagent:latest", }, }, - ActiveGate: activegate.Spec{ - CapabilityProperties: activegate.CapabilityProperties{ - Image: testRegistryUrl + "/linux/activegate:latest", + }, + }) + }) + + t.Run("ip:port", func(t *testing.T) { + assertAllowed(t, &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dynakube", + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testTenantUrl + "/api", + OneAgent: dynakube.OneAgentSpec{ + ClassicFullStack: &dynakube.HostInjectSpec{ + Image: "127.0.0.1:5000/test:tag", }, }, }, }) }) } + +func TestCheckImageField(t *testing.T) { + type testCase struct { + title string + imageURI string + isError bool + } + + testCases := []testCase{ + { + title: "uri without tag", + imageURI: "my.images.com/test", + isError: false, + }, + { + title: "uri with tag", + imageURI: "my.images.com/test:tag", + isError: false, + }, + { + title: "uri with protocol", + imageURI: "https://my.images.com/test:tag", + isError: false, + }, + { + title: "uri with port no protocol", + imageURI: "my.images.com:5000/test:tag", + isError: false, + }, + { + title: "uri with protocol:ip", + imageURI: "https://127.0.0.1/test:tag", + isError: false, + }, + { + title: "uri with ip:port no protocol", + imageURI: "127.0.0.1:5000/test:tag", + isError: false, + }, + { + title: "uri with ipv6:port", + imageURI: "[1080:0:0:0:8:800:200C:417A]:8888/test", + isError: false, + }, + { + title: "uri with ipv6:port:tag", + imageURI: "[1080:0:0:0:8:800:200C:417A]:8888/test:tag", + isError: false, + }, + { + title: "uri with protocol:ipv6:port", + imageURI: "https://[1080:0:0:0:8:800:200C:417A]:8888/test", + isError: true, // the image parsing library will error + }, + { + title: "uri with protocol:ip:port", + imageURI: "https://127.0.0.1:5000/test:tag", + isError: true, // the image parsing library will error + }, + { + title: "uri with protocol port", + imageURI: "https://my.images.com:5000/test:tag", + isError: true, // the image parsing library will error + }, + { + title: "some random URI", + imageURI: "BOOM", + isError: true, + }, + } + + for _, test := range testCases { + t.Run(test.title, func(t *testing.T) { + errMsg := checkImageField(test.imageURI, "test") + if test.isError { + require.NotEmpty(t, errMsg) + } else { + require.Empty(t, errMsg) + } + }) + } +} From c827bd288b91d9ef79f1a60fac19e34f39ed56e9 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Thu, 19 Dec 2024 10:44:01 +0100 Subject: [PATCH 071/426] Create separate reconciler for otel-collector (#4216) --- pkg/api/consts.go | 10 +- pkg/api/v1beta3/dynakube/extensions_props.go | 22 +- pkg/consts/extensions.go | 11 + pkg/consts/otelc.go | 7 + pkg/consts/tls.go | 10 + .../statefulset/builder/modifiers/eec.go | 2 +- pkg/controllers/dynakube/controller.go | 14 + .../dynakube/controller_system_test.go | 2 + pkg/controllers/dynakube/controller_test.go | 19 +- .../dynakube/extension/conditions.go | 6 + .../dynakube/extension/consts/consts.go | 31 +- .../dynakube/extension/eec/reconciler_test.go | 29 +- .../dynakube/extension/eec/statefulset.go | 25 +- .../dynakube/extension/otel/conditions.go | 3 - .../dynakube/extension/otel/reconciler.go | 59 ---- .../dynakube/extension/otel/statefulset.go | 332 ------------------ .../dynakube/extension/reconciler.go | 6 - .../dynakube/extension/reconciler_test.go | 24 +- pkg/controllers/dynakube/extension/secret.go | 23 +- pkg/controllers/dynakube/extension/service.go | 19 +- .../dynakube/extension/service_test.go | 3 +- .../dynakube/extension/servicename/naming.go | 18 - .../dynakube/extension/tls/reconciler.go | 26 +- .../dynakube/extension/tls/reconciler_test.go | 34 +- .../dynakube/extension/utils/utils.go | 40 --- .../{extension/otel => otelc}/config.go | 4 +- pkg/controllers/dynakube/otelc/reconciler.go | 39 ++ .../dynakube/otelc/statefulset/conditions.go | 3 + .../dynakube/otelc/statefulset/config.go | 9 + .../dynakube/otelc/statefulset/container.go | 42 +++ .../dynakube/otelc/statefulset/env.go | 88 +++++ .../dynakube/otelc/statefulset/reconciler.go | 189 ++++++++++ .../statefulset/reconciler_test.go} | 184 ++++++---- .../dynakube/otelc/statefulset/volumes.go | 93 +++++ pkg/util/kubeobjects/statefulset/builder.go | 9 +- pkg/util/kubeobjects/topology/constraint.go | 24 ++ 36 files changed, 796 insertions(+), 663 deletions(-) create mode 100644 pkg/consts/extensions.go create mode 100644 pkg/consts/otelc.go create mode 100644 pkg/consts/tls.go create mode 100644 pkg/controllers/dynakube/extension/conditions.go delete mode 100644 pkg/controllers/dynakube/extension/otel/conditions.go delete mode 100644 pkg/controllers/dynakube/extension/otel/reconciler.go delete mode 100644 pkg/controllers/dynakube/extension/otel/statefulset.go delete mode 100644 pkg/controllers/dynakube/extension/servicename/naming.go delete mode 100644 pkg/controllers/dynakube/extension/utils/utils.go rename pkg/controllers/dynakube/{extension/otel => otelc}/config.go (55%) create mode 100644 pkg/controllers/dynakube/otelc/reconciler.go create mode 100644 pkg/controllers/dynakube/otelc/statefulset/conditions.go create mode 100644 pkg/controllers/dynakube/otelc/statefulset/config.go create mode 100644 pkg/controllers/dynakube/otelc/statefulset/container.go create mode 100644 pkg/controllers/dynakube/otelc/statefulset/env.go create mode 100644 pkg/controllers/dynakube/otelc/statefulset/reconciler.go rename pkg/controllers/dynakube/{extension/otel/statefulset_test.go => otelc/statefulset/reconciler_test.go} (84%) create mode 100644 pkg/controllers/dynakube/otelc/statefulset/volumes.go create mode 100644 pkg/util/kubeobjects/topology/constraint.go diff --git a/pkg/api/consts.go b/pkg/api/consts.go index 703e048bee..3dc4754d1f 100644 --- a/pkg/api/consts.go +++ b/pkg/api/consts.go @@ -1,10 +1,8 @@ package api const ( - LatestTag = "latest" - RawTag = "raw" - AnnotationDynatraceExtensions = "dynatrace.com/extensions" - AnnotationDynatraceOpenTelemetryCollector = "dynatrace.com/openTelemetryCollector" - AnnotationDynatraceextEnsionExecutionController = "dynatrace.com/extensionExecutionController" - InternalFlagPrefix = "internal.operator.dynatrace.com/" + LatestTag = "latest" + RawTag = "raw" + InternalFlagPrefix = "internal.operator.dynatrace.com/" + AnnotationSecretHash = InternalFlagPrefix + "secret-hash" ) diff --git a/pkg/api/v1beta3/dynakube/extensions_props.go b/pkg/api/v1beta3/dynakube/extensions_props.go index 53601efc32..6bfe4bba2a 100644 --- a/pkg/api/v1beta3/dynakube/extensions_props.go +++ b/pkg/api/v1beta3/dynakube/extensions_props.go @@ -1,6 +1,8 @@ package dynakube -import "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/consts" +) func (dk *DynaKube) IsExtensionsEnabled() bool { return dk.Spec.Extensions != nil @@ -16,12 +18,16 @@ func (dk *DynaKube) ExtensionsNeedsSelfSignedTLS() bool { func (dk *DynaKube) ExtensionsTLSSecretName() string { if dk.ExtensionsNeedsSelfSignedTLS() { - return dk.Name + consts.ExtensionsSelfSignedTLSSecretSuffix + return dk.ExtensionsSelfSignedTLSSecretName() } return dk.ExtensionsTLSRefName() } +func (dk *DynaKube) ExtensionsSelfSignedTLSSecretName() string { + return dk.Name + consts.ExtensionsSelfSignedTLSSecretSuffix +} + func (dk *DynaKube) ExtensionsExecutionControllerStatefulsetName() string { return dk.Name + "-extensions-controller" } @@ -33,3 +39,15 @@ func (dk *DynaKube) ExtensionsCollectorStatefulsetName() string { func (dk *DynaKube) ExtensionsTokenSecretName() string { return dk.Name + "-extensions-token" } + +func (dk *DynaKube) ExtensionsPortName() string { + return "dynatrace" + consts.ExtensionsControllerSuffix + "-" + consts.ExtensionsCollectorTargetPortName +} + +func (dk *DynaKube) ExtensionsServiceNameFQDN() string { + return dk.ExtensionsServiceName() + "." + dk.Namespace +} + +func (dk *DynaKube) ExtensionsServiceName() string { + return dk.Name + consts.ExtensionsControllerSuffix +} diff --git a/pkg/consts/extensions.go b/pkg/consts/extensions.go new file mode 100644 index 0000000000..78386dab39 --- /dev/null +++ b/pkg/consts/extensions.go @@ -0,0 +1,11 @@ +package consts + +const ( + ExtensionsSelfSignedTLSSecretSuffix = "-extensions-controller-tls" + + // shared volume name between eec and OtelC + ExtensionsTokensVolumeName = "tokens" + + ExtensionsControllerSuffix = "-extensions-controller" + ExtensionsCollectorTargetPortName = "collector-com" +) diff --git a/pkg/consts/otelc.go b/pkg/consts/otelc.go new file mode 100644 index 0000000000..4e655cc3d9 --- /dev/null +++ b/pkg/consts/otelc.go @@ -0,0 +1,7 @@ +package consts + +const ( + OtelcTokenSecretKey = "otelc.token" + OtelcTokenSecretValuePrefix = "dt0x01" + OtelCollectorComPort = 14599 +) diff --git a/pkg/consts/tls.go b/pkg/consts/tls.go new file mode 100644 index 0000000000..1efb27d753 --- /dev/null +++ b/pkg/consts/tls.go @@ -0,0 +1,10 @@ +package consts + +const ( + + // TLSKeyDataName is the key used to store a TLS private key in the secret's data field. + TLSKeyDataName = "tls.key" + + // TLSCrtDataName is the key used to store a TLS certificate in the secret's data field. + TLSCrtDataName = "tls.crt" +) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec.go index 32d32c1ef7..5aa66850bf 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec.go @@ -54,7 +54,7 @@ func (mod EecModifier) getVolumes() []corev1.Volume { DefaultMode: &mode, Items: []corev1.KeyToPath{ { - Key: eecconsts.EecTokenSecretKey, + Key: eecconsts.TokenSecretKey, Path: eecFile, Mode: &mode, }, diff --git a/pkg/controllers/dynakube/controller.go b/pkg/controllers/dynakube/controller.go index b82ae22675..3c38cafd20 100644 --- a/pkg/controllers/dynakube/controller.go +++ b/pkg/controllers/dynakube/controller.go @@ -21,6 +21,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" @@ -77,6 +78,7 @@ func NewDynaKubeController(kubeClient client.Client, apiReader client.Reader, co injectionReconcilerBuilder: injection.NewReconciler, istioReconcilerBuilder: istio.NewReconciler, extensionReconcilerBuilder: extension.NewReconciler, + otelcReconcilerBuilder: otelc.NewReconciler, logMonitoringReconcilerBuilder: logmonitoring.NewReconciler, proxyReconcilerBuilder: proxy.NewReconciler, kspmReconcilerBuilder: kspm.NewReconciler, @@ -113,6 +115,7 @@ type Controller struct { injectionReconcilerBuilder injection.ReconcilerBuilder istioReconcilerBuilder istio.ReconcilerBuilder extensionReconcilerBuilder extension.ReconcilerBuilder + otelcReconcilerBuilder otelc.ReconcilerBuilder logMonitoringReconcilerBuilder logmonitoring.ReconcilerBuilder proxyReconcilerBuilder proxy.ReconcilerBuilder kspmReconcilerBuilder kspm.ReconcilerBuilder @@ -332,6 +335,17 @@ func (controller *Controller) reconcileComponents(ctx context.Context, dynatrace componentErrors = append(componentErrors, err) } + log.Info("start reconciling otel-collector") + + otelcReconciler := controller.otelcReconcilerBuilder(controller.client, controller.apiReader, dk) + + err = otelcReconciler.Reconcile(ctx) + if err != nil { + log.Info("could not reconcile otelc") + + componentErrors = append(componentErrors, err) + } + log.Info("start reconciling LogMonitoring") logMonitoringReconciler := controller.logMonitoringReconcilerBuilder(controller.client, controller.apiReader, dynatraceClient, dk) diff --git a/pkg/controllers/dynakube/controller_system_test.go b/pkg/controllers/dynakube/controller_system_test.go index 1f95f5695c..d43f8c7927 100644 --- a/pkg/controllers/dynakube/controller_system_test.go +++ b/pkg/controllers/dynakube/controller_system_test.go @@ -21,6 +21,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/kspm" logmon "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubesystem" @@ -436,6 +437,7 @@ func createFakeClientAndReconciler(t *testing.T, mockClient dtclient.Client, dk logMonitoringReconcilerBuilder: logmon.NewReconciler, proxyReconcilerBuilder: proxy.NewReconciler, extensionReconcilerBuilder: extension.NewReconciler, + otelcReconcilerBuilder: otelc.NewReconciler, kspmReconcilerBuilder: kspm.NewReconciler, clusterID: testUID, } diff --git a/pkg/controllers/dynakube/controller_test.go b/pkg/controllers/dynakube/controller_test.go index 8491e86e0f..a4048126eb 100644 --- a/pkg/controllers/dynakube/controller_test.go +++ b/pkg/controllers/dynakube/controller_test.go @@ -23,6 +23,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" @@ -350,6 +351,9 @@ func TestReconcileComponents(t *testing.T) { mockExtensionReconciler := controllermock.NewReconciler(t) mockExtensionReconciler.On("Reconcile", mock.Anything).Return(errors.New("BOOM")) + mockOtelcReconciler := controllermock.NewReconciler(t) + mockOtelcReconciler.On("Reconcile", mock.Anything).Return(errors.New("BOOM")) + mockKSPMReconciler := controllermock.NewReconciler(t) mockKSPMReconciler.On("Reconcile", mock.Anything).Return(errors.New("BOOM")) @@ -363,6 +367,7 @@ func TestReconcileComponents(t *testing.T) { oneAgentReconcilerBuilder: createOneAgentReconcilerBuilder(mockOneAgentReconciler), logMonitoringReconcilerBuilder: createLogMonitoringReconcilerBuilder(mockLogMonitoringReconciler), extensionReconcilerBuilder: createExtensionReconcilerBuilder(mockExtensionReconciler), + otelcReconcilerBuilder: createOtelcReconcilerBuilder(mockOtelcReconciler), kspmReconcilerBuilder: createKSPMReconcilerBuilder(mockKSPMReconciler), } mockedDtc := dtclientmock.NewClient(t) @@ -371,7 +376,7 @@ func TestReconcileComponents(t *testing.T) { require.Error(t, err) // goerrors.Join concats errors with \n - assert.Len(t, strings.Split(err.Error(), "\n"), 6) // ActiveGate, Extension, OneAgent LogMonitoring, and Injection reconcilers + assert.Len(t, strings.Split(err.Error(), "\n"), 7) // ActiveGate, Extension, OtelC, OneAgent LogMonitoring, and Injection reconcilers }) t.Run("exit early in case of no oneagent conncection info", func(t *testing.T) { @@ -384,6 +389,9 @@ func TestReconcileComponents(t *testing.T) { mockExtensionReconciler := controllermock.NewReconciler(t) mockExtensionReconciler.On("Reconcile", mock.Anything).Return(errors.New("BOOM")) + mockOtelcReconciler := controllermock.NewReconciler(t) + mockOtelcReconciler.On("Reconcile", mock.Anything).Return(errors.New("BOOM")) + mockLogMonitoringReconciler := injectionmock.NewReconciler(t) mockLogMonitoringReconciler.On("Reconcile", mock.Anything).Return(oaconnectioninfo.NoOneAgentCommunicationHostsError) @@ -394,6 +402,7 @@ func TestReconcileComponents(t *testing.T) { activeGateReconcilerBuilder: createActivegateReconcilerBuilder(mockActiveGateReconciler), logMonitoringReconcilerBuilder: createLogMonitoringReconcilerBuilder(mockLogMonitoringReconciler), extensionReconcilerBuilder: createExtensionReconcilerBuilder(mockExtensionReconciler), + otelcReconcilerBuilder: createOtelcReconcilerBuilder(mockOtelcReconciler), } mockedDtc := dtclientmock.NewClient(t) @@ -401,7 +410,7 @@ func TestReconcileComponents(t *testing.T) { require.Error(t, err) // goerrors.Join concats errors with \n - assert.Len(t, strings.Split(err.Error(), "\n"), 2) // ActiveGate, Extension, no OneAgent connection info is not an error + assert.Len(t, strings.Split(err.Error(), "\n"), 3) // ActiveGate, Extension, OtelC, no OneAgent connection info is not an error }) } @@ -429,6 +438,12 @@ func createExtensionReconcilerBuilder(reconciler controllers.Reconciler) extensi } } +func createOtelcReconcilerBuilder(reconciler controllers.Reconciler) otelc.ReconcilerBuilder { + return func(_ client.Client, _ client.Reader, _ *dynakube.DynaKube) controllers.Reconciler { + return reconciler + } +} + func createInjectionReconcilerBuilder(reconciler *injectionmock.Reconciler) injection.ReconcilerBuilder { return func(_ client.Client, _ client.Reader, _ dtclient.Client, _ *istio.Client, _ *dynakube.DynaKube) controllers.Reconciler { return reconciler diff --git a/pkg/controllers/dynakube/extension/conditions.go b/pkg/controllers/dynakube/extension/conditions.go new file mode 100644 index 0000000000..32af03f3e4 --- /dev/null +++ b/pkg/controllers/dynakube/extension/conditions.go @@ -0,0 +1,6 @@ +package extension + +const ( + secretConditionType = "ExtensionsSecret" + serviceConditionType = "ExtensionsService" +) diff --git a/pkg/controllers/dynakube/extension/consts/consts.go b/pkg/controllers/dynakube/extension/consts/consts.go index e397da06c0..499ac460c0 100644 --- a/pkg/controllers/dynakube/extension/consts/consts.go +++ b/pkg/controllers/dynakube/extension/consts/consts.go @@ -1,33 +1,8 @@ package consts -import "github.com/Dynatrace/dynatrace-operator/pkg/api" - const ( - ExtensionsAnnotationSecretHash = api.InternalFlagPrefix + "secret-hash" - - // secret - EecTokenSecretKey = "eec.token" - EecTokenSecretValuePrefix = "EEC dt0x01" - - OtelcTokenSecretKey = "otelc.token" - OtelcTokenSecretValuePrefix = "dt0x01" - - // shared volume name between eec and OtelC - ExtensionsTokensVolumeName = "tokens" - - ExtensionsSecretConditionType = "ExtensionsSecret" - ExtensionsServiceConditionType = "ExtensionsService" - - ExtensionsControllerSuffix = "-extensions-controller" - ExtensionsCollectorComPort = 14599 - ExtensionsCollectorTargetPortName = "collector-com" - - ExtensionsSelfSignedTLSSecretSuffix = "-extensions-controller-tls" - ExtensionsSelfSignedTLSCommonNameSuffix = "-extensions-controller.dynatrace" - - // TLSKeyDataName is the key used to store a TLS private key in the secret's data field. - TLSKeyDataName = "tls.key" + TokenSecretKey = "eec.token" + TokenSecretValuePrefix = "EEC dt0x01" - // TLSCrtDataName is the key used to store a TLS certificate in the secret's data field. - TLSCrtDataName = "tls.crt" + ExtensionsControllerSuffix = "-extensions-controller" ) diff --git a/pkg/controllers/dynakube/extension/eec/reconciler_test.go b/pkg/controllers/dynakube/extension/eec/reconciler_test.go index d527949b22..3b410335ff 100644 --- a/pkg/controllers/dynakube/extension/eec/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/eec/reconciler_test.go @@ -4,17 +4,18 @@ import ( "strconv" "testing" + "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/tls" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/utils" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + eecConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/topology" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -84,7 +85,7 @@ func getStatefulset(t *testing.T, dk *dynakube.DynaKube) *appsv1.StatefulSet { } func mockTLSSecret(t *testing.T, client client.Client, dk *dynakube.DynaKube) client.Client { - tlsSecret := getTLSSecret(tls.GetTLSSecretName(dk), dk.Namespace, "super-cert", "super-key") + tlsSecret := getTLSSecret(dk.ExtensionsTLSSecretName(), dk.Namespace, "super-cert", "super-key") err := client.Create(context.Background(), &tlsSecret) require.NoError(t, err) @@ -179,7 +180,7 @@ func TestSecretHashAnnotation(t *testing.T) { statefulSet := getStatefulset(t, dk) require.Len(t, statefulSet.Spec.Template.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[consts.ExtensionsAnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash]) }) t.Run("annotation is set with tlsRefName", func(t *testing.T) { dk := getTestDynakube() @@ -187,7 +188,7 @@ func TestSecretHashAnnotation(t *testing.T) { statefulSet := getStatefulset(t, dk) require.Len(t, statefulSet.Spec.Template.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[consts.ExtensionsAnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash]) }) t.Run("annotation is updated when TLS Secret gets updated", func(t *testing.T) { statefulSet := &appsv1.StatefulSet{} @@ -204,10 +205,10 @@ func TestSecretHashAnnotation(t *testing.T) { err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsExecutionControllerStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) - originalSecretHash := statefulSet.Spec.Template.Annotations[consts.ExtensionsAnnotationSecretHash] + originalSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash] // then update the TLS Secret and call reconcile again - updatedTLSSecret := getTLSSecret(tls.GetTLSSecretName(dk), dk.Namespace, "updated-cert", "updated-key") + updatedTLSSecret := getTLSSecret(dk.ExtensionsTLSSecretName(), dk.Namespace, "updated-cert", "updated-key") err = mockK8sClient.Update(context.Background(), &updatedTLSSecret) require.NoError(t, err) @@ -216,7 +217,7 @@ func TestSecretHashAnnotation(t *testing.T) { err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsExecutionControllerStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) - resultingSecretHash := statefulSet.Spec.Template.Annotations[consts.ExtensionsAnnotationSecretHash] + resultingSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash] // original hash and resulting hash should be different, value got updated on reconcile assert.NotEqual(t, originalSecretHash, resultingSecretHash) @@ -228,7 +229,7 @@ func TestTopologySpreadConstraints(t *testing.T) { dk := getTestDynakube() statefulSet := getStatefulset(t, dk) appLabels := buildAppLabels(dk.Name) - assert.Equal(t, utils.BuildTopologySpreadConstraints(dk.Spec.Templates.ExtensionExecutionController.TopologySpreadConstraints, appLabels), statefulSet.Spec.Template.Spec.TopologySpreadConstraints) + assert.Equal(t, topology.MaxOnePerNode(appLabels), statefulSet.Spec.Template.Spec.TopologySpreadConstraints) }) t.Run("custom TopologySpreadConstraints", func(t *testing.T) { @@ -263,12 +264,12 @@ func TestEnvironmentVariables(t *testing.T) { assert.Equal(t, corev1.EnvVar{Name: envTenantId, Value: dk.Status.ActiveGate.ConnectionInfo.TenantUUID}, statefulSet.Spec.Template.Spec.Containers[0].Env[0]) assert.Equal(t, corev1.EnvVar{Name: envServerUrl, Value: buildActiveGateServiceName(dk) + "." + dk.Namespace + ".svc.cluster.local:443"}, statefulSet.Spec.Template.Spec.Containers[0].Env[1]) - assert.Equal(t, corev1.EnvVar{Name: envEecTokenPath, Value: eecTokenMountPath + "/" + consts.EecTokenSecretKey}, statefulSet.Spec.Template.Spec.Containers[0].Env[2]) + assert.Equal(t, corev1.EnvVar{Name: envEecTokenPath, Value: eecTokenMountPath + "/" + eecConsts.TokenSecretKey}, statefulSet.Spec.Template.Spec.Containers[0].Env[2]) assert.Equal(t, corev1.EnvVar{Name: envEecIngestPort, Value: strconv.Itoa(int(collectorPort))}, statefulSet.Spec.Template.Spec.Containers[0].Env[3]) assert.Equal(t, corev1.EnvVar{Name: envExtensionsModuleExecPathName, Value: envExtensionsModuleExecPath}, statefulSet.Spec.Template.Spec.Containers[0].Env[4]) assert.Equal(t, corev1.EnvVar{Name: envDsInstallDirName, Value: envDsInstallDir}, statefulSet.Spec.Template.Spec.Containers[0].Env[5]) assert.Equal(t, corev1.EnvVar{Name: envK8sClusterId, Value: dk.Status.KubeSystemUUID}, statefulSet.Spec.Template.Spec.Containers[0].Env[6]) - assert.Equal(t, corev1.EnvVar{Name: envK8sExtServiceUrl, Value: "https://" + dk.Name + consts.ExtensionsControllerSuffix + "." + dk.Namespace}, statefulSet.Spec.Template.Spec.Containers[0].Env[7]) + assert.Equal(t, corev1.EnvVar{Name: envK8sExtServiceUrl, Value: "https://" + dk.Name + eecConsts.ExtensionsControllerSuffix + "." + dk.Namespace}, statefulSet.Spec.Template.Spec.Containers[0].Env[7]) assert.Equal(t, corev1.EnvVar{Name: envDSTokenPath, Value: eecTokenMountPath + "/" + consts.OtelcTokenSecretKey}, statefulSet.Spec.Template.Spec.Containers[0].Env[8]) assert.Equal(t, corev1.EnvVar{Name: envHttpsCertPathPem, Value: envEecHttpsCertPathPem}, statefulSet.Spec.Template.Spec.Containers[0].Env[9]) assert.Equal(t, corev1.EnvVar{Name: envHttpsPrivKeyPathPem, Value: envEecHttpsPrivKeyPathPem}, statefulSet.Spec.Template.Spec.Containers[0].Env[10]) @@ -547,7 +548,7 @@ func TestAnnotations(t *testing.T) { assert.Len(t, statefulSet.ObjectMeta.Annotations, 2) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[consts.ExtensionsAnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationSecretHash]) }) t.Run("custom annotations", func(t *testing.T) { @@ -563,7 +564,7 @@ func TestAnnotations(t *testing.T) { assert.Empty(t, statefulSet.ObjectMeta.Annotations["a"]) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 2) assert.Equal(t, "b", statefulSet.Spec.Template.ObjectMeta.Annotations["a"]) - assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[consts.ExtensionsAnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationSecretHash]) }) } diff --git a/pkg/controllers/dynakube/extension/eec/statefulset.go b/pkg/controllers/dynakube/extension/eec/statefulset.go index 7421b3982a..af9039edd5 100644 --- a/pkg/controllers/dynakube/extension/eec/statefulset.go +++ b/pkg/controllers/dynakube/extension/eec/statefulset.go @@ -3,18 +3,18 @@ package eec import ( "strconv" + "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/servicename" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/tls" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/utils" + eecConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/statefulset" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/topology" "golang.org/x/net/context" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -84,6 +84,11 @@ func (r *reconciler) createOrUpdateStatefulset(ctx context.Context) error { return err } + topologySpreadConstraints := topology.MaxOnePerNode(appLabels) + if len(r.dk.Spec.Templates.ExtensionExecutionController.TopologySpreadConstraints) > 0 { + topologySpreadConstraints = r.dk.Spec.Templates.ExtensionExecutionController.TopologySpreadConstraints + } + desiredSts, err := statefulset.Build(r.dk, r.dk.ExtensionsExecutionControllerStatefulsetName(), buildContainer(r.dk), statefulset.SetReplicas(1), statefulset.SetPodManagementPolicy(appsv1.ParallelPodManagement), @@ -91,10 +96,10 @@ func (r *reconciler) createOrUpdateStatefulset(ctx context.Context) error { statefulset.SetAllAnnotations(nil, templateAnnotations), statefulset.SetAffinity(buildAffinity()), statefulset.SetTolerations(r.dk.Spec.Templates.ExtensionExecutionController.Tolerations), - statefulset.SetTopologySpreadConstraints(utils.BuildTopologySpreadConstraints(r.dk.Spec.Templates.ExtensionExecutionController.TopologySpreadConstraints, appLabels)), + statefulset.SetTopologySpreadConstraints(topologySpreadConstraints), statefulset.SetServiceAccount(serviceAccountName), statefulset.SetSecurityContext(buildPodSecurityContext(r.dk)), - statefulset.SetUpdateStrategy(utils.BuildUpdateStrategy()), + statefulset.SetRollingUpdateStrategyType(), setImagePullSecrets(r.dk.ImagePullSecretReferences()), setVolumes(r.dk), setPersistentVolumeClaim(r.dk), @@ -135,7 +140,7 @@ func (r *reconciler) buildTemplateAnnotations(ctx context.Context) (map[string]s query := k8ssecret.Query(r.client, r.client, log) tlsSecret, err := query.Get(ctx, types.NamespacedName{ - Name: tls.GetTLSSecretName(r.dk), + Name: r.dk.ExtensionsTLSSecretName(), Namespace: r.dk.Namespace, }) if err != nil { @@ -147,7 +152,7 @@ func (r *reconciler) buildTemplateAnnotations(ctx context.Context) (map[string]s return nil, err } - templateAnnotations[consts.ExtensionsAnnotationSecretHash] = tlsSecretHash + templateAnnotations[api.AnnotationSecretHash] = tlsSecretHash return templateAnnotations, nil } @@ -238,12 +243,12 @@ func buildContainerEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { containerEnvs := []corev1.EnvVar{ {Name: envTenantId, Value: dk.Status.ActiveGate.ConnectionInfo.TenantUUID}, {Name: envServerUrl, Value: buildActiveGateServiceName(dk) + "." + dk.Namespace + ".svc.cluster.local:443"}, - {Name: envEecTokenPath, Value: eecTokenMountPath + "/" + consts.EecTokenSecretKey}, + {Name: envEecTokenPath, Value: eecTokenMountPath + "/" + eecConsts.TokenSecretKey}, {Name: envEecIngestPort, Value: strconv.Itoa(int(collectorPort))}, {Name: envExtensionsModuleExecPathName, Value: envExtensionsModuleExecPath}, {Name: envDsInstallDirName, Value: envDsInstallDir}, {Name: envK8sClusterId, Value: dk.Status.KubeSystemUUID}, - {Name: envK8sExtServiceUrl, Value: serviceUrlScheme + servicename.BuildFQDN(dk)}, + {Name: envK8sExtServiceUrl, Value: serviceUrlScheme + dk.ExtensionsServiceNameFQDN()}, {Name: envDSTokenPath, Value: eecTokenMountPath + "/" + consts.OtelcTokenSecretKey}, {Name: envHttpsCertPathPem, Value: envEecHttpsCertPathPem}, {Name: envHttpsPrivKeyPathPem, Value: envEecHttpsPrivKeyPathPem}, diff --git a/pkg/controllers/dynakube/extension/otel/conditions.go b/pkg/controllers/dynakube/extension/otel/conditions.go deleted file mode 100644 index 3d055c4a93..0000000000 --- a/pkg/controllers/dynakube/extension/otel/conditions.go +++ /dev/null @@ -1,3 +0,0 @@ -package otel - -const otelControllerStatefulSetConditionType string = "OtelStatefulSet" diff --git a/pkg/controllers/dynakube/extension/otel/reconciler.go b/pkg/controllers/dynakube/extension/otel/reconciler.go deleted file mode 100644 index 38ac866881..0000000000 --- a/pkg/controllers/dynakube/extension/otel/reconciler.go +++ /dev/null @@ -1,59 +0,0 @@ -package otel - -import ( - "context" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/statefulset" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -type reconciler struct { - client client.Client - apiReader client.Reader - - dk *dynakube.DynaKube -} - -type ReconcilerBuilder func(clt client.Client, apiReader client.Reader, dk *dynakube.DynaKube) controllers.Reconciler - -var _ ReconcilerBuilder = NewReconciler - -func NewReconciler(clt client.Client, apiReader client.Reader, dk *dynakube.DynaKube) controllers.Reconciler { - return &reconciler{ - client: clt, - apiReader: apiReader, - dk: dk, - } -} - -func (r *reconciler) Reconcile(ctx context.Context) error { - if !r.dk.IsExtensionsEnabled() { - if meta.FindStatusCondition(*r.dk.Conditions(), otelControllerStatefulSetConditionType) == nil { - return nil - } - defer meta.RemoveStatusCondition(r.dk.Conditions(), otelControllerStatefulSetConditionType) - - sts, err := statefulset.Build(r.dk, r.dk.ExtensionsCollectorStatefulsetName(), corev1.Container{}) - if err != nil { - log.Error(err, "could not build "+r.dk.ExtensionsCollectorStatefulsetName()+" during cleanup") - - return err - } - - err = statefulset.Query(r.client, r.apiReader, log).Delete(ctx, sts) - - if err != nil { - log.Error(err, "failed to clean up "+r.dk.ExtensionsCollectorStatefulsetName()+" statufulset") - - return nil - } - - return nil - } - - return r.createOrUpdateStatefulset(ctx) -} diff --git a/pkg/controllers/dynakube/extension/otel/statefulset.go b/pkg/controllers/dynakube/extension/otel/statefulset.go deleted file mode 100644 index 10b0ce421b..0000000000 --- a/pkg/controllers/dynakube/extension/otel/statefulset.go +++ /dev/null @@ -1,332 +0,0 @@ -package otel - -import ( - "context" - "fmt" - "strconv" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/servicename" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/tls" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/utils" - "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" - "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" - k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/statefulset" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/ptr" -) - -const ( - serviceAccountName = "dynatrace-extensions-collector" - containerName = "collector" - - // default values - defaultImageRepo = "public.ecr.aws/dynatrace/dynatrace-otel-collector" - defaultImageTag = "latest" - defaultOLTPgrpcPort = "10001" - defaultOLTPhttpPort = "10002" - defaultReplicas = 1 - - // env variables - envShards = "SHARDS" - envShardId = "SHARD_ID" - envPodNamePrefix = "POD_NAME_PREFIX" - envPodName = "POD_NAME" - envOTLPgrpcPort = "OTLP_GRPC_PORT" - envOTLPhttpPort = "OTLP_HTTP_PORT" - envOTLPtoken = "OTLP_TOKEN" - envEECDStoken = "EEC_DS_TOKEN" - envTrustedCAs = "TRUSTED_CAS" - envK8sClusterName = "K8S_CLUSTER_NAME" - envK8sClusterUuid = "K8S_CLUSTER_UID" - envDTentityK8sCluster = "DT_ENTITY_KUBERNETES_CLUSTER" - // certDirEnv is the environment variable that identifies which directory - // to check for SSL certificate files. If set, this overrides the system default. - // It is a colon separated list of directories. - // See https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html. - envCertDir = "SSL_CERT_DIR" - envEECcontrollerTLS = "EXTENSIONS_CONTROLLER_TLS" - - // Volume names and paths - caCertsVolumeName = "cacerts" - trustedCAVolumeMountPath = "/tls/custom/cacerts" - trustedCAVolumePath = trustedCAVolumeMountPath + "/certs" - customEecTLSCertificatePath = "/tls/custom/eec" - customEecTLSCertificateFullPath = customEecTLSCertificatePath + "/" + consts.TLSCrtDataName - secretsTokensPath = "/secrets/tokens" - otelcSecretTokenFilePath = secretsTokensPath + "/" + consts.OtelcTokenSecretKey - - // misc - trustedCAsFile = "rootca.pem" -) - -func (r *reconciler) createOrUpdateStatefulset(ctx context.Context) error { - appLabels := buildAppLabels(r.dk.Name) - - templateAnnotations, err := r.buildTemplateAnnotations(ctx) - if err != nil { - return err - } - - sts, err := statefulset.Build(r.dk, r.dk.ExtensionsCollectorStatefulsetName(), buildContainer(r.dk), - statefulset.SetReplicas(getReplicas(r.dk)), - statefulset.SetPodManagementPolicy(appsv1.ParallelPodManagement), - statefulset.SetAllLabels(appLabels.BuildLabels(), appLabels.BuildMatchLabels(), appLabels.BuildLabels(), r.dk.Spec.Templates.OpenTelemetryCollector.Labels), - statefulset.SetAllAnnotations(nil, templateAnnotations), - statefulset.SetAffinity(buildAffinity()), - statefulset.SetServiceAccount(serviceAccountName), - statefulset.SetTolerations(r.dk.Spec.Templates.OpenTelemetryCollector.Tolerations), - statefulset.SetTopologySpreadConstraints(utils.BuildTopologySpreadConstraints(r.dk.Spec.Templates.OpenTelemetryCollector.TopologySpreadConstraints, appLabels)), - statefulset.SetSecurityContext(buildPodSecurityContext()), - statefulset.SetUpdateStrategy(utils.BuildUpdateStrategy()), - setImagePullSecrets(r.dk.ImagePullSecretReferences()), - setVolumes(r.dk), - ) - - if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), otelControllerStatefulSetConditionType, err) - - return err - } - - if err := hasher.AddAnnotation(sts); err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), otelControllerStatefulSetConditionType, err) - - return err - } - - _, err = statefulset.Query(r.client, r.apiReader, log).WithOwner(r.dk).CreateOrUpdate(ctx, sts) - if err != nil { - log.Info("failed to create/update " + r.dk.ExtensionsCollectorStatefulsetName() + " statefulset") - conditions.SetKubeApiError(r.dk.Conditions(), otelControllerStatefulSetConditionType, err) - - return err - } - - conditions.SetStatefulSetCreated(r.dk.Conditions(), otelControllerStatefulSetConditionType, sts.Name) - - return nil -} - -func (r *reconciler) buildTemplateAnnotations(ctx context.Context) (map[string]string, error) { - templateAnnotations := map[string]string{} - - if r.dk.Spec.Templates.OpenTelemetryCollector.Annotations != nil { - templateAnnotations = r.dk.Spec.Templates.OpenTelemetryCollector.Annotations - } - - query := k8ssecret.Query(r.client, r.client, log) - - tlsSecret, err := query.Get(ctx, types.NamespacedName{ - Name: tls.GetTLSSecretName(r.dk), - Namespace: r.dk.Namespace, - }) - if err != nil { - return nil, err - } - - tlsSecretHash, err := hasher.GenerateHash(tlsSecret.Data) - if err != nil { - return nil, err - } - - templateAnnotations[consts.ExtensionsAnnotationSecretHash] = tlsSecretHash - - return templateAnnotations, nil -} - -func getReplicas(dk *dynakube.DynaKube) int32 { - if dk.Spec.Templates.OpenTelemetryCollector.Replicas != nil { - return *dk.Spec.Templates.OpenTelemetryCollector.Replicas - } - - return defaultReplicas -} - -func buildContainer(dk *dynakube.DynaKube) corev1.Container { - imageRepo := dk.Spec.Templates.OpenTelemetryCollector.ImageRef.Repository - imageTag := dk.Spec.Templates.OpenTelemetryCollector.ImageRef.Tag - - if imageRepo == "" { - imageRepo = defaultImageRepo - } - - if imageTag == "" { - imageTag = defaultImageTag - } - - return corev1.Container{ - Name: containerName, - Image: imageRepo + ":" + imageTag, - ImagePullPolicy: corev1.PullAlways, - SecurityContext: buildSecurityContext(), - Env: buildContainerEnvs(dk), - Resources: dk.Spec.Templates.OpenTelemetryCollector.Resources, - Args: []string{fmt.Sprintf("--config=eec://%s:%d/otcconfig/prometheusMetrics#refresh-interval=5s&auth-file=%s", servicename.BuildFQDN(dk), consts.ExtensionsCollectorComPort, otelcSecretTokenFilePath)}, - VolumeMounts: buildContainerVolumeMounts(dk), - } -} - -func buildSecurityContext() *corev1.SecurityContext { - return &corev1.SecurityContext{ - SeccompProfile: &corev1.SeccompProfile{ - Type: corev1.SeccompProfileTypeRuntimeDefault, - }, - } -} - -func buildPodSecurityContext() *corev1.PodSecurityContext { - return &corev1.PodSecurityContext{ - SeccompProfile: &corev1.SeccompProfile{ - Type: corev1.SeccompProfileTypeRuntimeDefault, - }, - } -} - -func buildContainerEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { - envs := []corev1.EnvVar{ - {Name: envShards, Value: strconv.Itoa(int(getReplicas(dk)))}, - {Name: envPodNamePrefix, Value: dk.ExtensionsCollectorStatefulsetName()}, - {Name: envPodName, ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.labels['statefulset.kubernetes.io/pod-name']", - }, - }, - }, - {Name: envShardId, ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.labels['apps.kubernetes.io/pod-index']", - }, - }, - }, - {Name: envOTLPgrpcPort, Value: defaultOLTPgrpcPort}, - {Name: envOTLPhttpPort, Value: defaultOLTPhttpPort}, - {Name: envOTLPtoken, ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, - Key: consts.OtelcTokenSecretKey, - }, - }, - }, - {Name: envEECDStoken, ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, - Key: consts.OtelcTokenSecretKey, - }, - }, - }, - {Name: envCertDir, Value: customEecTLSCertificatePath}, - {Name: envK8sClusterName, Value: dk.Name}, - {Name: envK8sClusterUuid, Value: dk.Status.KubeSystemUUID}, - {Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, - } - if dk.Spec.TrustedCAs != "" { - envs = append(envs, corev1.EnvVar{Name: envTrustedCAs, Value: trustedCAVolumePath}) - } - - envs = append(envs, corev1.EnvVar{Name: envEECcontrollerTLS, Value: customEecTLSCertificateFullPath}) - - return envs -} - -func buildAppLabels(dkName string) *labels.AppLabels { - // TODO: when version is available - version := "0.0.0" - - return labels.NewAppLabels(labels.CollectorComponentLabel, dkName, labels.CollectorComponentLabel, version) -} - -func buildAffinity() corev1.Affinity { - // TODO: implement new attributes in CR dk.Spec.Templates.OpenTelemetryCollector.Affinity - // otherwise to use defaults ones - return node.Affinity() -} - -func setImagePullSecrets(imagePullSecrets []corev1.LocalObjectReference) func(o *appsv1.StatefulSet) { - return func(o *appsv1.StatefulSet) { - o.Spec.Template.Spec.ImagePullSecrets = imagePullSecrets - } -} - -func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { - return func(o *appsv1.StatefulSet) { - o.Spec.Template.Spec.Volumes = []corev1.Volume{ - { - Name: consts.ExtensionsTokensVolumeName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: dk.ExtensionsTokenSecretName(), - Items: []corev1.KeyToPath{ - { - Key: consts.OtelcTokenSecretKey, - Path: consts.OtelcTokenSecretKey, - }, - }, - DefaultMode: ptr.To(int32(420)), - }, - }, - }, - } - if dk.Spec.TrustedCAs != "" { - o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ - Name: caCertsVolumeName, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: dk.Spec.TrustedCAs, - }, - Items: []corev1.KeyToPath{ - { - Key: "certs", - Path: trustedCAsFile, - }, - }, - }, - }, - }) - } - - o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ - Name: dk.ExtensionsTLSSecretName(), - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: dk.ExtensionsTLSSecretName(), - Items: []corev1.KeyToPath{ - { - Key: consts.TLSCrtDataName, - Path: consts.TLSCrtDataName, - }, - }, - }, - }, - }) - } -} - -func buildContainerVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { - vm := []corev1.VolumeMount{ - {Name: consts.ExtensionsTokensVolumeName, ReadOnly: true, MountPath: secretsTokensPath}, - } - - if dk.Spec.TrustedCAs != "" { - vm = append(vm, corev1.VolumeMount{ - Name: caCertsVolumeName, - MountPath: trustedCAVolumeMountPath, - ReadOnly: true, - }) - } - - vm = append(vm, corev1.VolumeMount{ - Name: dk.ExtensionsTLSSecretName(), - MountPath: customEecTLSCertificatePath, - ReadOnly: true, - }) - - return vm -} diff --git a/pkg/controllers/dynakube/extension/reconciler.go b/pkg/controllers/dynakube/extension/reconciler.go index a6ac436216..c873b7dd73 100644 --- a/pkg/controllers/dynakube/extension/reconciler.go +++ b/pkg/controllers/dynakube/extension/reconciler.go @@ -6,7 +6,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/eec" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/otel" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/tls" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "sigs.k8s.io/controller-runtime/pkg/client" @@ -56,10 +55,5 @@ func (r *reconciler) Reconcile(ctx context.Context) error { return err } - err = otel.NewReconciler(r.client, r.apiReader, r.dk).Reconcile(ctx) - if err != nil { - return err - } - return nil } diff --git a/pkg/controllers/dynakube/extension/reconciler_test.go b/pkg/controllers/dynakube/extension/reconciler_test.go index 65f0710ea7..f312e4bd3a 100644 --- a/pkg/controllers/dynakube/extension/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/reconciler_test.go @@ -8,8 +8,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/servicename" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + eecConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/dttoken" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" @@ -50,12 +50,12 @@ func TestReconciler_Reconcile(t *testing.T) { dk := createDynakube() // mock SecretCreated condition - conditions.SetSecretCreated(dk.Conditions(), consts.ExtensionsSecretConditionType, dk.ExtensionsTokenSecretName()) + conditions.SetSecretCreated(dk.Conditions(), secretConditionType, dk.ExtensionsTokenSecretName()) // mock secret - secretToken, _ := dttoken.New(consts.EecTokenSecretValuePrefix) + secretToken, _ := dttoken.New(eecConsts.TokenSecretValuePrefix) secretData := map[string][]byte{ - consts.EecTokenSecretKey: []byte(secretToken.String()), + eecConsts.TokenSecretKey: []byte(secretToken.String()), } secretMock, _ := k8ssecret.Build(dk, testName+"-extensions-token", secretData) @@ -95,13 +95,13 @@ func TestReconciler_Reconcile(t *testing.T) { var secretFound corev1.Secret err = fakeClient.Get(context.Background(), client.ObjectKey{Name: testName + "-extensions-token", Namespace: testNamespace}, &secretFound) require.NoError(t, err) - require.NotEmpty(t, secretFound.Data[consts.EecTokenSecretKey]) + require.NotEmpty(t, secretFound.Data[eecConsts.TokenSecretKey]) require.NotEmpty(t, secretFound.Data[consts.OtelcTokenSecretKey]) // assert extensions token condition is added require.NotEmpty(t, dk.Conditions()) - condition := meta.FindStatusCondition(*dk.Conditions(), consts.ExtensionsSecretConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), secretConditionType) assert.Equal(t, metav1.ConditionTrue, condition.Status) assert.Equal(t, conditions.SecretCreatedReason, condition.Reason) assert.Equal(t, dk.ExtensionsTokenSecretName()+" created", condition.Message) @@ -118,7 +118,7 @@ func TestReconciler_Reconcile(t *testing.T) { // assert extensions token condition is added require.NotEmpty(t, dk.Conditions()) - condition := meta.FindStatusCondition(*dk.Conditions(), consts.ExtensionsSecretConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), secretConditionType) assert.Equal(t, metav1.ConditionFalse, condition.Status) assert.Equal(t, conditions.KubeApiErrorReason, condition.Reason) assert.Contains(t, condition.Message, "A problem occurred when using the Kubernetes API") @@ -136,17 +136,17 @@ func TestReconciler_Reconcile(t *testing.T) { require.NoError(t, err) var svc corev1.Service - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: servicename.Build(r.dk), Namespace: testNamespace}, &svc) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsServiceName(), Namespace: testNamespace}, &svc) require.NoError(t, err) assert.NotNil(t, svc) // assert extensions token condition is added require.NotEmpty(t, dk.Conditions()) - condition := meta.FindStatusCondition(*dk.Conditions(), consts.ExtensionsServiceConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), serviceConditionType) assert.Equal(t, metav1.ConditionTrue, condition.Status) assert.Equal(t, conditions.ServiceCreatedReason, condition.Reason) - assert.Equal(t, dk.Name+consts.ExtensionsControllerSuffix+" created", condition.Message) + assert.Equal(t, dk.Name+eecConsts.ExtensionsControllerSuffix+" created", condition.Message) }) t.Run("Don't create service when extensions are disabled with minimal setup", func(t *testing.T) { @@ -161,7 +161,7 @@ func TestReconciler_Reconcile(t *testing.T) { require.NoError(t, err) var svc corev1.Service - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: servicename.Build(r.dk), Namespace: testNamespace}, &svc) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsServiceName(), Namespace: testNamespace}, &svc) require.Error(t, err) assert.True(t, k8serrors.IsNotFound(err)) }) diff --git a/pkg/controllers/dynakube/extension/secret.go b/pkg/controllers/dynakube/extension/secret.go index f6bfa6fd6c..ef1523aac0 100644 --- a/pkg/controllers/dynakube/extension/secret.go +++ b/pkg/controllers/dynakube/extension/secret.go @@ -3,7 +3,8 @@ package extension import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + eecConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/dttoken" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" @@ -16,10 +17,10 @@ import ( func (r *reconciler) reconcileSecret(ctx context.Context) error { if !r.dk.IsExtensionsEnabled() { - if meta.FindStatusCondition(*r.dk.Conditions(), consts.ExtensionsSecretConditionType) == nil { + if meta.FindStatusCondition(*r.dk.Conditions(), secretConditionType) == nil { return nil } - defer meta.RemoveStatusCondition(r.dk.Conditions(), consts.ExtensionsSecretConditionType) + defer meta.RemoveStatusCondition(r.dk.Conditions(), secretConditionType) secret, err := r.buildSecret(dttoken.Token{}, dttoken.Token{}) if err != nil { @@ -41,16 +42,16 @@ func (r *reconciler) reconcileSecret(ctx context.Context) error { _, err := k8ssecret.Query(r.client, r.apiReader, log).Get(ctx, client.ObjectKey{Name: r.getSecretName(), Namespace: r.dk.Namespace}) if err != nil && !k8serrors.IsNotFound(err) { log.Info("failed to check existence of extension secret") - conditions.SetKubeApiError(r.dk.Conditions(), consts.ExtensionsSecretConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), secretConditionType, err) return err } if k8serrors.IsNotFound(err) { - newEecToken, err := dttoken.New(consts.EecTokenSecretValuePrefix) + newEecToken, err := dttoken.New(eecConsts.TokenSecretValuePrefix) if err != nil { log.Info("failed to generate eec token") - conditions.SetSecretGenFailed(r.dk.Conditions(), consts.ExtensionsSecretConditionType, errors.Wrap(err, "error generating eec token")) + conditions.SetSecretGenFailed(r.dk.Conditions(), secretConditionType, errors.Wrap(err, "error generating eec token")) return err } @@ -58,7 +59,7 @@ func (r *reconciler) reconcileSecret(ctx context.Context) error { newOtelcToken, err := dttoken.New(consts.OtelcTokenSecretValuePrefix) if err != nil { log.Info("failed to generate otelc token") - conditions.SetSecretGenFailed(r.dk.Conditions(), consts.ExtensionsSecretConditionType, errors.Wrap(err, "error generating otelc token")) + conditions.SetSecretGenFailed(r.dk.Conditions(), secretConditionType, errors.Wrap(err, "error generating otelc token")) return err } @@ -66,7 +67,7 @@ func (r *reconciler) reconcileSecret(ctx context.Context) error { newSecret, err := r.buildSecret(*newEecToken, *newOtelcToken) if err != nil { log.Info("failed to generate extension secret") - conditions.SetSecretGenFailed(r.dk.Conditions(), consts.ExtensionsSecretConditionType, err) + conditions.SetSecretGenFailed(r.dk.Conditions(), secretConditionType, err) return err } @@ -74,20 +75,20 @@ func (r *reconciler) reconcileSecret(ctx context.Context) error { _, err = k8ssecret.Query(r.client, r.apiReader, log).CreateOrUpdate(ctx, newSecret) if err != nil { log.Info("failed to create/update extension secret") - conditions.SetKubeApiError(r.dk.Conditions(), consts.ExtensionsSecretConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), secretConditionType, err) return err } } - conditions.SetSecretCreated(r.dk.Conditions(), consts.ExtensionsSecretConditionType, r.getSecretName()) + conditions.SetSecretCreated(r.dk.Conditions(), secretConditionType, r.getSecretName()) return nil } func (r *reconciler) buildSecret(eecToken dttoken.Token, otelcToken dttoken.Token) (*corev1.Secret, error) { secretData := map[string][]byte{ - consts.EecTokenSecretKey: []byte(eecToken.String()), + eecConsts.TokenSecretKey: []byte(eecToken.String()), consts.OtelcTokenSecretKey: []byte(otelcToken.String()), } diff --git a/pkg/controllers/dynakube/extension/service.go b/pkg/controllers/dynakube/extension/service.go index b7bee955a5..147229842a 100644 --- a/pkg/controllers/dynakube/extension/service.go +++ b/pkg/controllers/dynakube/extension/service.go @@ -3,8 +3,7 @@ package extension import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/servicename" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/service" @@ -15,10 +14,10 @@ import ( func (r *reconciler) reconcileService(ctx context.Context) error { if !r.dk.IsExtensionsEnabled() { - if meta.FindStatusCondition(*r.dk.Conditions(), consts.ExtensionsServiceConditionType) == nil { + if meta.FindStatusCondition(*r.dk.Conditions(), serviceConditionType) == nil { return nil } - defer meta.RemoveStatusCondition(r.dk.Conditions(), consts.ExtensionsServiceConditionType) + defer meta.RemoveStatusCondition(r.dk.Conditions(), serviceConditionType) svc, err := r.buildService() if err != nil { @@ -44,7 +43,7 @@ func (r *reconciler) reconcileService(ctx context.Context) error { func (r *reconciler) createOrUpdateService(ctx context.Context) error { newService, err := r.buildService() if err != nil { - conditions.SetServiceGenFailed(r.dk.Conditions(), consts.ExtensionsServiceConditionType, err) + conditions.SetServiceGenFailed(r.dk.Conditions(), serviceConditionType, err) return err } @@ -52,12 +51,12 @@ func (r *reconciler) createOrUpdateService(ctx context.Context) error { _, err = service.Query(r.client, r.apiReader, log).CreateOrUpdate(ctx, newService) if err != nil { log.Info("failed to create/update extension service") - conditions.SetKubeApiError(r.dk.Conditions(), consts.ExtensionsServiceConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), serviceConditionType, err) return err } - conditions.SetServiceCreated(r.dk.Conditions(), consts.ExtensionsServiceConditionType, servicename.Build(r.dk)) + conditions.SetServiceCreated(r.dk.Conditions(), serviceConditionType, r.dk.ExtensionsServiceName()) return nil } @@ -68,14 +67,14 @@ func (r *reconciler) buildService() (*corev1.Service, error) { appLabels := labels.NewAppLabels(labels.ExtensionComponentLabel, r.dk.Name, labels.ExtensionComponentLabel, "") svcPort := corev1.ServicePort{ - Name: servicename.BuildPortName(), - Port: consts.ExtensionsCollectorComPort, + Name: r.dk.ExtensionsPortName(), + Port: consts.OtelCollectorComPort, Protocol: corev1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.String, StrVal: consts.ExtensionsCollectorTargetPortName}, } return service.Build(r.dk, - servicename.Build(r.dk), + r.dk.ExtensionsServiceName(), appLabels.BuildMatchLabels(), svcPort, service.SetLabels(coreLabels.BuildLabels()), diff --git a/pkg/controllers/dynakube/extension/service_test.go b/pkg/controllers/dynakube/extension/service_test.go index 68086ad346..075e461f62 100644 --- a/pkg/controllers/dynakube/extension/service_test.go +++ b/pkg/controllers/dynakube/extension/service_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/servicename" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "github.com/Dynatrace/dynatrace-operator/pkg/version" @@ -38,6 +37,6 @@ func TestReconciler_prepareService(t *testing.T) { func TestFQDNNameGeneration(t *testing.T) { t.Run(`Check FQDN name generation`, func(t *testing.T) { dk := createDynakube() - assert.Equal(t, "test-name-extensions-controller.test-namespace", servicename.BuildFQDN(dk)) + assert.Equal(t, "test-name-extensions-controller.test-namespace", dk.ExtensionsServiceNameFQDN()) }) } diff --git a/pkg/controllers/dynakube/extension/servicename/naming.go b/pkg/controllers/dynakube/extension/servicename/naming.go deleted file mode 100644 index eb56f15f8f..0000000000 --- a/pkg/controllers/dynakube/extension/servicename/naming.go +++ /dev/null @@ -1,18 +0,0 @@ -package servicename - -import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" -) - -func BuildPortName() string { - return "dynatrace" + consts.ExtensionsControllerSuffix + "-" + consts.ExtensionsCollectorTargetPortName -} - -func BuildFQDN(dk *dynakube.DynaKube) string { - return Build(dk) + "." + dk.Namespace -} - -func Build(dk *dynakube.DynaKube) string { - return dk.Name + consts.ExtensionsControllerSuffix -} diff --git a/pkg/controllers/dynakube/extension/tls/reconciler.go b/pkg/controllers/dynakube/extension/tls/reconciler.go index cbec6f81d4..01196c5bb6 100644 --- a/pkg/controllers/dynakube/extension/tls/reconciler.go +++ b/pkg/controllers/dynakube/extension/tls/reconciler.go @@ -5,8 +5,8 @@ import ( "crypto/x509" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/certificates" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" @@ -20,6 +20,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) +const ( + extensionsSelfSignedTLSCommonNameSuffix = "-extensions-controller.dynatrace" +) + type reconciler struct { client client.Client apiReader client.Reader @@ -54,7 +58,7 @@ func (r *reconciler) reconcileSelfSignedTLSSecret(ctx context.Context) error { query := k8ssecret.Query(r.client, r.client, log) _, err := query.Get(ctx, types.NamespacedName{ - Name: getSelfSignedTLSSecretName(r.dk.Name), + Name: r.dk.ExtensionsSelfSignedTLSSecretName(), Namespace: r.dk.Namespace, }) @@ -76,7 +80,7 @@ func (r *reconciler) deleteSelfSignedTLSSecret(ctx context.Context) error { return query.Delete(ctx, &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: getSelfSignedTLSSecretName(r.dk.Name), + Name: r.dk.ExtensionsSelfSignedTLSSecretName(), Namespace: r.dk.Namespace, }, }) @@ -93,7 +97,7 @@ func (r *reconciler) createSelfSignedTLSSecret(ctx context.Context) error { cert.Cert.DNSNames = getCertificateAltNames(r.dk.Name) cert.Cert.KeyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment cert.Cert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} - cert.Cert.Subject.CommonName = r.dk.Name + consts.ExtensionsSelfSignedTLSCommonNameSuffix + cert.Cert.Subject.CommonName = r.dk.Name + extensionsSelfSignedTLSCommonNameSuffix err = cert.SelfSign() if err != nil { @@ -112,7 +116,7 @@ func (r *reconciler) createSelfSignedTLSSecret(ctx context.Context) error { coreLabels := k8slabels.NewCoreLabels(r.dk.Name, k8slabels.ExtensionComponentLabel) secretData := map[string][]byte{consts.TLSCrtDataName: pemCert, consts.TLSKeyDataName: pemPk} - secret, err := k8ssecret.Build(r.dk, getSelfSignedTLSSecretName(r.dk.Name), secretData, k8ssecret.SetLabels(coreLabels.BuildLabels())) + secret, err := k8ssecret.Build(r.dk, r.dk.ExtensionsSelfSignedTLSSecretName(), secretData, k8ssecret.SetLabels(coreLabels.BuildLabels())) if err != nil { conditions.SetSecretGenFailed(r.dk.Conditions(), conditionType, err) @@ -135,18 +139,6 @@ func (r *reconciler) createSelfSignedTLSSecret(ctx context.Context) error { return nil } -func GetTLSSecretName(dk *dynakube.DynaKube) string { - if dk.ExtensionsNeedsSelfSignedTLS() { - return getSelfSignedTLSSecretName(dk.Name) - } - - return dk.ExtensionsTLSRefName() -} - -func getSelfSignedTLSSecretName(dkName string) string { - return dkName + consts.ExtensionsSelfSignedTLSSecretSuffix -} - func getCertificateAltNames(dkName string) []string { return []string{ dkName + "-extensions-controller.dynatrace", diff --git a/pkg/controllers/dynakube/extension/tls/reconciler_test.go b/pkg/controllers/dynakube/extension/tls/reconciler_test.go index a4fa1a0985..173ad74aba 100644 --- a/pkg/controllers/dynakube/extension/tls/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/tls/reconciler_test.go @@ -10,7 +10,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -31,8 +31,6 @@ const ( testCustomConfigConfigMapName = "eec-custom-config" ) -var SelfSignedTLSSecretObjectKey = client.ObjectKey{Name: getSelfSignedTLSSecretName(testDynakubeName), Namespace: testNamespaceName} - func TestReconcile(t *testing.T) { t.Run("self-signed tls secret is not generated", func(t *testing.T) { dk := getTestDynakube() @@ -45,7 +43,9 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) var secret corev1.Secret - err = fakeClient.Get(context.Background(), SelfSignedTLSSecretObjectKey, &secret) + + key := client.ObjectKey{Name: dk.ExtensionsSelfSignedTLSSecretName(), Namespace: testNamespaceName} + err = fakeClient.Get(context.Background(), key, &secret) require.True(t, k8serrors.IsNotFound(err)) assert.Equal(t, corev1.Secret{}, secret) @@ -62,7 +62,9 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) var secret corev1.Secret - err = fakeClient.Get(context.Background(), SelfSignedTLSSecretObjectKey, &secret) + + key := client.ObjectKey{Name: dk.ExtensionsSelfSignedTLSSecretName(), Namespace: testNamespaceName} + err = fakeClient.Get(context.Background(), key, &secret) require.NoError(t, err) assert.NotEmpty(t, secret) @@ -86,7 +88,9 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) var secret corev1.Secret - err = fakeClient.Get(context.Background(), SelfSignedTLSSecretObjectKey, &secret) + + key := client.ObjectKey{Name: dk.ExtensionsSelfSignedTLSSecretName(), Namespace: testNamespaceName} + err = fakeClient.Get(context.Background(), key, &secret) require.NoError(t, err) require.NotEmpty(t, secret) @@ -106,7 +110,9 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) var secret corev1.Secret - err = fakeClient.Get(context.Background(), SelfSignedTLSSecretObjectKey, &secret) + + key := client.ObjectKey{Name: dk.ExtensionsSelfSignedTLSSecretName(), Namespace: testNamespaceName} + err = fakeClient.Get(context.Background(), key, &secret) require.True(t, k8serrors.IsNotFound(err)) assert.Empty(t, secret) @@ -126,7 +132,9 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) var secret corev1.Secret - err = fakeClient.Get(context.Background(), SelfSignedTLSSecretObjectKey, &secret) + + key := client.ObjectKey{Name: dk.ExtensionsSelfSignedTLSSecretName(), Namespace: testNamespaceName} + err = fakeClient.Get(context.Background(), key, &secret) require.True(t, k8serrors.IsNotFound(err)) assert.Equal(t, corev1.Secret{}, secret) @@ -139,16 +147,14 @@ func TestGetTLSSecretName(t *testing.T) { dk := getTestDynakube() dk.Spec.Templates.ExtensionExecutionController.TlsRefName = "" - secretName := GetTLSSecretName(dk) - - assert.Equal(t, getSelfSignedTLSSecretName(dk.Name), secretName) + secretName := dk.ExtensionsTLSSecretName() + assert.Equal(t, dk.ExtensionsSelfSignedTLSSecretName(), secretName) }) t.Run("tlsRefName secret", func(t *testing.T) { dk := getTestDynakube() dk.Spec.Templates.ExtensionExecutionController.TlsRefName = "dummy-value" - secretName := GetTLSSecretName(dk) - + secretName := dk.ExtensionsTLSSecretName() assert.Equal(t, "dummy-value", secretName) }) } @@ -196,7 +202,7 @@ func mockSelfSignedTLSSecret(t *testing.T, client client.Client, dk *dynakube.Dy func getSelfSignedTLSSecret(dk *dynakube.DynaKube) corev1.Secret { return corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: getSelfSignedTLSSecretName(dk.Name), + Name: dk.ExtensionsTLSSecretName(), Namespace: dk.Namespace, }, Data: map[string][]byte{ diff --git a/pkg/controllers/dynakube/extension/utils/utils.go b/pkg/controllers/dynakube/extension/utils/utils.go deleted file mode 100644 index 4e96d58f85..0000000000 --- a/pkg/controllers/dynakube/extension/utils/utils.go +++ /dev/null @@ -1,40 +0,0 @@ -package utils - -import ( - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func BuildTopologySpreadConstraints(topologySpreadConstraints []corev1.TopologySpreadConstraint, appLabels *labels.AppLabels) []corev1.TopologySpreadConstraint { - if len(topologySpreadConstraints) > 0 { - return topologySpreadConstraints - } else { - return []corev1.TopologySpreadConstraint{ - { - MaxSkew: 1, - TopologyKey: "topology.kubernetes.io/zone", - WhenUnsatisfiable: "ScheduleAnyway", - LabelSelector: &metav1.LabelSelector{MatchLabels: appLabels.BuildMatchLabels()}, - }, - { - MaxSkew: 1, - TopologyKey: "kubernetes.io/hostname", - WhenUnsatisfiable: "DoNotSchedule", - LabelSelector: &metav1.LabelSelector{MatchLabels: appLabels.BuildMatchLabels()}, - }, - } - } -} - -func BuildUpdateStrategy() appsv1.StatefulSetUpdateStrategy { - partition := int32(0) - - return appsv1.StatefulSetUpdateStrategy{ - RollingUpdate: &appsv1.RollingUpdateStatefulSetStrategy{ - Partition: &partition, - }, - Type: appsv1.RollingUpdateStatefulSetStrategyType, - } -} diff --git a/pkg/controllers/dynakube/extension/otel/config.go b/pkg/controllers/dynakube/otelc/config.go similarity index 55% rename from pkg/controllers/dynakube/extension/otel/config.go rename to pkg/controllers/dynakube/otelc/config.go index 43f9727302..0287cccc36 100644 --- a/pkg/controllers/dynakube/extension/otel/config.go +++ b/pkg/controllers/dynakube/otelc/config.go @@ -1,9 +1,9 @@ -package otel +package otelc import ( "github.com/Dynatrace/dynatrace-operator/pkg/logd" ) var ( - log = logd.Get().WithName("extension-otel") + log = logd.Get().WithName("otel-collector") ) diff --git a/pkg/controllers/dynakube/otelc/reconciler.go b/pkg/controllers/dynakube/otelc/reconciler.go new file mode 100644 index 0000000000..85d770bb10 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/reconciler.go @@ -0,0 +1,39 @@ +package otelc + +import ( + "context" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/statefulset" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Reconciler struct { + client client.Client + apiReader client.Reader + dk *dynakube.DynaKube + statefulsetReconciler controllers.Reconciler +} + +type ReconcilerBuilder func(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) controllers.Reconciler + +func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) controllers.Reconciler { //nolint + return &Reconciler{ + client: client, + apiReader: apiReader, + dk: dk, + statefulsetReconciler: statefulset.NewReconciler(client, apiReader, dk), + } +} + +func (r *Reconciler) Reconcile(ctx context.Context) error { + err := r.statefulsetReconciler.Reconcile(ctx) + if err != nil { + log.Info("failed to reconcile Dynatrace OTELc statefulset") + + return err + } + + return nil +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/conditions.go b/pkg/controllers/dynakube/otelc/statefulset/conditions.go new file mode 100644 index 0000000000..c5e6baa29d --- /dev/null +++ b/pkg/controllers/dynakube/otelc/statefulset/conditions.go @@ -0,0 +1,3 @@ +package statefulset + +const conditionType string = "OtelStatefulSet" diff --git a/pkg/controllers/dynakube/otelc/statefulset/config.go b/pkg/controllers/dynakube/otelc/statefulset/config.go new file mode 100644 index 0000000000..ae77de6536 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/statefulset/config.go @@ -0,0 +1,9 @@ +package statefulset + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/logd" +) + +var ( + log = logd.Get().WithName("otelc-statefulset") +) diff --git a/pkg/controllers/dynakube/otelc/statefulset/container.go b/pkg/controllers/dynakube/otelc/statefulset/container.go new file mode 100644 index 0000000000..64c1764f43 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/statefulset/container.go @@ -0,0 +1,42 @@ +package statefulset + +import ( + "fmt" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + corev1 "k8s.io/api/core/v1" +) + +const ( + // default values + defaultImageRepo = "public.ecr.aws/dynatrace/dynatrace-otel-collector" + defaultImageTag = "latest" + containerName = "collector" + secretsTokensPath = "/secrets/tokens" + otelcSecretTokenFilePath = secretsTokensPath + "/" + consts.OtelcTokenSecretKey +) + +func getContainer(dk *dynakube.DynaKube) corev1.Container { + imageRepo := dk.Spec.Templates.OpenTelemetryCollector.ImageRef.Repository + imageTag := dk.Spec.Templates.OpenTelemetryCollector.ImageRef.Tag + + if imageRepo == "" { + imageRepo = defaultImageRepo + } + + if imageTag == "" { + imageTag = defaultImageTag + } + + return corev1.Container{ + Name: containerName, + Image: imageRepo + ":" + imageTag, + ImagePullPolicy: corev1.PullAlways, + SecurityContext: buildSecurityContext(), + Env: getEnvs(dk), + Resources: dk.Spec.Templates.OpenTelemetryCollector.Resources, + Args: []string{fmt.Sprintf("--config=eec://%s:%d/otcconfig/prometheusMetrics#refresh-interval=5s&auth-file=%s", dk.ExtensionsServiceNameFQDN(), consts.OtelCollectorComPort, otelcSecretTokenFilePath)}, + VolumeMounts: buildContainerVolumeMounts(dk), + } +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/env.go b/pkg/controllers/dynakube/otelc/statefulset/env.go new file mode 100644 index 0000000000..5277b59c8f --- /dev/null +++ b/pkg/controllers/dynakube/otelc/statefulset/env.go @@ -0,0 +1,88 @@ +package statefulset + +import ( + "strconv" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + corev1 "k8s.io/api/core/v1" +) + +const ( + // default values + defaultOLTPgrpcPort = "10001" + defaultOLTPhttpPort = "10002" + defaultReplicas = 1 + + // env variables + envShards = "SHARDS" + envShardId = "SHARD_ID" + envPodNamePrefix = "POD_NAME_PREFIX" + envPodName = "POD_NAME" + envOTLPgrpcPort = "OTLP_GRPC_PORT" + envOTLPhttpPort = "OTLP_HTTP_PORT" + envOTLPtoken = "OTLP_TOKEN" + envEECDStoken = "EEC_DS_TOKEN" + envTrustedCAs = "TRUSTED_CAS" + envK8sClusterName = "K8S_CLUSTER_NAME" + envK8sClusterUid = "K8S_CLUSTER_UID" + envDTentityK8sCluster = "DT_ENTITY_KUBERNETES_CLUSTER" + // certDirEnv is the environment variable that identifies which directory + // to check for SSL certificate files. If set, this overrides the system default. + // It is a colon separated list of directories. + // See https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html. + envCertDir = "SSL_CERT_DIR" + envEECcontrollerTLS = "EXTENSIONS_CONTROLLER_TLS" + + // Volume names and paths + trustedCAVolumeMountPath = "/tls/custom/cacerts" + trustedCAVolumePath = trustedCAVolumeMountPath + "/certs" + customEecTLSCertificatePath = "/tls/custom/eec" + customEecTLSCertificateFullPath = customEecTLSCertificatePath + "/" + consts.TLSCrtDataName +) + +func getEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { + envs := []corev1.EnvVar{ + {Name: envShards, Value: strconv.Itoa(int(getReplicas(dk)))}, + {Name: envPodNamePrefix, Value: dk.ExtensionsCollectorStatefulsetName()}, + {Name: envPodName, ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.labels['statefulset.kubernetes.io/pod-name']", + }, + }, + }, + {Name: envShardId, ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.labels['apps.kubernetes.io/pod-index']", + }, + }, + }, + {Name: envOTLPgrpcPort, Value: defaultOLTPgrpcPort}, + {Name: envOTLPhttpPort, Value: defaultOLTPhttpPort}, + {Name: envOTLPtoken, ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, + Key: consts.OtelcTokenSecretKey, + }, + }, + }, + {Name: envEECDStoken, ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, + Key: consts.OtelcTokenSecretKey, + }, + }, + }, + {Name: envCertDir, Value: customEecTLSCertificatePath}, + {Name: envK8sClusterName, Value: dk.Name}, + {Name: envK8sClusterUid, Value: dk.Status.KubeSystemUUID}, + {Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, + } + if dk.Spec.TrustedCAs != "" { + envs = append(envs, corev1.EnvVar{Name: envTrustedCAs, Value: trustedCAVolumePath}) + } + + envs = append(envs, corev1.EnvVar{Name: envEECcontrollerTLS, Value: customEecTLSCertificateFullPath}) + + return envs +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go new file mode 100644 index 0000000000..720dee14aa --- /dev/null +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go @@ -0,0 +1,189 @@ +package statefulset + +import ( + "context" + + "github.com/Dynatrace/dynatrace-operator/pkg/api" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" + k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/statefulset" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/topology" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + serviceAccountName = "dynatrace-extensions-collector" +) + +type Reconciler struct { + client client.Client + apiReader client.Reader + dk *dynakube.DynaKube +} + +func NewReconciler(clt client.Client, + apiReader client.Reader, + dk *dynakube.DynaKube) *Reconciler { + return &Reconciler{ + client: clt, + apiReader: apiReader, + dk: dk, + } +} + +func (r *Reconciler) Reconcile(ctx context.Context) error { + if !r.dk.IsExtensionsEnabled() { + if meta.FindStatusCondition(*r.dk.Conditions(), conditionType) == nil { + return nil + } + defer meta.RemoveStatusCondition(r.dk.Conditions(), conditionType) + + sts, err := statefulset.Build(r.dk, r.dk.ExtensionsCollectorStatefulsetName(), corev1.Container{}) + if err != nil { + log.Error(err, "could not build "+r.dk.ExtensionsCollectorStatefulsetName()+" during cleanup") + + return err + } + + err = statefulset.Query(r.client, r.apiReader, log).Delete(ctx, sts) + + if err != nil { + log.Error(err, "failed to clean up "+r.dk.ExtensionsCollectorStatefulsetName()+" statufulset") + + return nil + } + + return nil + } + + return r.createOrUpdateStatefulset(ctx) +} + +func (r *Reconciler) createOrUpdateStatefulset(ctx context.Context) error { + appLabels := buildAppLabels(r.dk.Name) + + templateAnnotations, err := r.buildTemplateAnnotations(ctx) + if err != nil { + return err + } + + topologySpreadConstraints := topology.MaxOnePerNode(appLabels) + if len(r.dk.Spec.Templates.OpenTelemetryCollector.TopologySpreadConstraints) > 0 { + topologySpreadConstraints = r.dk.Spec.Templates.OpenTelemetryCollector.TopologySpreadConstraints + } + + sts, err := statefulset.Build(r.dk, r.dk.ExtensionsCollectorStatefulsetName(), getContainer(r.dk), + statefulset.SetReplicas(getReplicas(r.dk)), + statefulset.SetPodManagementPolicy(appsv1.ParallelPodManagement), + statefulset.SetAllLabels(appLabels.BuildLabels(), appLabels.BuildMatchLabels(), appLabels.BuildLabels(), r.dk.Spec.Templates.OpenTelemetryCollector.Labels), + statefulset.SetAllAnnotations(nil, templateAnnotations), + statefulset.SetAffinity(buildAffinity()), + statefulset.SetServiceAccount(serviceAccountName), + statefulset.SetTolerations(r.dk.Spec.Templates.OpenTelemetryCollector.Tolerations), + statefulset.SetTopologySpreadConstraints(topologySpreadConstraints), + statefulset.SetSecurityContext(buildPodSecurityContext()), + statefulset.SetRollingUpdateStrategyType(), + setImagePullSecrets(r.dk.ImagePullSecretReferences()), + setVolumes(r.dk), + ) + + if err != nil { + conditions.SetKubeApiError(r.dk.Conditions(), conditionType, err) + + return err + } + + if err := hasher.AddAnnotation(sts); err != nil { + conditions.SetKubeApiError(r.dk.Conditions(), conditionType, err) + + return err + } + + _, err = statefulset.Query(r.client, r.apiReader, log).WithOwner(r.dk).CreateOrUpdate(ctx, sts) + if err != nil { + log.Info("failed to create/update " + r.dk.ExtensionsCollectorStatefulsetName() + " statefulset") + conditions.SetKubeApiError(r.dk.Conditions(), conditionType, err) + + return err + } + + conditions.SetStatefulSetCreated(r.dk.Conditions(), conditionType, sts.Name) + + return nil +} + +func (r *Reconciler) buildTemplateAnnotations(ctx context.Context) (map[string]string, error) { + templateAnnotations := map[string]string{} + + if r.dk.Spec.Templates.OpenTelemetryCollector.Annotations != nil { + templateAnnotations = r.dk.Spec.Templates.OpenTelemetryCollector.Annotations + } + + query := k8ssecret.Query(r.client, r.client, log) + + tlsSecret, err := query.Get(ctx, types.NamespacedName{ + Name: r.dk.ExtensionsTLSSecretName(), + Namespace: r.dk.Namespace, + }) + if err != nil { + return nil, err + } + + tlsSecretHash, err := hasher.GenerateHash(tlsSecret.Data) + if err != nil { + return nil, err + } + + templateAnnotations[api.AnnotationSecretHash] = tlsSecretHash + + return templateAnnotations, nil +} + +func getReplicas(dk *dynakube.DynaKube) int32 { + if dk.Spec.Templates.OpenTelemetryCollector.Replicas != nil { + return *dk.Spec.Templates.OpenTelemetryCollector.Replicas + } + + return defaultReplicas +} + +func buildSecurityContext() *corev1.SecurityContext { + return &corev1.SecurityContext{ + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + } +} + +func buildPodSecurityContext() *corev1.PodSecurityContext { + return &corev1.PodSecurityContext{ + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + } +} + +func buildAppLabels(dkName string) *labels.AppLabels { + // TODO: when version is available + version := "0.0.0" + + return labels.NewAppLabels(labels.CollectorComponentLabel, dkName, labels.CollectorComponentLabel, version) +} + +func buildAffinity() corev1.Affinity { + return node.Affinity() +} + +func setImagePullSecrets(imagePullSecrets []corev1.LocalObjectReference) func(o *appsv1.StatefulSet) { + return func(o *appsv1.StatefulSet) { + o.Spec.Template.Spec.ImagePullSecrets = imagePullSecrets + } +} diff --git a/pkg/controllers/dynakube/extension/otel/statefulset_test.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go similarity index 84% rename from pkg/controllers/dynakube/extension/otel/statefulset_test.go rename to pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go index a70cdc6836..de5be03f5d 100644 --- a/pkg/controllers/dynakube/extension/otel/statefulset_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go @@ -1,25 +1,27 @@ -package otel +package statefulset import ( "context" "fmt" "testing" + "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/tls" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/utils" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/topology" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -27,77 +29,65 @@ import ( const ( testDynakubeName = "dynakube" testNamespaceName = "dynatrace" - testOtelPullSecret = "otel-pull-secret" + testOtelPullSecret = "otelc-pull-secret" ) -func getTestDynakube() *dynakube.DynaKube { - return &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: testDynakubeName, - Namespace: testNamespaceName, - Annotations: map[string]string{}, - }, - Spec: dynakube.DynaKubeSpec{ - Extensions: &dynakube.ExtensionsSpec{}, - Templates: dynakube.TemplatesSpec{OpenTelemetryCollector: dynakube.OpenTelemetryCollectorSpec{}}, - }, - } -} +func TestReconcile(t *testing.T) { + ctx := context.Background() -func getStatefulset(t *testing.T, dk *dynakube.DynaKube) *appsv1.StatefulSet { - mockK8sClient := fake.NewClient(dk) - mockK8sClient = mockTLSSecret(t, mockK8sClient, dk) - - err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) - require.NoError(t, err) - - statefulSet := &appsv1.StatefulSet{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) - require.NoError(t, err) - - return statefulSet -} + t.Run("Create and update works with minimal setup", func(t *testing.T) { + dk := getTestDynakube() -func mockTLSSecret(t *testing.T, client client.Client, dk *dynakube.DynaKube) client.Client { - tlsSecret := getTLSSecret(tls.GetTLSSecretName(dk), dk.Namespace, "super-cert", "super-key") + mockK8sClient := fake.NewClient() + mockK8sClient = mockTLSSecret(t, mockK8sClient, dk) - err := client.Create(context.Background(), &tlsSecret) - require.NoError(t, err) + reconciler := NewReconciler(mockK8sClient, + mockK8sClient, dk) + err := reconciler.Reconcile(ctx) + require.NoError(t, err) - return client -} + condition := meta.FindStatusCondition(*dk.Conditions(), conditionType) + oldTransitionTime := condition.LastTransitionTime + require.NotNil(t, condition) + require.NotEmpty(t, oldTransitionTime) + assert.Equal(t, conditions.StatefulSetCreatedReason, condition.Reason) + assert.Equal(t, metav1.ConditionTrue, condition.Status) -func getTLSSecret(name string, namespace string, crt string, key string) corev1.Secret { - return corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Data: map[string][]byte{ - consts.TLSCrtDataName: []byte(crt), - consts.TLSKeyDataName: []byte(key), - }, - } -} + err = reconciler.Reconcile(context.Background()) + require.NoError(t, err) -func TestConditions(t *testing.T) { - t.Run("extensions are disabled", func(t *testing.T) { + var sts appsv1.StatefulSet + err = mockK8sClient.Get(ctx, types.NamespacedName{ + Name: dk.ExtensionsCollectorStatefulsetName(), + Namespace: dk.Namespace, + }, &sts) + require.False(t, k8serrors.IsNotFound(err)) + assert.NotEmpty(t, sts) + }) + t.Run("Only runs when required, and cleans up condition + statefulset", func(t *testing.T) { dk := getTestDynakube() dk.Spec.Extensions = nil - conditions.SetStatefulSetCreated(dk.Conditions(), otelControllerStatefulSetConditionType, dk.ExtensionsCollectorStatefulsetName()) - - mockK8sClient := fake.NewClient(dk) - err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) - require.NoError(t, err) + previousSts := appsv1.StatefulSet{} + previousSts.Name = dk.ExtensionsCollectorStatefulsetName() + previousSts.Namespace = dk.Namespace + mockK8sClient := fake.NewClient(&previousSts) + mockK8sClient = mockTLSSecret(t, mockK8sClient, dk) - statefulSet := &appsv1.StatefulSet{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) - require.Error(t, err) + conditions.SetStatefulSetCreated(dk.Conditions(), conditionType, "this is a test") - assert.True(t, errors.IsNotFound(err)) + reconciler := NewReconciler(mockK8sClient, mockK8sClient, dk) + err := reconciler.Reconcile(ctx) - assert.Empty(t, dk.Conditions()) + require.NoError(t, err) + assert.Empty(t, *dk.Conditions()) + + var sts appsv1.StatefulSet + err = mockK8sClient.Get(ctx, types.NamespacedName{ + Name: dk.ExtensionsCollectorStatefulsetName(), + Namespace: dk.Namespace, + }, &sts) + require.True(t, k8serrors.IsNotFound(err)) }) } @@ -108,7 +98,7 @@ func TestSecretHashAnnotation(t *testing.T) { statefulSet := getStatefulset(t, dk) require.Len(t, statefulSet.Spec.Template.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[consts.ExtensionsAnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash]) }) t.Run("annotation is set with tlsRefName", func(t *testing.T) { dk := getTestDynakube() @@ -116,7 +106,7 @@ func TestSecretHashAnnotation(t *testing.T) { statefulSet := getStatefulset(t, dk) require.Len(t, statefulSet.Spec.Template.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[consts.ExtensionsAnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash]) }) t.Run("annotation is updated when TLS Secret gets updated", func(t *testing.T) { statefulSet := &appsv1.StatefulSet{} @@ -133,10 +123,10 @@ func TestSecretHashAnnotation(t *testing.T) { err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) - originalSecretHash := statefulSet.Spec.Template.Annotations[consts.ExtensionsAnnotationSecretHash] + originalSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash] // then update the TLS Secret and call reconcile again - updatedTLSSecret := getTLSSecret(tls.GetTLSSecretName(dk), dk.Namespace, "updated-cert", "updated-key") + updatedTLSSecret := getTLSSecret(dk.ExtensionsTLSSecretName(), dk.Namespace, "updated-cert", "updated-key") err = mockK8sClient.Update(context.Background(), &updatedTLSSecret) require.NoError(t, err) @@ -145,7 +135,7 @@ func TestSecretHashAnnotation(t *testing.T) { err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) - resultingSecretHash := statefulSet.Spec.Template.Annotations[consts.ExtensionsAnnotationSecretHash] + resultingSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash] // original hash and resulting hash should be different, value got updated on reconcile assert.NotEqual(t, originalSecretHash, resultingSecretHash) @@ -180,7 +170,7 @@ func TestTopologySpreadConstraints(t *testing.T) { dk := getTestDynakube() statefulSet := getStatefulset(t, dk) appLabels := buildAppLabels(dk.Name) - assert.Equal(t, utils.BuildTopologySpreadConstraints(dk.Spec.Templates.OpenTelemetryCollector.TopologySpreadConstraints, appLabels), statefulSet.Spec.Template.Spec.TopologySpreadConstraints) + assert.Equal(t, topology.MaxOnePerNode(appLabels), statefulSet.Spec.Template.Spec.TopologySpreadConstraints) }) t.Run("custom TopologySpreadConstraints", func(t *testing.T) { @@ -241,7 +231,7 @@ func TestEnvironmentVariables(t *testing.T) { }}, statefulSet.Spec.Template.Spec.Containers[0].Env[7]) assert.Equal(t, corev1.EnvVar{Name: envCertDir, Value: customEecTLSCertificatePath}, statefulSet.Spec.Template.Spec.Containers[0].Env[8]) assert.Equal(t, corev1.EnvVar{Name: envK8sClusterName, Value: dk.Name}, statefulSet.Spec.Template.Spec.Containers[0].Env[9]) - assert.Equal(t, corev1.EnvVar{Name: envK8sClusterUuid, Value: dk.Status.KubeSystemUUID}, statefulSet.Spec.Template.Spec.Containers[0].Env[10]) + assert.Equal(t, corev1.EnvVar{Name: envK8sClusterUid, Value: dk.Status.KubeSystemUUID}, statefulSet.Spec.Template.Spec.Containers[0].Env[10]) assert.Equal(t, corev1.EnvVar{Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, statefulSet.Spec.Template.Spec.Containers[0].Env[11]) }) t.Run("environment variables with trustedCA", func(t *testing.T) { @@ -352,7 +342,7 @@ func TestAnnotations(t *testing.T) { assert.Len(t, statefulSet.ObjectMeta.Annotations, 1) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[consts.ExtensionsAnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationSecretHash]) }) t.Run("custom annotations", func(t *testing.T) { @@ -368,7 +358,7 @@ func TestAnnotations(t *testing.T) { assert.Empty(t, statefulSet.ObjectMeta.Annotations["a"]) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 2) assert.Equal(t, "b", statefulSet.Spec.Template.ObjectMeta.Annotations["a"]) - assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[consts.ExtensionsAnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationSecretHash]) }) } @@ -491,7 +481,7 @@ func TestVolumes(t *testing.T) { } assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) }) - t.Run("volumes with otel token", func(t *testing.T) { + t.Run("volumes with otelc token", func(t *testing.T) { dk := getTestDynakube() statefulSet := getStatefulset(t, dk) @@ -514,3 +504,53 @@ func TestVolumes(t *testing.T) { assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) }) } + +func getTestDynakube() *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakubeName, + Namespace: testNamespaceName, + Annotations: map[string]string{}, + }, + Spec: dynakube.DynaKubeSpec{ + Extensions: &dynakube.ExtensionsSpec{}, + Templates: dynakube.TemplatesSpec{OpenTelemetryCollector: dynakube.OpenTelemetryCollectorSpec{}}, + }, + } +} + +func getStatefulset(t *testing.T, dk *dynakube.DynaKube) *appsv1.StatefulSet { + mockK8sClient := fake.NewClient(dk) + mockK8sClient = mockTLSSecret(t, mockK8sClient, dk) + + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + statefulSet := &appsv1.StatefulSet{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) + require.NoError(t, err) + + return statefulSet +} + +func mockTLSSecret(t *testing.T, client client.Client, dk *dynakube.DynaKube) client.Client { + tlsSecret := getTLSSecret(dk.ExtensionsTLSSecretName(), dk.Namespace, "super-cert", "super-key") + + err := client.Create(context.Background(), &tlsSecret) + require.NoError(t, err) + + return client +} + +func getTLSSecret(name string, namespace string, crt string, key string) corev1.Secret { + return corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Data: map[string][]byte{ + consts.TLSCrtDataName: []byte(crt), + consts.TLSKeyDataName: []byte(key), + }, + } +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/volumes.go b/pkg/controllers/dynakube/otelc/statefulset/volumes.go new file mode 100644 index 0000000000..5b6a9c9957 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/statefulset/volumes.go @@ -0,0 +1,93 @@ +package statefulset + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" +) + +const ( + // Volume names and paths + caCertsVolumeName = "cacerts" + + trustedCAsFile = "rootca.pem" +) + +func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { + return func(o *appsv1.StatefulSet) { + o.Spec.Template.Spec.Volumes = []corev1.Volume{ + { + Name: consts.ExtensionsTokensVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTokenSecretName(), + Items: []corev1.KeyToPath{ + { + Key: consts.OtelcTokenSecretKey, + Path: consts.OtelcTokenSecretKey, + }, + }, + DefaultMode: ptr.To(int32(420)), + }, + }, + }, + } + if dk.Spec.TrustedCAs != "" { + o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ + Name: caCertsVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: dk.Spec.TrustedCAs, + }, + Items: []corev1.KeyToPath{ + { + Key: "certs", + Path: trustedCAsFile, + }, + }, + }, + }, + }) + } + + o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ + Name: dk.ExtensionsTLSSecretName(), + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTLSSecretName(), + Items: []corev1.KeyToPath{ + { + Key: consts.TLSCrtDataName, + Path: consts.TLSCrtDataName, + }, + }, + }, + }, + }) + } +} + +func buildContainerVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { + vm := []corev1.VolumeMount{ + {Name: consts.ExtensionsTokensVolumeName, ReadOnly: true, MountPath: secretsTokensPath}, + } + + if dk.Spec.TrustedCAs != "" { + vm = append(vm, corev1.VolumeMount{ + Name: caCertsVolumeName, + MountPath: trustedCAVolumeMountPath, + ReadOnly: true, + }) + } + + vm = append(vm, corev1.VolumeMount{ + Name: dk.ExtensionsTLSSecretName(), + MountPath: customEecTLSCertificatePath, + ReadOnly: true, + }) + + return vm +} diff --git a/pkg/util/kubeobjects/statefulset/builder.go b/pkg/util/kubeobjects/statefulset/builder.go index 1665926cbe..160040eb35 100644 --- a/pkg/util/kubeobjects/statefulset/builder.go +++ b/pkg/util/kubeobjects/statefulset/builder.go @@ -114,9 +114,14 @@ func SetSecurityContext(securityContext *corev1.PodSecurityContext) builder.Opti } } -func SetUpdateStrategy(updateStartegy appsv1.StatefulSetUpdateStrategy) builder.Option[*appsv1.StatefulSet] { +func SetRollingUpdateStrategyType() builder.Option[*appsv1.StatefulSet] { return func(s *appsv1.StatefulSet) { - s.Spec.UpdateStrategy = updateStartegy + s.Spec.UpdateStrategy = appsv1.StatefulSetUpdateStrategy{ + RollingUpdate: &appsv1.RollingUpdateStatefulSetStrategy{ + Partition: ptr.To(int32(0)), + }, + Type: appsv1.RollingUpdateStatefulSetStrategyType, + } } } diff --git a/pkg/util/kubeobjects/topology/constraint.go b/pkg/util/kubeobjects/topology/constraint.go new file mode 100644 index 0000000000..0bff759d33 --- /dev/null +++ b/pkg/util/kubeobjects/topology/constraint.go @@ -0,0 +1,24 @@ +package topology + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func MaxOnePerNode(appLabels *labels.AppLabels) []corev1.TopologySpreadConstraint { + return []corev1.TopologySpreadConstraint{ + { + MaxSkew: 1, + TopologyKey: "topology.kubernetes.io/zone", + WhenUnsatisfiable: "ScheduleAnyway", + LabelSelector: &metav1.LabelSelector{MatchLabels: appLabels.BuildMatchLabels()}, + }, + { + MaxSkew: 1, + TopologyKey: "kubernetes.io/hostname", + WhenUnsatisfiable: "DoNotSchedule", + LabelSelector: &metav1.LabelSelector{MatchLabels: appLabels.BuildMatchLabels()}, + }, + } +} From b4235e11261265a106d6a70ccca200da519ac45f Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 19 Dec 2024 11:34:16 +0100 Subject: [PATCH 072/426] Move install-config from `envFrom` to a direct env via templates (#4231) --- .../templates/Common/csi/daemonset.yaml | 4 +- .../Common/operator/deployment-operator.yaml | 4 +- .../Common/operator/install-config.yaml | 20 ------ .../Common/webhook/deployment-webhook.yaml | 4 +- .../helm/chart/default/templates/_helpers.tpl | 15 +++++ .../tests/Common/csi/daemonset_test.yaml | 15 ++++- .../operator/deployment-operator_test.yaml | 30 +++++++-- .../Common/operator/install-config_test.yaml | 61 ------------------- .../webhook/deployment-webhook_test.yaml | 45 +++++++++++--- 9 files changed, 90 insertions(+), 108 deletions(-) delete mode 100644 config/helm/chart/default/templates/Common/operator/install-config.yaml delete mode 100644 config/helm/chart/default/tests/Common/operator/install-config_test.yaml diff --git a/config/helm/chart/default/templates/Common/csi/daemonset.yaml b/config/helm/chart/default/templates/Common/csi/daemonset.yaml index 4017177d9a..c1e0cf69b7 100644 --- a/config/helm/chart/default/templates/Common/csi/daemonset.yaml +++ b/config/helm/chart/default/templates/Common/csi/daemonset.yaml @@ -170,9 +170,7 @@ spec: - name: MAX_UNMOUNTED_VOLUME_AGE value: "{{ .Values.csidriver.maxUnmountedVolumeAge}}" {{- end }} - envFrom: - - configMapRef: - name: install-config + {{ include "dynatrace-operator.modules-json-env" . | nindent 10 }} {{- include "dynatrace-operator.startupProbe" . | nindent 8 }} {{- if not .Values.debug }} livenessProbe: diff --git a/config/helm/chart/default/templates/Common/operator/deployment-operator.yaml b/config/helm/chart/default/templates/Common/operator/deployment-operator.yaml index 12d75d7a3d..06c2e59c4a 100644 --- a/config/helm/chart/default/templates/Common/operator/deployment-operator.yaml +++ b/config/helm/chart/default/templates/Common/operator/deployment-operator.yaml @@ -67,9 +67,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - envFrom: - - configMapRef: - name: install-config + {{ include "dynatrace-operator.modules-json-env" . | nindent 12}} ports: - containerPort: 10080 name: livez diff --git a/config/helm/chart/default/templates/Common/operator/install-config.yaml b/config/helm/chart/default/templates/Common/operator/install-config.yaml deleted file mode 100644 index d6aee6d8db..0000000000 --- a/config/helm/chart/default/templates/Common/operator/install-config.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: install-config - namespace: {{ .Release.Namespace }} - labels: - {{- include "dynatrace-operator.operatorLabels" . | nindent 4 }} -data: - modules.json: | - { - "csiDriver": {{ .Values.csidriver.enabled }}, - "activeGate": {{ .Values.rbac.activeGate.create }}, - "oneAgent": {{ .Values.rbac.oneAgent.create }}, - "extensions": {{ .Values.rbac.extensions.create }}, - "logMonitoring": {{ .Values.rbac.logMonitoring.create }}, - "edgeConnect": {{ .Values.rbac.edgeConnect.create }}, - "supportability": {{ .Values.rbac.supportability }}, - "kspm": {{ .Values.rbac.kspm.create }} - } - diff --git a/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml b/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml index be0f6718eb..e75d3ccc48 100644 --- a/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml +++ b/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml @@ -87,9 +87,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - envFrom: - - configMapRef: - name: install-config + {{ include "dynatrace-operator.modules-json-env" . | nindent 12 }} readinessProbe: httpGet: path: /readyz diff --git a/config/helm/chart/default/templates/_helpers.tpl b/config/helm/chart/default/templates/_helpers.tpl index 6b7a17949a..92610022ff 100644 --- a/config/helm/chart/default/templates/_helpers.tpl +++ b/config/helm/chart/default/templates/_helpers.tpl @@ -69,3 +69,18 @@ startupProbe: timeoutSeconds: 5 failureThreshold: 1 {{- end -}} + +{{- define "dynatrace-operator.modules-json-env" -}} +- name: modules.json + value: | + { + "csiDriver": {{ .Values.csidriver.enabled }}, + "activeGate": {{ .Values.rbac.activeGate.create }}, + "oneAgent": {{ .Values.rbac.oneAgent.create }}, + "extensions": {{ .Values.rbac.extensions.create }}, + "logMonitoring": {{ .Values.rbac.logMonitoring.create }}, + "edgeConnect": {{ .Values.rbac.edgeConnect.create }}, + "supportability": {{ .Values.rbac.supportability }}, + "kspm": {{ .Values.rbac.kspm.create }} + } +{{- end -}} diff --git a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml index 8520864c9e..742c692b4f 100644 --- a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml @@ -236,9 +236,18 @@ tests: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - envFrom: - - configMapRef: - name: install-config + - name: modules.json + value: | + { + "csiDriver": true, + "activeGate": true, + "oneAgent": true, + "extensions": true, + "logMonitoring": true, + "edgeConnect": true, + "supportability": true, + "kspm": true + } image: image-name imagePullPolicy: Always startupProbe: diff --git a/config/helm/chart/default/tests/Common/operator/deployment-operator_test.yaml b/config/helm/chart/default/tests/Common/operator/deployment-operator_test.yaml index e6cb89352a..e18bbfb6a0 100644 --- a/config/helm/chart/default/tests/Common/operator/deployment-operator_test.yaml +++ b/config/helm/chart/default/tests/Common/operator/deployment-operator_test.yaml @@ -86,9 +86,18 @@ tests: valueFrom: fieldRef: fieldPath: metadata.name - envFrom: - - configMapRef: - name: install-config + - name: modules.json + value: | + { + "csiDriver": true, + "activeGate": true, + "oneAgent": true, + "extensions": true, + "logMonitoring": true, + "edgeConnect": true, + "supportability": true, + "kspm": true + } ports: - containerPort: 10080 name: livez @@ -264,9 +273,18 @@ tests: valueFrom: fieldRef: fieldPath: metadata.name - envFrom: - - configMapRef: - name: install-config + - name: modules.json + value: | + { + "csiDriver": true, + "activeGate": true, + "oneAgent": true, + "extensions": true, + "logMonitoring": true, + "edgeConnect": true, + "supportability": true, + "kspm": true + } ports: - containerPort: 10080 name: livez diff --git a/config/helm/chart/default/tests/Common/operator/install-config_test.yaml b/config/helm/chart/default/tests/Common/operator/install-config_test.yaml deleted file mode 100644 index fb34fb7c25..0000000000 --- a/config/helm/chart/default/tests/Common/operator/install-config_test.yaml +++ /dev/null @@ -1,61 +0,0 @@ -suite: test role for oneagent on kubernetes -templates: - - Common/operator/install-config.yaml -tests: - - it: ConfigMap should exist - asserts: - - equal: - path: metadata.name - value: install-config - - equal: - path: metadata.namespace - value: NAMESPACE - - isNotEmpty: - path: metadata.labels - - equal: - path: data - value: - modules.json: | - { - "csiDriver": true, - "activeGate": true, - "oneAgent": true, - "extensions": true, - "logMonitoring": true, - "edgeConnect": true, - "supportability": true, - "kspm": true - } - - it: ConfigMap should respect the set values - set: - csidriver.enabled: false - rbac.oneAgent.create: false - rbac.logMonitoring.create: false - rbac.edgeConnect.create: false - rbac.activeGate.create: false - rbac.extensions.create: false - rbac.supportability: false - rbac.kspm.create: false - asserts: - - equal: - path: metadata.name - value: install-config - - equal: - path: metadata.namespace - value: NAMESPACE - - isNotEmpty: - path: metadata.labels - - equal: - path: data - value: - modules.json: | - { - "csiDriver": false, - "activeGate": false, - "oneAgent": false, - "extensions": false, - "logMonitoring": false, - "edgeConnect": false, - "supportability": false, - "kspm": false - } diff --git a/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml b/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml index 213ccff512..2f0b1d24f1 100644 --- a/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml +++ b/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml @@ -116,9 +116,18 @@ tests: valueFrom: fieldRef: fieldPath: metadata.name - envFrom: - - configMapRef: - name: install-config + - name: modules.json + value: | + { + "csiDriver": true, + "activeGate": true, + "oneAgent": true, + "extensions": true, + "logMonitoring": true, + "edgeConnect": true, + "supportability": true, + "kspm": true + } livenessProbe: httpGet: path: /livez @@ -297,9 +306,18 @@ tests: valueFrom: fieldRef: fieldPath: metadata.name - envFrom: - - configMapRef: - name: install-config + - name: modules.json + value: | + { + "csiDriver": true, + "activeGate": true, + "oneAgent": true, + "extensions": true, + "logMonitoring": true, + "edgeConnect": true, + "supportability": true, + "kspm": true + } livenessProbe: httpGet: path: /livez @@ -443,9 +461,18 @@ tests: valueFrom: fieldRef: fieldPath: metadata.name - envFrom: - - configMapRef: - name: install-config + - name: modules.json + value: | + { + "csiDriver": true, + "activeGate": true, + "oneAgent": true, + "extensions": true, + "logMonitoring": true, + "edgeConnect": true, + "supportability": true, + "kspm": true + } livenessProbe: httpGet: path: /livez From 5146f09797ccb4bc1378ba522413d07feef1c55d Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Thu, 19 Dec 2024 12:50:45 +0100 Subject: [PATCH 073/426] Unify make commands for deployment (#4214) Co-authored-by: Andrii Soldatenko --- HACKING.md | 14 +-------- Makefile | 3 -- doc/debug.md | 6 ++-- hack/make/debug/debug.mk | 2 +- hack/make/deploy/deploy.mk | 29 ++++++++++++------- hack/make/deploy/helm.mk | 20 ------------- hack/make/deploy/undeploy.mk | 19 ------------ .../components/operator/installation.go | 4 +-- 8 files changed, 25 insertions(+), 72 deletions(-) delete mode 100644 hack/make/deploy/helm.mk delete mode 100644 hack/make/deploy/undeploy.mk diff --git a/HACKING.md b/HACKING.md index 1345d12a7d..53a96489e6 100644 --- a/HACKING.md +++ b/HACKING.md @@ -7,19 +7,7 @@ ### Installation -There are automatic builds from the master branch. The latest development build can be installed as follows: - -#### Kubernetes - -```sh -make deploy/kubernetes -``` - -#### OpenShift - -```sh -make deploy/openshift -``` +There are automatic builds from the main branch. The latest development build can be installed using `make deploy`. #### Tests diff --git a/Makefile b/Makefile index 34900aaa6e..640f2c6efc 100644 --- a/Makefile +++ b/Makefile @@ -56,8 +56,5 @@ SHELL ?= bash ## Builds the operator image and pushes it to quay with a snapshot tag build: images/build/push -## Installs (deploys) the operator on a k8s/openshift cluster -install: deploy/helm - ## Installs prerequisites, builds and pushes a tagged operator image, and deploys the operator on a cluster all: prerequisites build install diff --git a/doc/debug.md b/doc/debug.md index a9c3611a45..1fefc74408 100644 --- a/doc/debug.md +++ b/doc/debug.md @@ -40,7 +40,7 @@ As the operator only sends requests to the Kubernetes API, but never receives an 1. Deploy the operator as usual: ```shell -make deploy/helm +make deploy ``` 2. Scale down the cluster operator: @@ -106,7 +106,7 @@ make debug/telepresence/uninstall 2. Deploy without debugging changes: ```shell -make deploy/helm +make deploy ``` ### CSI-Driver Server @@ -161,7 +161,7 @@ make debug/tunnel/stop 2. Deploy without debugging changes: ```shell -make deploy/helm +make deploy ``` ### CSI-Driver Provisioner diff --git a/hack/make/debug/debug.mk b/hack/make/debug/debug.mk index 3bb87cec1e..04b7b39b1d 100644 --- a/hack/make/debug/debug.mk +++ b/hack/make/debug/debug.mk @@ -19,7 +19,7 @@ debug/build: ## Install image with necessary changes to deployments. debug/deploy: - DEBUG=true make deploy/helm + DEBUG=true make deploy ## Install and setup Telepresence to intercept requests to the webhook debug/telepresence/install: diff --git a/hack/make/deploy/deploy.mk b/hack/make/deploy/deploy.mk index c9b70b49c5..7c1670f509 100644 --- a/hack/make/deploy/deploy.mk +++ b/hack/make/deploy/deploy.mk @@ -1,21 +1,28 @@ ENABLE_CSI ?= true PLATFORM ?= "kubernetes" -## Deploy the operator without the csi-driver, with platform specified in % (kubernetes or openshift) -deploy/%/no-csi: +## Deploy the operator without the csi-driver +deploy/no-csi: @make ENABLE_CSI=false $(@D) -## Deploy the operator with csi-driver, with platform specified in % (kubernetes or openshift) -deploy/%: - @make PLATFORM=$(@F) $(@D) - -## Deploy the operator with csi-driver, on kubernetes +## Deploy the operator with csi-driver deploy: manifests/crd/helm - kubectl get namespace dynatrace || kubectl create namespace dynatrace - helm template dynatrace-operator config/helm/chart/default \ + helm upgrade dynatrace-operator config/helm/chart/default \ + --install \ --namespace dynatrace \ + --create-namespace \ + --atomic \ --set installCRD=true \ - --set platform=$(PLATFORM) \ --set csidriver.enabled=$(ENABLE_CSI) \ --set manifests=true \ - --set image="$(IMAGE_URI)" | kubectl apply -f - + --set image="$(IMAGE_URI)" \ + --set debug=$(DEBUG) + +## Undeploy the current operator installation +undeploy: + kubectl delete dynakube --all -n dynatrace + kubectl delete edgeconnect --all -n dynatrace + kubectl -n dynatrace wait pod --for=delete -l app.kubernetes.io/managed-by=dynatrace-operator --timeout=300s + + helm uninstall dynatrace-operator \ + --namespace dynatrace diff --git a/hack/make/deploy/helm.mk b/hack/make/deploy/helm.mk deleted file mode 100644 index abc4aa4949..0000000000 --- a/hack/make/deploy/helm.mk +++ /dev/null @@ -1,20 +0,0 @@ - -DEBUG ?= false - -## Deploy the operator in a cluster configured in ~/.kube/config where platform and version are autodetected -deploy/helm: manifests/crd/helm - helm upgrade dynatrace-operator config/helm/chart/default \ - --install \ - --namespace dynatrace \ - --create-namespace \ - --atomic \ - --set installCRD=true \ - --set csidriver.enabled=$(ENABLE_CSI) \ - --set manifests=true \ - --set image="$(IMAGE_URI)" \ - --set debug=$(DEBUG) - -## Undeploy the operator in a cluster configured in ~/.kube/config where platform and k8s version are autodetected -undeploy/helm: - helm uninstall dynatrace-operator \ - --namespace dynatrace diff --git a/hack/make/deploy/undeploy.mk b/hack/make/deploy/undeploy.mk deleted file mode 100644 index cdd24f40bb..0000000000 --- a/hack/make/deploy/undeploy.mk +++ /dev/null @@ -1,19 +0,0 @@ -## Remove the operator without the csi-driver, with platform specified in % (kubernetes or openshift) -undeploy/%/no-csi: - @make ENABLE_CSI=false $(@D) - -## Remove the operator with csi-driver, with platform specified in % (kubernetes or openshift) -undeploy/%: - @make PLATFORM=$(@F) $(@D) - -## Remove the operator with csi-driver, on kubernetes -undeploy: manifests/crd/helm - kubectl delete dynakube --all -n dynatrace - kubectl -n dynatrace wait pod --for=delete -l app.kubernetes.io/managed-by=dynatrace-operator --timeout=300s - helm template dynatrace-operator config/helm/chart/default \ - --namespace dynatrace \ - --set installCRD=true \ - --set platform=$(PLATFORM) \ - --set csidriver.enabled=$(ENABLE_CSI) \ - --set manifests=true \ - --set image="$(IMAGE_URI)" | kubectl delete -f - diff --git a/test/helpers/components/operator/installation.go b/test/helpers/components/operator/installation.go index da3e9b59d4..b346f9607e 100644 --- a/test/helpers/components/operator/installation.go +++ b/test/helpers/components/operator/installation.go @@ -25,7 +25,7 @@ const ( func InstallViaMake(withCSI bool) env.Func { return func(ctx context.Context, envConfig *envconf.Config) (context.Context, error) { rootDir := project.RootDir() - err := execMakeCommand(rootDir, "deploy/helm", fmt.Sprintf("ENABLE_CSI=%t", withCSI)) + err := execMakeCommand(rootDir, "deploy", fmt.Sprintf("ENABLE_CSI=%t", withCSI)) if err != nil { return ctx, err } @@ -56,7 +56,7 @@ func UninstallViaMake(withCSI bool) env.Func { } } - return ctx, execMakeCommand(rootDir, "undeploy/helm", fmt.Sprintf("ENABLE_CSI=%t", withCSI)) + return ctx, execMakeCommand(rootDir, "undeploy", fmt.Sprintf("ENABLE_CSI=%t", withCSI)) } } From 21a8181ed51333f1a5157cdde93698ee4367a2f7 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Thu, 19 Dec 2024 12:59:59 +0100 Subject: [PATCH 074/426] Move OneAgent type into its own section (#4211) --- cmd/troubleshoot/component.go | 8 +- cmd/troubleshoot/dynakube_test.go | 31 +- cmd/troubleshoot/image.go | 2 +- cmd/troubleshoot/image_test.go | 3 +- doc/e2e/features.md | 22 +- pkg/api/v1beta1/dynakube/convert_from.go | 17 +- pkg/api/v1beta1/dynakube/convert_from_test.go | 41 +-- pkg/api/v1beta1/dynakube/convert_to.go | 21 +- pkg/api/v1beta2/dynakube/convert_from.go | 31 +- pkg/api/v1beta2/dynakube/convert_from_test.go | 39 +- pkg/api/v1beta2/dynakube/convert_to.go | 21 +- pkg/api/v1beta3/dynakube/activegate/props.go | 2 +- .../v1beta3/dynakube/dynakube_props_test.go | 2 - pkg/api/v1beta3/dynakube/dynakube_status.go | 57 +-- pkg/api/v1beta3/dynakube/dynakube_types.go | 3 +- .../v1beta3/dynakube/feature_flags_test.go | 30 ++ .../v1beta3/dynakube/logmonitoring/props.go | 8 + .../v1beta3/dynakube/logmonitoring_props.go | 2 +- pkg/api/v1beta3/dynakube/oneagent/props.go | 312 ++++++++++++++++ .../v1beta3/dynakube/oneagent/props_test.go | 260 ++++++++++++++ .../{oneagent_types.go => oneagent/spec.go} | 29 +- pkg/api/v1beta3/dynakube/oneagent/status.go | 58 +++ .../oneagent/zz_generated.deepcopy.go | 274 ++++++++++++++ pkg/api/v1beta3/dynakube/oneagent_props.go | 305 +--------------- .../v1beta3/dynakube/oneagent_props_test.go | 338 ------------------ .../v1beta3/dynakube/zz_generated.deepcopy.go | 251 ------------- pkg/api/validation/dynakube/csi_daemonset.go | 4 +- .../validation/dynakube/csi_daemonset_test.go | 9 +- pkg/api/validation/dynakube/image.go | 2 +- pkg/api/validation/dynakube/image_test.go | 17 +- pkg/api/validation/dynakube/logmonitoring.go | 2 +- .../validation/dynakube/logmonitoring_test.go | 5 +- pkg/api/validation/dynakube/module_test.go | 27 +- pkg/api/validation/dynakube/modules.go | 4 +- .../validation/dynakube/namespace_selector.go | 4 +- .../dynakube/namespace_selector_test.go | 49 +-- pkg/api/validation/dynakube/oneagent.go | 40 ++- pkg/api/validation/dynakube/oneagent_test.go | 93 ++--- pkg/api/validation/dynakube/preview_test.go | 5 +- .../validation/dynakube/validation_test.go | 33 +- pkg/clients/dynatrace/processmoduleconfig.go | 4 +- pkg/controllers/csi/gc/reconciler.go | 2 +- pkg/controllers/csi/provisioner/controller.go | 12 +- .../csi/provisioner/controller_test.go | 43 +-- pkg/controllers/csi/provisioner/install.go | 4 +- .../csi/provisioner/install_test.go | 13 +- .../dynakube/apimonitoring/reconciler_test.go | 5 +- .../activegate/communication_hosts_test.go | 5 +- .../oneagent/communication_hosts_test.go | 7 +- .../connectioninfo/oneagent/reconciler.go | 17 +- .../oneagent/reconciler_test.go | 43 +-- .../dynakube/controller_system_test.go | 7 +- pkg/controllers/dynakube/controller_test.go | 19 +- .../deploymentmetadata/deploymentmetadata.go | 8 +- .../deploymentmetadata_test.go | 11 +- .../dynakube/deploymentmetadata/reconciler.go | 4 +- .../deploymentmetadata/reconciler_test.go | 9 +- .../dynakube/dtpullsecret/generate_test.go | 5 +- .../dynakube/dtpullsecret/reconciler.go | 2 +- .../dynakube/dtpullsecret/reconciler_test.go | 7 +- .../dynakube/dynatraceclient/builder.go | 2 +- .../dynakube/injection/reconciler.go | 6 +- .../dynakube/injection/reconciler_test.go | 43 +-- pkg/controllers/dynakube/istio/reconciler.go | 2 +- .../dynakube/istio/reconciler_test.go | 13 +- .../logmonitoring/configsecret/reconciler.go | 4 +- .../configsecret/reconciler_test.go | 9 +- .../daemonset/reconciler_test.go | 7 +- .../dynakube/oneagent/daemonset/arguments.go | 6 +- .../oneagent/daemonset/arguments_test.go | 45 +-- .../dynakube/oneagent/daemonset/daemonset.go | 35 +- .../oneagent/daemonset/daemonset_test.go | 117 +++--- .../dynakube/oneagent/daemonset/env_vars.go | 8 +- .../oneagent/daemonset/env_vars_test.go | 15 +- .../dynakube/oneagent/daemonset/volumes.go | 6 +- .../oneagent/daemonset/volumes_test.go | 45 +-- .../dynakube/oneagent/oneagent_reconciler.go | 23 +- .../oneagent/oneagent_reconciler_test.go | 69 ++-- pkg/controllers/dynakube/phase.go | 4 +- pkg/controllers/dynakube/phase_test.go | 9 +- .../processmoduleconfigsecret/reconciler.go | 6 +- .../reconciler_test.go | 27 +- .../dynakube/version/activegate.go | 2 +- .../dynakube/version/codemodules.go | 11 +- .../dynakube/version/codemodules_test.go | 27 +- pkg/controllers/dynakube/version/oneagent.go | 16 +- .../dynakube/version/oneagent_test.go | 51 +-- .../dynakube/version/reconciler.go | 2 +- .../dynakube/version/reconciler_test.go | 17 +- .../nodes/nodes_controller_test.go | 13 +- .../initgeneration/initgeneration.go | 10 +- .../initgeneration/initgeneration_test.go | 15 +- pkg/injection/namespace/mapper/mapper.go | 8 +- pkg/injection/namespace/mapper/mapper_test.go | 5 +- pkg/oci/registry/client_test.go | 9 +- .../mutation/namespace/webhook_test.go | 7 +- pkg/webhook/mutation/pod/init_container.go | 4 +- .../mutation/pod/metadata/mutator_test.go | 9 +- .../mutation/pod/oneagent/annotations.go | 2 +- pkg/webhook/mutation/pod/oneagent/env_test.go | 9 +- pkg/webhook/mutation/pod/oneagent/mutator.go | 10 +- .../mutation/pod/oneagent/mutator_test.go | 33 +- pkg/webhook/mutation/pod/oneagent/volumes.go | 2 +- pkg/webhook/mutation/pod/webhook_test.go | 15 +- .../label_version_detection.go | 15 +- .../metadata_enrichment.go | 8 +- .../read_only_csi_volume.go | 3 +- .../applicationmonitoring/without_csi.go | 4 +- test/features/classic/classic.go | 4 +- .../classic/switch_modes/switch_modes.go | 8 +- .../cloudnative/codemodules/codemodules.go | 19 +- test/features/cloudnative/init_containers.go | 8 +- .../cloudnative/switch_modes/switch_modes.go | 6 +- .../support_archive/support_archive.go | 3 +- .../components/codemodules/codemodules.go | 2 +- test/helpers/components/dynakube/dynakube.go | 10 +- test/helpers/components/dynakube/options.go | 15 +- test/helpers/components/oneagent/daemonset.go | 2 +- test/helpers/istio/install.go | 2 +- 119 files changed, 1840 insertions(+), 1735 deletions(-) create mode 100644 pkg/api/v1beta3/dynakube/oneagent/props.go create mode 100644 pkg/api/v1beta3/dynakube/oneagent/props_test.go rename pkg/api/v1beta3/dynakube/{oneagent_types.go => oneagent/spec.go} (94%) create mode 100644 pkg/api/v1beta3/dynakube/oneagent/status.go create mode 100644 pkg/api/v1beta3/dynakube/oneagent/zz_generated.deepcopy.go delete mode 100644 pkg/api/v1beta3/dynakube/oneagent_props_test.go diff --git a/cmd/troubleshoot/component.go b/cmd/troubleshoot/component.go index e6aa42b3f7..19cb8cef18 100644 --- a/cmd/troubleshoot/component.go +++ b/cmd/troubleshoot/component.go @@ -37,13 +37,13 @@ func (c component) getImage(dk *dynakube.DynaKube) (string, bool) { switch c { case componentOneAgent: - if dk.CustomOneAgentImage() != "" { - return dk.CustomOneAgentImage(), true + if dk.OneAgent().GetCustomImage() != "" { + return dk.OneAgent().GetCustomImage(), true } - return dk.OneAgentImage(), false + return dk.OneAgent().GetImage(), false case componentCodeModules: - return dk.CustomCodeModulesImage(), true + return dk.OneAgent().GetCustomCodeModulesImage(), true case componentActiveGate: if dk.ActiveGate().GetCustomImage() != "" { return dk.ActiveGate().GetCustomImage(), true diff --git a/cmd/troubleshoot/dynakube_test.go b/cmd/troubleshoot/dynakube_test.go index d9771a88a3..58181487a4 100644 --- a/cmd/troubleshoot/dynakube_test.go +++ b/cmd/troubleshoot/dynakube_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/pkg/errors" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -295,24 +296,24 @@ func (builder *testDynaKubeBuilder) withActiveGateCustomImage(image string) *tes } func (builder *testDynaKubeBuilder) withCloudNativeFullStack() *testDynaKubeBuilder { - builder.dynakube.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{}, + builder.dynakube.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{}, } - builder.dynakube.Status.OneAgent.ImageID = builder.dynakube.DefaultOneAgentImage(testVersion) + builder.dynakube.Status.OneAgent.ImageID = builder.dynakube.OneAgent().GetDefaultImage(testVersion) return builder } func (builder *testDynaKubeBuilder) withClassicFullStack() *testDynaKubeBuilder { - builder.dynakube.Spec.OneAgent.ClassicFullStack = &dynakube.HostInjectSpec{} - builder.dynakube.Status.OneAgent.ImageID = builder.dynakube.DefaultOneAgentImage(testVersion) + builder.dynakube.Spec.OneAgent.ClassicFullStack = &oneagent.HostInjectSpec{} + builder.dynakube.Status.OneAgent.ImageID = builder.dynakube.OneAgent().GetDefaultImage(testVersion) return builder } func (builder *testDynaKubeBuilder) withHostMonitoring() *testDynaKubeBuilder { - builder.dynakube.Spec.OneAgent.HostMonitoring = &dynakube.HostInjectSpec{} - builder.dynakube.Status.OneAgent.ImageID = builder.dynakube.DefaultOneAgentImage(testVersion) + builder.dynakube.Spec.OneAgent.HostMonitoring = &oneagent.HostInjectSpec{} + builder.dynakube.Status.OneAgent.ImageID = builder.dynakube.OneAgent().GetDefaultImage(testVersion) return builder } @@ -321,7 +322,7 @@ func (builder *testDynaKubeBuilder) withClassicFullStackCustomImage(image string if builder.dynakube.Spec.OneAgent.ClassicFullStack != nil { builder.dynakube.Spec.OneAgent.ClassicFullStack.Image = image } else { - builder.dynakube.Spec.OneAgent.ClassicFullStack = &dynakube.HostInjectSpec{ + builder.dynakube.Spec.OneAgent.ClassicFullStack = &oneagent.HostInjectSpec{ Image: image, } } @@ -334,8 +335,8 @@ func (builder *testDynaKubeBuilder) withCloudNativeFullStackCustomImage(image st if builder.dynakube.Spec.OneAgent.CloudNativeFullStack != nil { builder.dynakube.Spec.OneAgent.CloudNativeFullStack.Image = image } else { - builder.dynakube.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + builder.dynakube.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ Image: image, }, } @@ -349,7 +350,7 @@ func (builder *testDynaKubeBuilder) withHostMonitoringCustomImage(image string) if builder.dynakube.Spec.OneAgent.HostMonitoring != nil { builder.dynakube.Spec.OneAgent.HostMonitoring.Image = image } else { - builder.dynakube.Spec.OneAgent.HostMonitoring = &dynakube.HostInjectSpec{ + builder.dynakube.Spec.OneAgent.HostMonitoring = &oneagent.HostInjectSpec{ Image: image, } } @@ -362,8 +363,8 @@ func (builder *testDynaKubeBuilder) withCloudNativeCodeModulesImage(image string if builder.dynakube.Spec.OneAgent.CloudNativeFullStack != nil { builder.dynakube.Spec.OneAgent.CloudNativeFullStack.CodeModulesImage = image } else { - builder.dynakube.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + builder.dynakube.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ InitResources: &corev1.ResourceRequirements{}, CodeModulesImage: image, }, @@ -378,8 +379,8 @@ func (builder *testDynaKubeBuilder) withApplicationMonitoringCodeModulesImage(im if builder.dynakube.Spec.OneAgent.ApplicationMonitoring != nil { builder.dynakube.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage = image } else { - builder.dynakube.Spec.OneAgent.ApplicationMonitoring = &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + builder.dynakube.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ InitResources: &corev1.ResourceRequirements{}, CodeModulesImage: image, }, diff --git a/cmd/troubleshoot/image.go b/cmd/troubleshoot/image.go index efa7a3b8b6..802526a919 100644 --- a/cmd/troubleshoot/image.go +++ b/cmd/troubleshoot/image.go @@ -35,7 +35,7 @@ func verifyAllImagesAvailable(ctx context.Context, baseLog logd.Logger, keychain imagePullFunc := CreateImagePullFunc(ctx, keychain, transport) - if dk.NeedsOneAgent() { + if dk.OneAgent().IsDaemonsetRequired() { verifyImageIsAvailable(log, imagePullFunc, dk, componentOneAgent, false) verifyImageIsAvailable(log, imagePullFunc, dk, componentCodeModules, true) } diff --git a/cmd/troubleshoot/image_test.go b/cmd/troubleshoot/image_test.go index f472bddff1..6331e282c4 100644 --- a/cmd/troubleshoot/image_test.go +++ b/cmd/troubleshoot/image_test.go @@ -13,6 +13,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dtpullsecret" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/Dynatrace/dynatrace-operator/pkg/oci/dockerkeychain" @@ -80,7 +81,7 @@ func TestImagePullable(t *testing.T) { dockerServer, secret, server, err := setupDockerMocker( []string{ "/v2/", - "/v2" + dynakube.DefaultOneAgentImageRegistrySubPath + "/manifests/" + testVersion + "-raw", + "/v2" + oneagent.DefaultOneAgentImageRegistrySubPath + "/manifests/" + testVersion + "-raw", "/v2/" + testCustomOneAgentImage + "/manifests/" + testVersion, "/v2/" + testOneAgentCodeModulesImage + "/manifests/" + testVersion, "/v2" + activegate.DefaultImageRegistrySubPath + "/manifests/" + testVersion + "-raw", diff --git a/doc/e2e/features.md b/doc/e2e/features.md index 3a0a6b1d00..18d350a903 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -41,7 +41,7 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/applicationmonitor -## func [LabelVersionDetection]() +## func [LabelVersionDetection]() ```go func LabelVersionDetection(t *testing.T) features.Feature @@ -63,7 +63,7 @@ Verification of the metadata enrichment part of the operator. The test checks th -## func [ReadOnlyCSIVolume]() +## func [ReadOnlyCSIVolume]() ```go func ReadOnlyCSIVolume(t *testing.T) features.Feature @@ -131,7 +131,7 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" - [func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrt []byte, trustedCAs []byte)](<#AssessOneAgentContainer>) - [func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrt []byte, trustedCAs []byte)](<#AssessSampleContainer>) - [func AssessSampleInitContainers(builder *features.FeatureBuilder, sampleApp *sample.App)](<#AssessSampleInitContainers>) -- [func DefaultCloudNativeSpec() *dynakube.CloudNativeFullStackSpec](<#DefaultCloudNativeSpec>) +- [func DefaultCloudNativeSpec() *oneagent.CloudNativeFullStackSpec](<#DefaultCloudNativeSpec>) @@ -170,7 +170,7 @@ func AssessSampleInitContainers(builder *features.FeatureBuilder, sampleApp *sam ## func [DefaultCloudNativeSpec]() ```go -func DefaultCloudNativeSpec() *dynakube.CloudNativeFullStackSpec +func DefaultCloudNativeSpec() *oneagent.CloudNativeFullStackSpec ``` # codemodules @@ -189,7 +189,7 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/codemo -## func [InstallFromImage]() +## func [InstallFromImage]() ```go func InstallFromImage(t *testing.T) features.Feature @@ -199,7 +199,7 @@ Verification that the storage in the CSI driver directory does not increase when -## func [WithProxy]() +## func [WithProxy]() ```go func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature @@ -215,7 +215,7 @@ Connectivity in the dynatrace namespace and sample application namespace is rest -## func [WithProxyAndAGCert]() +## func [WithProxyAndAGCert]() ```go func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature @@ -223,7 +223,7 @@ func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature -## func [WithProxyCA]() +## func [WithProxyCA]() ```go func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature @@ -231,7 +231,7 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature -## func [WithProxyCAAndAGCert]() +## func [WithProxyCAAndAGCert]() ```go func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature @@ -478,7 +478,7 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/support_archive" -## func [Feature]() +## func [Feature]() ```go func Feature(t *testing.T) features.Feature @@ -490,7 +490,7 @@ Verification if support-archive package created by the support-archive command a -## type [CustomResources]() +## type [CustomResources]() ```go type CustomResources struct { diff --git a/pkg/api/v1beta1/dynakube/convert_from.go b/pkg/api/v1beta1/dynakube/convert_from.go index 3ce9bc625a..34b695f990 100644 --- a/pkg/api/v1beta1/dynakube/convert_from.go +++ b/pkg/api/v1beta1/dynakube/convert_from.go @@ -4,6 +4,7 @@ import ( "strconv" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/conversion" @@ -48,15 +49,15 @@ func (dst *DynaKube) fromOneAgentSpec(src *dynakube.DynaKube) { dst.Spec.OneAgent.HostGroup = src.Spec.OneAgent.HostGroup switch { - case src.HostMonitoringMode(): + case src.OneAgent().IsHostMonitoringMode(): dst.Spec.OneAgent.HostMonitoring = fromHostInjectSpec(*src.Spec.OneAgent.HostMonitoring) - case src.ClassicFullStackMode(): + case src.OneAgent().IsClassicFullStackMode(): dst.Spec.OneAgent.ClassicFullStack = fromHostInjectSpec(*src.Spec.OneAgent.ClassicFullStack) - case src.CloudNativeFullstackMode(): + case src.OneAgent().IsCloudNativeFullstackMode(): dst.Spec.OneAgent.CloudNativeFullStack = &CloudNativeFullStackSpec{} dst.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec = *fromHostInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec) dst.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec = *fromAppInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec) - case src.ApplicationMonitoringMode(): + case src.OneAgent().IsApplicationMonitoringMode(): dst.Spec.OneAgent.ApplicationMonitoring = &ApplicationMonitoringSpec{} dst.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec = *fromAppInjectSpec(src.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec) dst.Spec.OneAgent.ApplicationMonitoring.Version = src.Spec.OneAgent.ApplicationMonitoring.Version @@ -94,9 +95,9 @@ func (dst *DynaKube) fromActiveGateSpec(src *dynakube.DynaKube) { func (dst *DynaKube) fromMovedFields(src *dynakube.DynaKube) error { dst.Annotations[AnnotationFeatureMetadataEnrichment] = strconv.FormatBool(src.MetadataEnrichmentEnabled()) dst.Annotations[AnnotationFeatureApiRequestThreshold] = strconv.FormatInt(int64(src.GetDynatraceApiRequestThreshold()), 10) - dst.Annotations[AnnotationFeatureOneAgentSecCompProfile] = src.OneAgentSecCompProfile() + dst.Annotations[AnnotationFeatureOneAgentSecCompProfile] = src.OneAgent().GetSecCompProfile() - if selector := src.OneAgentNamespaceSelector(); selector != nil { + if selector := src.OneAgent().GetNamespaceSelector(); selector != nil { dst.Spec.NamespaceSelector = *selector } else { dst.Spec.NamespaceSelector = src.Spec.MetadataEnrichment.NamespaceSelector @@ -160,7 +161,7 @@ func (dst *DynaKube) fromActiveGateStatus(src dynakube.DynaKube) { dst.Status.ActiveGate.VersionStatus = src.Status.ActiveGate.VersionStatus } -func fromHostInjectSpec(src dynakube.HostInjectSpec) *HostInjectSpec { +func fromHostInjectSpec(src oneagent.HostInjectSpec) *HostInjectSpec { dst := &HostInjectSpec{} dst.AutoUpdate = src.AutoUpdate dst.OneAgentResources = src.OneAgentResources @@ -178,7 +179,7 @@ func fromHostInjectSpec(src dynakube.HostInjectSpec) *HostInjectSpec { return dst } -func fromAppInjectSpec(src dynakube.AppInjectionSpec) *AppInjectionSpec { +func fromAppInjectSpec(src oneagent.AppInjectionSpec) *AppInjectionSpec { dst := &AppInjectionSpec{} dst.CodeModulesImage = src.CodeModulesImage diff --git a/pkg/api/v1beta1/dynakube/convert_from_test.go b/pkg/api/v1beta1/dynakube/convert_from_test.go index 9ed9621959..b76aaacb51 100644 --- a/pkg/api/v1beta1/dynakube/convert_from_test.go +++ b/pkg/api/v1beta1/dynakube/convert_from_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -135,7 +136,7 @@ func compareBase(t *testing.T, oldDk DynaKube, newDk dynakube.DynaKube) { func compareMovedFields(t *testing.T, oldDk DynaKube, newDk dynakube.DynaKube) { assert.Equal(t, oldDk.FeatureApiRequestThreshold(), newDk.ApiRequestThreshold()) - assert.Equal(t, oldDk.FeatureOneAgentSecCompProfile(), newDk.OneAgentSecCompProfile()) + assert.Equal(t, oldDk.FeatureOneAgentSecCompProfile(), newDk.OneAgent().GetSecCompProfile()) assert.Equal(t, !oldDk.FeatureDisableMetadataEnrichment(), newDk.MetadataEnrichmentEnabled()) assert.Equal(t, *oldDk.NamespaceSelector(), newDk.Spec.MetadataEnrichment.NamespaceSelector) @@ -143,12 +144,12 @@ func compareMovedFields(t *testing.T, oldDk DynaKube, newDk dynakube.DynaKube) { assert.Equal(t, dynakube.MountAttemptsToTimeout(oldDk.FeatureMaxFailedCsiMountAttempts()), newDk.FeatureMaxCSIRetryTimeout().String()) } - if newDk.NeedAppInjection() { - assert.Equal(t, oldDk.NamespaceSelector(), newDk.OneAgentNamespaceSelector()) + if newDk.OneAgent().IsAppInjectionNeeded() { + assert.Equal(t, oldDk.NamespaceSelector(), newDk.OneAgent().GetNamespaceSelector()) } } -func compareHostInjectSpec(t *testing.T, oldSpec HostInjectSpec, newSpec dynakube.HostInjectSpec) { +func compareHostInjectSpec(t *testing.T, oldSpec HostInjectSpec, newSpec oneagent.HostInjectSpec) { assert.Equal(t, oldSpec.Annotations, newSpec.Annotations) assert.Equal(t, oldSpec.Args, newSpec.Args) assert.Equal(t, *oldSpec.AutoUpdate, *newSpec.AutoUpdate) @@ -163,17 +164,17 @@ func compareHostInjectSpec(t *testing.T, oldSpec HostInjectSpec, newSpec dynakub assert.Equal(t, oldSpec.Version, newSpec.Version) } -func compareAppInjectionSpec(t *testing.T, oldSpec AppInjectionSpec, newSpec dynakube.AppInjectionSpec) { +func compareAppInjectionSpec(t *testing.T, oldSpec AppInjectionSpec, newSpec oneagent.AppInjectionSpec) { assert.Equal(t, oldSpec.CodeModulesImage, newSpec.CodeModulesImage) assert.Equal(t, oldSpec.InitResources, newSpec.InitResources) } -func compareCloudNativeSpec(t *testing.T, oldSpec CloudNativeFullStackSpec, newSpec dynakube.CloudNativeFullStackSpec) { +func compareCloudNativeSpec(t *testing.T, oldSpec CloudNativeFullStackSpec, newSpec oneagent.CloudNativeFullStackSpec) { compareAppInjectionSpec(t, oldSpec.AppInjectionSpec, newSpec.AppInjectionSpec) compareHostInjectSpec(t, oldSpec.HostInjectSpec, newSpec.HostInjectSpec) } -func compareApplicationMonitoringSpec(t *testing.T, oldSpec ApplicationMonitoringSpec, newSpec dynakube.ApplicationMonitoringSpec) { +func compareApplicationMonitoringSpec(t *testing.T, oldSpec ApplicationMonitoringSpec, newSpec oneagent.ApplicationMonitoringSpec) { compareAppInjectionSpec(t, oldSpec.AppInjectionSpec, newSpec.AppInjectionSpec) assert.Equal(t, *oldSpec.UseCSIDriver, isEnabledModules.CSIDriver) assert.Equal(t, oldSpec.Version, newSpec.Version) @@ -279,8 +280,8 @@ func getNewDynakubeBase() dynakube.DynaKube { } } -func getNewHostInjectSpec() dynakube.HostInjectSpec { - return dynakube.HostInjectSpec{ +func getNewHostInjectSpec() oneagent.HostInjectSpec { + return oneagent.HostInjectSpec{ Version: "host-inject-version", Image: "host-inject-image", Tolerations: []corev1.Toleration{ @@ -322,8 +323,8 @@ func getNewHostInjectSpec() dynakube.HostInjectSpec { } } -func getNewAppInjectionSpec() dynakube.AppInjectionSpec { - return dynakube.AppInjectionSpec{ +func getNewAppInjectionSpec() oneagent.AppInjectionSpec { + return oneagent.AppInjectionSpec{ InitResources: &corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: *resource.NewScaledQuantity(2, 1)}, @@ -333,15 +334,15 @@ func getNewAppInjectionSpec() dynakube.AppInjectionSpec { } } -func getNewCloudNativeSpec() dynakube.CloudNativeFullStackSpec { - return dynakube.CloudNativeFullStackSpec{ +func getNewCloudNativeSpec() oneagent.CloudNativeFullStackSpec { + return oneagent.CloudNativeFullStackSpec{ AppInjectionSpec: getNewAppInjectionSpec(), HostInjectSpec: getNewHostInjectSpec(), } } -func getNewApplicationMonitoringSpec() dynakube.ApplicationMonitoringSpec { - return dynakube.ApplicationMonitoringSpec{ +func getNewApplicationMonitoringSpec() oneagent.ApplicationMonitoringSpec { + return oneagent.ApplicationMonitoringSpec{ AppInjectionSpec: getNewAppInjectionSpec(), Version: "app-monitoring-version", } @@ -402,7 +403,7 @@ func getNewActiveGateSpec() activegate.Spec { func getNewStatus() dynakube.DynaKubeStatus { return dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ ImageID: "oa-image-id", Version: "oa-version", @@ -410,7 +411,7 @@ func getNewStatus() dynakube.DynaKubeStatus { Source: status.CustomImageVersionSource, LastProbeTimestamp: &testTime, }, - Instances: map[string]dynakube.OneAgentInstance{ + Instances: map[string]oneagent.Instance{ "oa-instance-key-1": { PodName: "oa-instance-pod-1", IPAddress: "oa-instance-ip-1", @@ -424,13 +425,13 @@ func getNewStatus() dynakube.DynaKubeStatus { Healthcheck: ®istryv1.HealthConfig{ Test: []string{"oa-health-check-test"}, }, - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ LastRequest: testTime, TenantUUID: "oa-tenant-uuid", Endpoints: "oa-endpoints", }, - CommunicationHosts: []dynakube.CommunicationHostStatus{ + CommunicationHosts: []oneagent.CommunicationHostStatus{ { Protocol: "oa-protocol-1", Host: "oa-host-1", @@ -453,7 +454,7 @@ func getNewStatus() dynakube.DynaKubeStatus { LastProbeTimestamp: &testTime, }, }, - CodeModules: dynakube.CodeModulesStatus{ + CodeModules: oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ ImageID: "cm-image-id", Version: "cm-version", diff --git a/pkg/api/v1beta1/dynakube/convert_to.go b/pkg/api/v1beta1/dynakube/convert_to.go index 89c46c2cf7..4a8edc283a 100644 --- a/pkg/api/v1beta1/dynakube/convert_to.go +++ b/pkg/api/v1beta1/dynakube/convert_to.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/conversion" ) @@ -61,11 +62,11 @@ func (src *DynaKube) toOneAgentSpec(dst *dynakube.DynaKube) { case src.ClassicFullStackMode(): dst.Spec.OneAgent.ClassicFullStack = toHostInjectSpec(*src.Spec.OneAgent.ClassicFullStack) case src.CloudNativeFullstackMode(): - dst.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} + dst.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} dst.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec = *toHostInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec) dst.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec = *toAppInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec) case src.ApplicationMonitoringMode(): - dst.Spec.OneAgent.ApplicationMonitoring = &dynakube.ApplicationMonitoringSpec{} + dst.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} dst.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec = *toAppInjectSpec(src.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec) dst.Spec.OneAgent.ApplicationMonitoring.Version = src.Spec.OneAgent.ApplicationMonitoring.Version } @@ -165,7 +166,7 @@ func (src *DynaKube) convertDynatraceApiRequestThreshold(dst *dynakube.DynaKube) func (src *DynaKube) toStatus(dst *dynakube.DynaKube) { src.toOneAgentStatus(dst) src.toActiveGateStatus(dst) - dst.Status.CodeModules = dynakube.CodeModulesStatus{ + dst.Status.CodeModules = oneagent.CodeModulesStatus{ VersionStatus: src.Status.CodeModules.VersionStatus, } @@ -180,11 +181,11 @@ func (src *DynaKube) toStatus(dst *dynakube.DynaKube) { } func (src *DynaKube) toOneAgentStatus(dst *dynakube.DynaKube) { - dst.Status.OneAgent.Instances = map[string]dynakube.OneAgentInstance{} + dst.Status.OneAgent.Instances = map[string]oneagent.Instance{} // Instance for key, instance := range src.Status.OneAgent.Instances { - tmp := dynakube.OneAgentInstance{ + tmp := oneagent.Instance{ PodName: instance.PodName, IPAddress: instance.IPAddress, } @@ -197,7 +198,7 @@ func (src *DynaKube) toOneAgentStatus(dst *dynakube.DynaKube) { dst.Status.OneAgent.ConnectionInfoStatus.ConnectionInfo = (communication.ConnectionInfo)(src.Status.OneAgent.ConnectionInfoStatus.ConnectionInfoStatus) for _, host := range src.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts { - tmp := dynakube.CommunicationHostStatus{ + tmp := oneagent.CommunicationHostStatus{ Host: host.Host, Port: host.Port, Protocol: host.Protocol, @@ -216,8 +217,8 @@ func (src *DynaKube) toActiveGateStatus(dst *dynakube.DynaKube) { dst.Status.ActiveGate.VersionStatus = src.Status.ActiveGate.VersionStatus } -func toHostInjectSpec(src HostInjectSpec) *dynakube.HostInjectSpec { - dst := &dynakube.HostInjectSpec{} +func toHostInjectSpec(src HostInjectSpec) *oneagent.HostInjectSpec { + dst := &oneagent.HostInjectSpec{} dst.AutoUpdate = src.AutoUpdate dst.OneAgentResources = src.OneAgentResources dst.Args = src.Args @@ -234,8 +235,8 @@ func toHostInjectSpec(src HostInjectSpec) *dynakube.HostInjectSpec { return dst } -func toAppInjectSpec(src AppInjectionSpec) *dynakube.AppInjectionSpec { - dst := &dynakube.AppInjectionSpec{} +func toAppInjectSpec(src AppInjectionSpec) *oneagent.AppInjectionSpec { + dst := &oneagent.AppInjectionSpec{} dst.CodeModulesImage = src.CodeModulesImage dst.InitResources = src.InitResources diff --git a/pkg/api/v1beta2/dynakube/convert_from.go b/pkg/api/v1beta2/dynakube/convert_from.go index a866099c25..6147a99d3f 100644 --- a/pkg/api/v1beta2/dynakube/convert_from.go +++ b/pkg/api/v1beta2/dynakube/convert_from.go @@ -1,7 +1,8 @@ package dynakube import ( - v1beta3 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "sigs.k8s.io/controller-runtime/pkg/conversion" ) @@ -10,7 +11,7 @@ var isEnabledModules = installconfig.GetModules() // ConvertFrom converts from the Hub version (v1beta3) to this version (v1beta3). func (dst *DynaKube) ConvertFrom(srcRaw conversion.Hub) error { - src := srcRaw.(*v1beta3.DynaKube) + src := srcRaw.(*dynakube.DynaKube) dst.fromBase(src) dst.fromOneAgentSpec(src) @@ -21,7 +22,7 @@ func (dst *DynaKube) ConvertFrom(srcRaw conversion.Hub) error { return nil } -func (dst *DynaKube) fromBase(src *v1beta3.DynaKube) { +func (dst *DynaKube) fromBase(src *dynakube.DynaKube) { if src.Annotations == nil { src.Annotations = map[string]string{} } @@ -39,19 +40,19 @@ func (dst *DynaKube) fromBase(src *v1beta3.DynaKube) { dst.Spec.DynatraceApiRequestThreshold = int(src.GetDynatraceApiRequestThreshold()) } -func (dst *DynaKube) fromOneAgentSpec(src *v1beta3.DynaKube) { +func (dst *DynaKube) fromOneAgentSpec(src *dynakube.DynaKube) { dst.Spec.OneAgent.HostGroup = src.Spec.OneAgent.HostGroup switch { - case src.HostMonitoringMode(): + case src.OneAgent().IsHostMonitoringMode(): dst.Spec.OneAgent.HostMonitoring = fromHostInjectSpec(*src.Spec.OneAgent.HostMonitoring) - case src.ClassicFullStackMode(): + case src.OneAgent().IsClassicFullStackMode(): dst.Spec.OneAgent.ClassicFullStack = fromHostInjectSpec(*src.Spec.OneAgent.ClassicFullStack) - case src.CloudNativeFullstackMode(): + case src.OneAgent().IsCloudNativeFullstackMode(): dst.Spec.OneAgent.CloudNativeFullStack = &CloudNativeFullStackSpec{} dst.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec = *fromHostInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec) dst.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec = *fromAppInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec) - case src.ApplicationMonitoringMode(): + case src.OneAgent().IsApplicationMonitoringMode(): dst.Spec.OneAgent.ApplicationMonitoring = &ApplicationMonitoringSpec{} dst.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec = *fromAppInjectSpec(src.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec) dst.Spec.OneAgent.ApplicationMonitoring.Version = src.Spec.OneAgent.ApplicationMonitoring.Version @@ -59,7 +60,7 @@ func (dst *DynaKube) fromOneAgentSpec(src *v1beta3.DynaKube) { } } -func (dst *DynaKube) fromActiveGateSpec(src *v1beta3.DynaKube) { +func (dst *DynaKube) fromActiveGateSpec(src *dynakube.DynaKube) { dst.Spec.ActiveGate.Image = src.Spec.ActiveGate.Image dst.Spec.ActiveGate.PriorityClassName = src.Spec.ActiveGate.PriorityClassName dst.Spec.ActiveGate.TlsSecretName = src.Spec.ActiveGate.TlsSecretName @@ -87,7 +88,7 @@ func (dst *DynaKube) fromActiveGateSpec(src *v1beta3.DynaKube) { } } -func (dst *DynaKube) fromStatus(src *v1beta3.DynaKube) { +func (dst *DynaKube) fromStatus(src *dynakube.DynaKube) { dst.fromOneAgentStatus(*src) dst.fromActiveGateStatus(*src) dst.Status.CodeModules = CodeModulesStatus{ @@ -106,7 +107,7 @@ func (dst *DynaKube) fromStatus(src *v1beta3.DynaKube) { dst.Status.KubernetesClusterName = src.Status.KubernetesClusterName } -func (dst *DynaKube) fromOneAgentStatus(src v1beta3.DynaKube) { +func (dst *DynaKube) fromOneAgentStatus(src dynakube.DynaKube) { dst.Status.OneAgent.Instances = map[string]OneAgentInstance{} // Instance @@ -137,13 +138,13 @@ func (dst *DynaKube) fromOneAgentStatus(src v1beta3.DynaKube) { dst.Status.OneAgent.Healthcheck = src.Status.OneAgent.Healthcheck } -func (dst *DynaKube) fromActiveGateStatus(src v1beta3.DynaKube) { +func (dst *DynaKube) fromActiveGateStatus(src dynakube.DynaKube) { dst.Status.ActiveGate.ConnectionInfoStatus.ConnectionInfoStatus = (ConnectionInfoStatus)(src.Status.ActiveGate.ConnectionInfo) dst.Status.ActiveGate.ServiceIPs = src.Status.ActiveGate.ServiceIPs dst.Status.ActiveGate.VersionStatus = src.Status.ActiveGate.VersionStatus } -func fromHostInjectSpec(src v1beta3.HostInjectSpec) *HostInjectSpec { +func fromHostInjectSpec(src oneagent.HostInjectSpec) *HostInjectSpec { dst := &HostInjectSpec{} dst.AutoUpdate = src.AutoUpdate == nil || *src.AutoUpdate dst.OneAgentResources = src.OneAgentResources @@ -162,7 +163,7 @@ func fromHostInjectSpec(src v1beta3.HostInjectSpec) *HostInjectSpec { return dst } -func fromAppInjectSpec(src v1beta3.AppInjectionSpec) *AppInjectionSpec { +func fromAppInjectSpec(src oneagent.AppInjectionSpec) *AppInjectionSpec { dst := &AppInjectionSpec{} dst.CodeModulesImage = src.CodeModulesImage @@ -172,7 +173,7 @@ func fromAppInjectSpec(src v1beta3.AppInjectionSpec) *AppInjectionSpec { return dst } -func (dst *DynaKube) fromMetadataEnrichment(src *v1beta3.DynaKube) { +func (dst *DynaKube) fromMetadataEnrichment(src *dynakube.DynaKube) { dst.Spec.MetadataEnrichment.Enabled = src.MetadataEnrichmentEnabled() dst.Spec.MetadataEnrichment.NamespaceSelector = src.Spec.MetadataEnrichment.NamespaceSelector } diff --git a/pkg/api/v1beta2/dynakube/convert_from_test.go b/pkg/api/v1beta2/dynakube/convert_from_test.go index 35ed4dbdea..e353be01ec 100644 --- a/pkg/api/v1beta2/dynakube/convert_from_test.go +++ b/pkg/api/v1beta2/dynakube/convert_from_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -119,8 +120,8 @@ func compareBase(t *testing.T, oldDk DynaKube, newDk dynakube.DynaKube) { assert.Equal(t, oldDk.Spec.TrustedCAs, newDk.Spec.TrustedCAs) assert.Equal(t, uint16(oldDk.Spec.DynatraceApiRequestThreshold), *newDk.Spec.DynatraceApiRequestThreshold) //nolint:gosec - if newDk.NeedAppInjection() { - assert.Equal(t, oldDk.OneAgentNamespaceSelector(), newDk.OneAgentNamespaceSelector()) + if newDk.OneAgent().IsAppInjectionNeeded() { + assert.Equal(t, oldDk.OneAgentNamespaceSelector(), newDk.OneAgent().GetNamespaceSelector()) } assert.Equal(t, oldDk.MetadataEnrichmentEnabled(), newDk.MetadataEnrichmentEnabled()) @@ -138,7 +139,7 @@ func compareBase(t *testing.T, oldDk DynaKube, newDk dynakube.DynaKube) { } } -func compareHostInjectSpec(t *testing.T, oldSpec HostInjectSpec, newSpec dynakube.HostInjectSpec) { +func compareHostInjectSpec(t *testing.T, oldSpec HostInjectSpec, newSpec oneagent.HostInjectSpec) { assert.Equal(t, oldSpec.Annotations, newSpec.Annotations) assert.Equal(t, oldSpec.Args, newSpec.Args) assert.Equal(t, oldSpec.AutoUpdate, *newSpec.AutoUpdate) @@ -154,17 +155,17 @@ func compareHostInjectSpec(t *testing.T, oldSpec HostInjectSpec, newSpec dynakub assert.Equal(t, oldSpec.SecCompProfile, newSpec.SecCompProfile) } -func compareAppInjectionSpec(t *testing.T, oldSpec AppInjectionSpec, newSpec dynakube.AppInjectionSpec) { +func compareAppInjectionSpec(t *testing.T, oldSpec AppInjectionSpec, newSpec oneagent.AppInjectionSpec) { assert.Equal(t, oldSpec.CodeModulesImage, newSpec.CodeModulesImage) assert.Equal(t, oldSpec.InitResources, newSpec.InitResources) } -func compareCloudNativeSpec(t *testing.T, oldSpec CloudNativeFullStackSpec, newSpec dynakube.CloudNativeFullStackSpec) { +func compareCloudNativeSpec(t *testing.T, oldSpec CloudNativeFullStackSpec, newSpec oneagent.CloudNativeFullStackSpec) { compareAppInjectionSpec(t, oldSpec.AppInjectionSpec, newSpec.AppInjectionSpec) compareHostInjectSpec(t, oldSpec.HostInjectSpec, newSpec.HostInjectSpec) } -func compareApplicationMonitoringSpec(t *testing.T, oldSpec ApplicationMonitoringSpec, newSpec dynakube.ApplicationMonitoringSpec) { +func compareApplicationMonitoringSpec(t *testing.T, oldSpec ApplicationMonitoringSpec, newSpec oneagent.ApplicationMonitoringSpec) { compareAppInjectionSpec(t, oldSpec.AppInjectionSpec, newSpec.AppInjectionSpec) assert.Equal(t, oldSpec.UseCSIDriver, isEnabledModules.CSIDriver) assert.Equal(t, oldSpec.Version, newSpec.Version) @@ -270,8 +271,8 @@ func getNewDynakubeBase() dynakube.DynaKube { } } -func getNewHostInjectSpec() dynakube.HostInjectSpec { - return dynakube.HostInjectSpec{ +func getNewHostInjectSpec() oneagent.HostInjectSpec { + return oneagent.HostInjectSpec{ Version: "host-inject-version", Image: "host-inject-image", Tolerations: []corev1.Toleration{ @@ -313,8 +314,8 @@ func getNewHostInjectSpec() dynakube.HostInjectSpec { } } -func getNewAppInjectionSpec() dynakube.AppInjectionSpec { - return dynakube.AppInjectionSpec{ +func getNewAppInjectionSpec() oneagent.AppInjectionSpec { + return oneagent.AppInjectionSpec{ InitResources: &corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: *resource.NewScaledQuantity(2, 1)}, @@ -324,15 +325,15 @@ func getNewAppInjectionSpec() dynakube.AppInjectionSpec { } } -func getNewCloudNativeSpec() dynakube.CloudNativeFullStackSpec { - return dynakube.CloudNativeFullStackSpec{ +func getNewCloudNativeSpec() oneagent.CloudNativeFullStackSpec { + return oneagent.CloudNativeFullStackSpec{ AppInjectionSpec: getNewAppInjectionSpec(), HostInjectSpec: getNewHostInjectSpec(), } } -func getNewApplicationMonitoringSpec() dynakube.ApplicationMonitoringSpec { - return dynakube.ApplicationMonitoringSpec{ +func getNewApplicationMonitoringSpec() oneagent.ApplicationMonitoringSpec { + return oneagent.ApplicationMonitoringSpec{ AppInjectionSpec: getNewAppInjectionSpec(), Version: "app-monitoring-version", } @@ -393,7 +394,7 @@ func getNewActiveGateSpec() activegate.Spec { func getNewStatus() dynakube.DynaKubeStatus { return dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ ImageID: "oa-image-id", Version: "oa-version", @@ -401,7 +402,7 @@ func getNewStatus() dynakube.DynaKubeStatus { Source: status.CustomImageVersionSource, LastProbeTimestamp: &testTime, }, - Instances: map[string]dynakube.OneAgentInstance{ + Instances: map[string]oneagent.Instance{ "oa-instance-key-1": { PodName: "oa-instance-pod-1", IPAddress: "oa-instance-ip-1", @@ -415,13 +416,13 @@ func getNewStatus() dynakube.DynaKubeStatus { Healthcheck: ®istryv1.HealthConfig{ Test: []string{"oa-health-check-test"}, }, - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ LastRequest: testTime, TenantUUID: "oa-tenant-uuid", Endpoints: "oa-endpoints", }, - CommunicationHosts: []dynakube.CommunicationHostStatus{ + CommunicationHosts: []oneagent.CommunicationHostStatus{ { Protocol: "oa-protocol-1", Host: "oa-host-1", @@ -444,7 +445,7 @@ func getNewStatus() dynakube.DynaKubeStatus { LastProbeTimestamp: &testTime, }, }, - CodeModules: dynakube.CodeModulesStatus{ + CodeModules: oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ ImageID: "cm-image-id", Version: "cm-version", diff --git a/pkg/api/v1beta2/dynakube/convert_to.go b/pkg/api/v1beta2/dynakube/convert_to.go index 76677a69f2..9000c7b053 100644 --- a/pkg/api/v1beta2/dynakube/convert_to.go +++ b/pkg/api/v1beta2/dynakube/convert_to.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/conversion" ) @@ -72,11 +73,11 @@ func (src *DynaKube) toOneAgentSpec(dst *dynakube.DynaKube) { case src.ClassicFullStackMode(): dst.Spec.OneAgent.ClassicFullStack = toHostInjectSpec(*src.Spec.OneAgent.ClassicFullStack) case src.CloudNativeFullstackMode(): - dst.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} + dst.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} dst.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec = *toHostInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec) dst.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec = *toAppInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec) case src.ApplicationMonitoringMode(): - dst.Spec.OneAgent.ApplicationMonitoring = &dynakube.ApplicationMonitoringSpec{} + dst.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} dst.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec = *toAppInjectSpec(src.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec) dst.Spec.OneAgent.ApplicationMonitoring.Version = src.Spec.OneAgent.ApplicationMonitoring.Version } @@ -113,7 +114,7 @@ func (src *DynaKube) toActiveGateSpec(dst *dynakube.DynaKube) { func (src *DynaKube) toStatus(dst *dynakube.DynaKube) { src.toOneAgentStatus(dst) src.toActiveGateStatus(dst) - dst.Status.CodeModules = dynakube.CodeModulesStatus{ + dst.Status.CodeModules = oneagent.CodeModulesStatus{ VersionStatus: src.Status.CodeModules.VersionStatus, } @@ -130,11 +131,11 @@ func (src *DynaKube) toStatus(dst *dynakube.DynaKube) { } func (src *DynaKube) toOneAgentStatus(dst *dynakube.DynaKube) { - dst.Status.OneAgent.Instances = map[string]dynakube.OneAgentInstance{} + dst.Status.OneAgent.Instances = map[string]oneagent.Instance{} // Instance for key, instance := range src.Status.OneAgent.Instances { - tmp := dynakube.OneAgentInstance{ + tmp := oneagent.Instance{ PodName: instance.PodName, IPAddress: instance.IPAddress, } @@ -147,7 +148,7 @@ func (src *DynaKube) toOneAgentStatus(dst *dynakube.DynaKube) { dst.Status.OneAgent.ConnectionInfoStatus.ConnectionInfo = (communication.ConnectionInfo)(src.Status.OneAgent.ConnectionInfoStatus.ConnectionInfoStatus) for _, host := range src.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts { - tmp := dynakube.CommunicationHostStatus{ + tmp := oneagent.CommunicationHostStatus{ Host: host.Host, Port: host.Port, Protocol: host.Protocol, @@ -166,8 +167,8 @@ func (src *DynaKube) toActiveGateStatus(dst *dynakube.DynaKube) { dst.Status.ActiveGate.VersionStatus = src.Status.ActiveGate.VersionStatus } -func toHostInjectSpec(src HostInjectSpec) *dynakube.HostInjectSpec { - dst := &dynakube.HostInjectSpec{} +func toHostInjectSpec(src HostInjectSpec) *oneagent.HostInjectSpec { + dst := &oneagent.HostInjectSpec{} dst.AutoUpdate = &src.AutoUpdate dst.OneAgentResources = src.OneAgentResources @@ -186,8 +187,8 @@ func toHostInjectSpec(src HostInjectSpec) *dynakube.HostInjectSpec { return dst } -func toAppInjectSpec(src AppInjectionSpec) *dynakube.AppInjectionSpec { - dst := &dynakube.AppInjectionSpec{} +func toAppInjectSpec(src AppInjectionSpec) *oneagent.AppInjectionSpec { + dst := &oneagent.AppInjectionSpec{} dst.CodeModulesImage = src.CodeModulesImage dst.InitResources = src.InitResources diff --git a/pkg/api/v1beta3/dynakube/activegate/props.go b/pkg/api/v1beta3/dynakube/activegate/props.go index d0a47ab444..0bb8daf157 100644 --- a/pkg/api/v1beta3/dynakube/activegate/props.go +++ b/pkg/api/v1beta3/dynakube/activegate/props.go @@ -106,7 +106,7 @@ func (ag *Spec) GetConnectionInfoConfigMapName() string { return ag.name + ConnectionInfoConfigMapSuffix } -// DefaultImage provides the image reference for the ActiveGate from tenant registry. +// GetDefaultImage provides the image reference for the ActiveGate from tenant registry. // Format: repo:tag. func (ag *Spec) GetDefaultImage(version string) string { apiUrlHost := ag.apiUrlHost() diff --git a/pkg/api/v1beta3/dynakube/dynakube_props_test.go b/pkg/api/v1beta3/dynakube/dynakube_props_test.go index 76cdc4cda1..4ccea22b72 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_props_test.go +++ b/pkg/api/v1beta3/dynakube/dynakube_props_test.go @@ -27,8 +27,6 @@ import ( "k8s.io/utils/ptr" ) -const testAPIURL = "http://test-endpoint/api" - func TestTokens(t *testing.T) { testName := "test-name" testValue := "test-value" diff --git a/pkg/api/v1beta3/dynakube/dynakube_status.go b/pkg/api/v1beta3/dynakube/dynakube_status.go index 4a36247b7d..2cb1259c5f 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_status.go +++ b/pkg/api/v1beta3/dynakube/dynakube_status.go @@ -5,11 +5,10 @@ import ( "fmt" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" - containerv1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/pkg/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -21,13 +20,13 @@ import ( type DynaKubeStatus struct { //nolint:revive // Observed state of OneAgent - OneAgent OneAgentStatus `json:"oneAgent,omitempty"` + OneAgent oneagent.Status `json:"oneAgent,omitempty"` // Observed state of ActiveGate ActiveGate activegate.Status `json:"activeGate,omitempty"` // Observed state of Code Modules - CodeModules CodeModulesStatus `json:"codeModules,omitempty"` + CodeModules oneagent.CodeModulesStatus `json:"codeModules,omitempty"` // Observed state of Metadata-Enrichment MetadataEnrichment MetadataEnrichmentStatus `json:"metadataEnrichment,omitempty"` @@ -74,56 +73,6 @@ func GetCacheValidMessage(functionName string, lastRequestTimestamp metav1.Time, int(remaining.Minutes())) } -type OneAgentConnectionInfoStatus struct { - // Information for communicating with the tenant - communication.ConnectionInfo `json:",inline"` - - // List of communication hosts - CommunicationHosts []CommunicationHostStatus `json:"communicationHosts,omitempty"` -} - -type CommunicationHostStatus struct { - // Connection protocol - Protocol string `json:"protocol,omitempty"` - - // Host domain - Host string `json:"host,omitempty"` - - // Connection port - Port uint32 `json:"port,omitempty"` -} - -type CodeModulesStatus struct { - status.VersionStatus `json:",inline"` -} - -type OneAgentStatus struct { - status.VersionStatus `json:",inline"` - - // List of deployed OneAgent instances - Instances map[string]OneAgentInstance `json:"instances,omitempty"` - - // Time of the last instance status update - LastInstanceStatusUpdate *metav1.Time `json:"lastInstanceStatusUpdate,omitempty"` - - // Commands used for OneAgent's readiness probe - // +kubebuilder:validation:Type=object - // +kubebuilder:validation:Schemaless - // +kubebuilder:pruning:PreserveUnknownFields - Healthcheck *containerv1.HealthConfig `json:"healthcheck,omitempty"` - - // Information about OneAgent's connections - ConnectionInfoStatus OneAgentConnectionInfoStatus `json:"connectionInfoStatus,omitempty"` -} - -type OneAgentInstance struct { - // Name of the OneAgent pod - PodName string `json:"podName,omitempty"` - - // IP address of the pod - IPAddress string `json:"ipAddress,omitempty"` -} - type EnrichmentRuleType string const ( diff --git a/pkg/api/v1beta3/dynakube/dynakube_types.go b/pkg/api/v1beta3/dynakube/dynakube_types.go index ac62f83857..6db9fe3c6f 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_types.go +++ b/pkg/api/v1beta3/dynakube/dynakube_types.go @@ -9,6 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -94,7 +95,7 @@ type DynaKubeSpec struct { //nolint:revive // General configuration about OneAgent instances. // You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text" - OneAgent OneAgentSpec `json:"oneAgent,omitempty"` + OneAgent oneagent.Spec `json:"oneAgent,omitempty"` // Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. // For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace.com/support/help/get-started/monitoring-environment/environment-id). diff --git a/pkg/api/v1beta3/dynakube/feature_flags_test.go b/pkg/api/v1beta3/dynakube/feature_flags_test.go index dabab4eea2..6d2692cfbb 100644 --- a/pkg/api/v1beta3/dynakube/feature_flags_test.go +++ b/pkg/api/v1beta3/dynakube/feature_flags_test.go @@ -289,3 +289,33 @@ func TestAgentInitialConnectRetry(t *testing.T) { require.Equal(t, 5, initialRetry) }) } + +func TestIsOneAgentPrivileged(t *testing.T) { + t.Run("is false by default", func(t *testing.T) { + dk := DynaKube{} + + assert.False(t, dk.FeatureOneAgentPrivileged()) + }) + t.Run("is true when annotation is set to true", func(t *testing.T) { + dk := DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + AnnotationFeatureRunOneAgentContainerPrivileged: "true", + }, + }, + } + + assert.True(t, dk.FeatureOneAgentPrivileged()) + }) + t.Run("is false when annotation is set to false", func(t *testing.T) { + dk := DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + AnnotationFeatureRunOneAgentContainerPrivileged: "false", + }, + }, + } + + assert.False(t, dk.FeatureOneAgentPrivileged()) + }) +} diff --git a/pkg/api/v1beta3/dynakube/logmonitoring/props.go b/pkg/api/v1beta3/dynakube/logmonitoring/props.go index 9716b9d84d..3b014065c2 100644 --- a/pkg/api/v1beta3/dynakube/logmonitoring/props.go +++ b/pkg/api/v1beta3/dynakube/logmonitoring/props.go @@ -24,6 +24,14 @@ func (lm *LogMonitoring) IsStandalone() bool { return lm.IsEnabled() && !lm.enabledDependencies.hostAgents } +func (lm *LogMonitoring) GetNodeSelector() map[string]string { + if lm.IsStandalone() && lm.TemplateSpec != nil { + return lm.TemplateSpec.NodeSelector + } + + return nil +} + // Template is a nil-safe way to access the underlying TemplateSpec. func (lm *LogMonitoring) Template() TemplateSpec { if lm.TemplateSpec == nil { diff --git a/pkg/api/v1beta3/dynakube/logmonitoring_props.go b/pkg/api/v1beta3/dynakube/logmonitoring_props.go index c7fc6df26d..af3c8cf036 100644 --- a/pkg/api/v1beta3/dynakube/logmonitoring_props.go +++ b/pkg/api/v1beta3/dynakube/logmonitoring_props.go @@ -10,7 +10,7 @@ func (dk *DynaKube) LogMonitoring() *logmonitoring.LogMonitoring { TemplateSpec: dk.Spec.Templates.LogMonitoring, } lm.SetName(dk.Name) - lm.SetHostAgentDependency(dk.NeedsOneAgent()) + lm.SetHostAgentDependency(dk.OneAgent().IsDaemonsetRequired()) return lm } diff --git a/pkg/api/v1beta3/dynakube/oneagent/props.go b/pkg/api/v1beta3/dynakube/oneagent/props.go new file mode 100644 index 0000000000..38bac7ca34 --- /dev/null +++ b/pkg/api/v1beta3/dynakube/oneagent/props.go @@ -0,0 +1,312 @@ +package oneagent + +import ( + "fmt" + "strings" + + "github.com/Dynatrace/dynatrace-operator/pkg/api" + "github.com/Dynatrace/dynatrace-operator/pkg/util/dtversion" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + OneAgentTenantSecretSuffix = "-oneagent-tenant-secret" + OneAgentConnectionInfoConfigMapSuffix = "-oneagent-connection-info" + PodNameOsAgent = "oneagent" + DefaultOneAgentImageRegistrySubPath = "/linux/oneagent" +) + +func NewOneAgent(spec *Spec, status *Status, codeModulesStatus *CodeModulesStatus, //nolint:revive + name, apiUrlHost string, + featureOneAgentPrivileged, featureOneAgentSkipLivenessProbe bool) *OneAgent { + return &OneAgent{ + Spec: spec, + Status: status, + CodeModulesStatus: codeModulesStatus, + + name: name, + apiUrlHost: apiUrlHost, + + featureOneAgentPrivileged: featureOneAgentPrivileged, + featureOneAgentSkipLivenessProbe: featureOneAgentSkipLivenessProbe, + } +} + +func (oa *OneAgent) IsCSIAvailable() bool { + return installconfig.GetModules().CSIDriver +} + +// IsApplicationMonitoringMode returns true when application only section is used. +func (oa *OneAgent) IsApplicationMonitoringMode() bool { + return oa.ApplicationMonitoring != nil +} + +// IsCloudNativeFullstackMode returns true when cloud native fullstack section is used. +func (oa *OneAgent) IsCloudNativeFullstackMode() bool { + return oa.CloudNativeFullStack != nil +} + +// IsHostMonitoringMode returns true when host monitoring section is used. +func (oa *OneAgent) IsHostMonitoringMode() bool { + return oa.HostMonitoring != nil +} + +// IsClassicFullStackMode returns true when classic fullstack section is used. +func (oa *OneAgent) IsClassicFullStackMode() bool { + return oa.ClassicFullStack != nil +} + +// IsDaemonsetRequired returns true when a feature requires OneAgent instances. +func (oa *OneAgent) IsDaemonsetRequired() bool { + return oa.IsClassicFullStackMode() || oa.IsCloudNativeFullstackMode() || oa.IsHostMonitoringMode() +} + +func (oa *OneAgent) GetDaemonsetName() string { + return fmt.Sprintf("%s-%s", oa.name, PodNameOsAgent) +} + +func (oa *OneAgent) IsPrivilegedNeeded() bool { + return oa.featureOneAgentPrivileged +} + +func (oa *OneAgent) IsReadinessProbeNeeded() bool { + return oa.Healthcheck != nil +} + +func (oa *OneAgent) IsLivenessProbeNeeded() bool { + return oa.Healthcheck != nil && !oa.featureOneAgentSkipLivenessProbe +} + +// IsAutoUpdateEnabled returns true if the Operator should update OneAgent instances automatically. +func (oa *OneAgent) IsAutoUpdateEnabled() bool { + switch { + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.AutoUpdate == nil || *oa.CloudNativeFullStack.AutoUpdate + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.AutoUpdate == nil || *oa.HostMonitoring.AutoUpdate + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.AutoUpdate == nil || *oa.ClassicFullStack.AutoUpdate + default: + return false + } +} + +// GetTenantSecret returns the name of the secret containing the token for the OneAgent. +func (oa *OneAgent) GetTenantSecret() string { + return oa.name + OneAgentTenantSecretSuffix +} + +func (oa *OneAgent) GetConnectionInfoConfigMapName() string { + return oa.name + OneAgentConnectionInfoConfigMapSuffix +} + +func (oa *OneAgent) IsReadOnlyOneAgentsMode() bool { + return oa.IsCloudNativeFullstackMode() || (oa.IsHostMonitoringMode() && oa.IsCSIAvailable()) +} + +func (oa *OneAgent) IsAppInjectionNeeded() bool { + return oa.IsCloudNativeFullstackMode() || oa.IsApplicationMonitoringMode() +} + +func (oa *OneAgent) GetInitResources() *corev1.ResourceRequirements { + if oa.IsApplicationMonitoringMode() { + return oa.ApplicationMonitoring.InitResources + } else if oa.IsCloudNativeFullstackMode() { + return oa.CloudNativeFullStack.InitResources + } + + return nil +} + +func (oa *OneAgent) GetNamespaceSelector() *metav1.LabelSelector { + switch { + case oa.IsCloudNativeFullstackMode(): + return &oa.CloudNativeFullStack.NamespaceSelector + case oa.IsApplicationMonitoringMode(): + return &oa.ApplicationMonitoring.NamespaceSelector + } + + return nil +} + +func (oa *OneAgent) GetSecCompProfile() string { + switch { + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.SecCompProfile + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.SecCompProfile + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.SecCompProfile + default: + return "" + } +} + +func (oa *OneAgent) GetNodeSelector(fallbackNodeSelector map[string]string) map[string]string { + switch { + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.NodeSelector + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.NodeSelector + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.NodeSelector + } + + return fallbackNodeSelector +} + +// GetImage provides the image reference set in Status for the OneAgent. +// Format: repo@sha256:digest. +func (oa *OneAgent) GetImage() string { + return oa.Status.ImageID +} + +// GetVersion provides version set in Status for the OneAgent. +func (oa *OneAgent) GetVersion() string { + return oa.Status.Version +} + +// GetCustomVersion provides the version for the OneAgent provided in the Spec. +func (oa *OneAgent) GetCustomVersion() string { + switch { + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.Version + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.Version + case oa.IsApplicationMonitoringMode(): + return oa.ApplicationMonitoring.Version + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.Version + } + + return "" +} + +// GetCustomImage provides the image reference for the OneAgent provided in the Spec. +func (oa *OneAgent) GetCustomImage() string { + switch { + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.Image + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.Image + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.Image + } + + return "" +} + +// GetDefaultImage provides the image reference for the OneAgent from tenant registry. +func (oa *OneAgent) GetDefaultImage(version string) string { + if oa.apiUrlHost == "" { + return "" + } + + truncatedVersion := dtversion.ToImageTag(version) + tag := truncatedVersion + + if !strings.Contains(tag, api.RawTag) { + tag += "-" + api.RawTag + } + + return oa.apiUrlHost + DefaultOneAgentImageRegistrySubPath + ":" + tag +} + +func (oa *OneAgent) GetHostGroup() string { + if oa.HostGroup != "" { + return oa.HostGroup + } + + return oa.GetHostGroupAsParam() +} + +func (oa *OneAgent) GetHostGroupAsParam() string { + var hostGroup string + + var args []string + + switch { + case oa.IsCloudNativeFullstackMode() && oa.CloudNativeFullStack.Args != nil: + args = oa.CloudNativeFullStack.Args + case oa.IsClassicFullStackMode() && oa.ClassicFullStack.Args != nil: + args = oa.ClassicFullStack.Args + case oa.IsHostMonitoringMode() && oa.HostMonitoring.Args != nil: + args = oa.HostMonitoring.Args + } + + for _, arg := range args { + key, value := splitArg(arg) + if key == "--set-host-group" { + hostGroup = value + + break + } + } + + return hostGroup +} + +func splitArg(arg string) (key, value string) { + split := strings.Split(arg, "=") + + const expectedLen = 2 + + if len(split) != expectedLen { + return + } + + key = split[0] + value = split[1] + + return +} + +func (oa *OneAgent) IsCommunicationRouteClear() bool { + return len(oa.ConnectionInfoStatus.CommunicationHosts) > 0 +} + +func (oa *OneAgent) GetEnvironment() []corev1.EnvVar { + switch { + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.Env + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.Env + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.Env + } + + return []corev1.EnvVar{} +} + +func (oa *OneAgent) GetEndpoints() string { + return oa.ConnectionInfoStatus.Endpoints +} + +// GetCustomCodeModulesImage provides the image reference for the CodeModules provided in the Spec. +func (oa *OneAgent) GetCustomCodeModulesImage() string { + if oa.IsCloudNativeFullstackMode() { + return oa.CloudNativeFullStack.CodeModulesImage + } else if oa.IsApplicationMonitoringMode() && oa.IsCSIAvailable() { + return oa.ApplicationMonitoring.CodeModulesImage + } + + return "" +} + +// GetCustomCodeModulesVersion provides the version for the CodeModules provided in the Spec. +func (oa *OneAgent) GetCustomCodeModulesVersion() string { + return oa.GetCustomVersion() +} + +// GetCodeModulesVersion provides version set in Status for the CodeModules. +func (oa *OneAgent) GetCodeModulesVersion() string { + return oa.CodeModulesStatus.Version +} + +// GetCodeModulesImage provides the image reference set in Status for the CodeModules. +// Format: repo@sha256:digest. +func (oa *OneAgent) GetCodeModulesImage() string { + return oa.CodeModulesStatus.ImageID +} diff --git a/pkg/api/v1beta3/dynakube/oneagent/props_test.go b/pkg/api/v1beta3/dynakube/oneagent/props_test.go new file mode 100644 index 0000000000..6dd51a8505 --- /dev/null +++ b/pkg/api/v1beta3/dynakube/oneagent/props_test.go @@ -0,0 +1,260 @@ +/* +Copyright 2021 Dynatrace LLC. + +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. +*/ + +package oneagent + +import ( + "net/url" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" +) + +const testAPIURL = "http://test-endpoint/api" + +func TestNeedsReadonlyOneagent(t *testing.T) { + t.Run("cloud native fullstack always use readonly host agent", func(t *testing.T) { + oneagent := OneAgent{ + Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{}, + }, + } + assert.True(t, oneagent.IsReadOnlyOneAgentsMode()) + }) + + t.Run("host monitoring with readonly host agent", func(t *testing.T) { + oneAgent := OneAgent{ + Spec: &Spec{ + HostMonitoring: &HostInjectSpec{}, + }, + } + assert.True(t, oneAgent.IsReadOnlyOneAgentsMode()) + }) + + t.Run("host monitoring without readonly host agent", func(t *testing.T) { + setupDisabledCSIEnv(t) + + oneAgent := OneAgent{ + Spec: &Spec{ + HostMonitoring: &HostInjectSpec{}, + }, + } + assert.False(t, oneAgent.IsReadOnlyOneAgentsMode()) + }) +} + +func TestDefaultOneAgentImage(t *testing.T) { + t.Run("OneAgentImage with no API URL", func(t *testing.T) { + oneAgent := OneAgent{} + assert.Equal(t, "", oneAgent.GetDefaultImage("")) + }) + + t.Run("OneAgentImage adds raw postfix", func(t *testing.T) { + hostUrl, _ := url.Parse(testAPIURL) + oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false) + assert.Equal(t, "test-endpoint/linux/oneagent:1.234.5-raw", oneAgent.GetDefaultImage("1.234.5")) + }) + + t.Run("OneAgentImage doesn't add 'raw' postfix if present", func(t *testing.T) { + hostUrl, _ := url.Parse(testAPIURL) + oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false) + assert.Equal(t, "test-endpoint/linux/oneagent:1.234.5-raw", oneAgent.GetDefaultImage("1.234.5-raw")) + }) + + t.Run("OneAgentImage with custom version truncates build date", func(t *testing.T) { + version := "1.239.14.20220325-164521" + expectedImage := "test-endpoint/linux/oneagent:1.239.14-raw" + hostUrl, _ := url.Parse(testAPIURL) + oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false) + assert.Equal(t, expectedImage, oneAgent.GetDefaultImage(version)) + }) +} + +func TestCustomOneAgentImage(t *testing.T) { + t.Run("OneAgentImage with custom image", func(t *testing.T) { + customImg := "registry/my/oneagent:latest" + oneAgent := OneAgent{Spec: &Spec{ClassicFullStack: &HostInjectSpec{Image: customImg}}} + assert.Equal(t, customImg, oneAgent.GetCustomImage()) + }) + + t.Run("OneAgentImage with no custom image", func(t *testing.T) { + oneAgent := OneAgent{Spec: &Spec{ClassicFullStack: &HostInjectSpec{}}} + assert.Equal(t, "", oneAgent.GetCustomImage()) + }) +} + +func TestOneAgentDaemonsetName(t *testing.T) { + oneAgent := OneAgent{name: "test-name"} + assert.Equal(t, "test-name-oneagent", oneAgent.GetDaemonsetName()) +} + +func TestCodeModulesVersion(t *testing.T) { + testVersion := "1.2.3" + + t.Run("use status", func(t *testing.T) { + codeModulesStatus := &CodeModulesStatus{VersionStatus: status.VersionStatus{Version: testVersion}} + oneAgent := NewOneAgent(&Spec{}, &Status{}, codeModulesStatus, "", "", false, false) + version := oneAgent.GetCodeModulesVersion() + assert.Equal(t, testVersion, version) + }) + t.Run("use version ", func(t *testing.T) { + codeModulesStatus := &CodeModulesStatus{VersionStatus: status.VersionStatus{Version: "other"}} + oneAgent := NewOneAgent(&Spec{ + ApplicationMonitoring: &ApplicationMonitoringSpec{Version: testVersion}, + }, &Status{}, codeModulesStatus, "", "", false, false) + version := oneAgent.GetCustomCodeModulesVersion() + + assert.Equal(t, testVersion, version) + }) +} + +func TestGetOneAgentEnvironment(t *testing.T) { + t.Run("get environment from classicFullstack", func(t *testing.T) { + oneAgent := OneAgent{ + Spec: &Spec{ + ClassicFullStack: &HostInjectSpec{ + Env: []corev1.EnvVar{ + { + Name: "classicFullstack", + Value: "true", + }, + }, + }, + }, + } + env := oneAgent.GetEnvironment() + + require.Len(t, env, 1) + assert.Equal(t, "classicFullstack", env[0].Name) + }) + + t.Run("get environment from hostMonitoring", func(t *testing.T) { + oneAgent := OneAgent{ + Spec: &Spec{ + HostMonitoring: &HostInjectSpec{ + Env: []corev1.EnvVar{ + { + Name: "hostMonitoring", + Value: "true", + }, + }, + }, + }, + } + env := oneAgent.GetEnvironment() + + require.Len(t, env, 1) + assert.Equal(t, "hostMonitoring", env[0].Name) + }) + + t.Run("get environment from cloudNative", func(t *testing.T) { + oneAgent := OneAgent{ + Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Env: []corev1.EnvVar{ + { + Name: "cloudNative", + Value: "true", + }, + }, + }, + }, + }, + } + env := oneAgent.GetEnvironment() + + require.Len(t, env, 1) + assert.Equal(t, "cloudNative", env[0].Name) + }) + + t.Run("get environment from applicationMonitoring", func(t *testing.T) { + oneAgent := OneAgent{Spec: &Spec{ + ApplicationMonitoring: &ApplicationMonitoringSpec{}, + }} + env := oneAgent.GetEnvironment() + + require.NotNil(t, env) + assert.Empty(t, env) + }) + + t.Run("get environment from unconfigured dynakube", func(t *testing.T) { + oneAgent := OneAgent{Spec: &Spec{}} + env := oneAgent.GetEnvironment() + + require.NotNil(t, env) + assert.Empty(t, env) + }) +} + +func TestOneAgentHostGroup(t *testing.T) { + t.Run("get host group from cloudNativeFullstack.args", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-group=arg", + }, + }, + }, + }, + } + hostGroup := dk.GetHostGroup() + assert.Equal(t, "arg", hostGroup) + }) + + t.Run("get host group from oneagent.hostGroup", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + HostGroup: "field", + }, + } + hostGroup := dk.GetHostGroup() + assert.Equal(t, "field", hostGroup) + }) + + t.Run("get host group if both methods used", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-group=arg", + }, + }, + }, + HostGroup: "field", + }, + } + hostGroup := dk.GetHostGroup() + assert.Equal(t, "field", hostGroup) + }) +} + +func setupDisabledCSIEnv(t *testing.T) { + t.Helper() + installconfig.SetModulesOverride(t, installconfig.Modules{ + CSIDriver: false, + ActiveGate: true, + OneAgent: true, + Extensions: true, + LogMonitoring: true, + EdgeConnect: true, + Supportability: true, + }) +} diff --git a/pkg/api/v1beta3/dynakube/oneagent_types.go b/pkg/api/v1beta3/dynakube/oneagent/spec.go similarity index 94% rename from pkg/api/v1beta3/dynakube/oneagent_types.go rename to pkg/api/v1beta3/dynakube/oneagent/spec.go index c7a7fb727b..eb2c78fe4c 100644 --- a/pkg/api/v1beta3/dynakube/oneagent_types.go +++ b/pkg/api/v1beta3/dynakube/oneagent/spec.go @@ -1,13 +1,27 @@ -package dynakube +package oneagent import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -type OneAgentMode string +type OneAgent struct { + *Spec + *Status + *CodeModulesStatus -type OneAgentSpec struct { + name string + apiUrlHost string + + featureOneAgentPrivileged bool + featureOneAgentSkipLivenessProbe bool +} + +type Mode string + +// +kubebuilder:object:generate=true +type Spec struct { // Has a single OneAgent per node via DaemonSet. // Injection is performed via the same OneAgent DaemonSet. // +nullable @@ -35,11 +49,13 @@ type OneAgentSpec struct { HostGroup string `json:"hostGroup,omitempty"` } +// +kubebuilder:object:generate=true type CloudNativeFullStackSpec struct { HostInjectSpec `json:",inline"` AppInjectionSpec `json:",inline"` } +// +kubebuilder:object:generate=true type HostInjectSpec struct { // Add custom OneAgent annotations. @@ -113,6 +129,7 @@ type HostInjectSpec struct { Args []string `json:"args,omitempty"` } +// +kubebuilder:object:generate=true type ApplicationMonitoringSpec struct { // Use a specific OneAgent CodeModule version. Defaults to the latest version from the Dynatrace cluster. @@ -123,6 +140,7 @@ type ApplicationMonitoringSpec struct { AppInjectionSpec `json:",inline"` } +// +kubebuilder:object:generate=true type AppInjectionSpec struct { // Define resources requests and limits for the initContainer. For details, see Managing resources for containers // (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). @@ -140,3 +158,8 @@ type AppInjectionSpec struct { // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Namespace Selector",order=17,xDescriptors="urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Namespace" NamespaceSelector metav1.LabelSelector `json:"namespaceSelector,omitempty"` } + +// +kubebuilder:object:generate=true +type CodeModulesStatus struct { + status.VersionStatus `json:",inline"` +} diff --git a/pkg/api/v1beta3/dynakube/oneagent/status.go b/pkg/api/v1beta3/dynakube/oneagent/status.go new file mode 100644 index 0000000000..b1a9427bdb --- /dev/null +++ b/pkg/api/v1beta3/dynakube/oneagent/status.go @@ -0,0 +1,58 @@ +package oneagent + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + containerv1 "github.com/google/go-containerregistry/pkg/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +kubebuilder:object:generate=true +type Status struct { + status.VersionStatus `json:",inline"` + + // List of deployed OneAgent instances + Instances map[string]Instance `json:"instances,omitempty"` + + // Time of the last instance status update + LastInstanceStatusUpdate *metav1.Time `json:"lastInstanceStatusUpdate,omitempty"` + + // Commands used for OneAgent's readiness probe + // +kubebuilder:validation:Type=object + // +kubebuilder:validation:Schemaless + // +kubebuilder:pruning:PreserveUnknownFields + Healthcheck *containerv1.HealthConfig `json:"healthcheck,omitempty"` + + // Information about OneAgent's connections + ConnectionInfoStatus ConnectionInfoStatus `json:"connectionInfoStatus,omitempty"` +} + +// +kubebuilder:object:generate=true +type Instance struct { + // Name of the OneAgent pod + PodName string `json:"podName,omitempty"` + + // IP address of the pod + IPAddress string `json:"ipAddress,omitempty"` +} + +// +kubebuilder:object:generate=true +type ConnectionInfoStatus struct { + // Information for communicating with the tenant + communication.ConnectionInfo `json:",inline"` + + // List of communication hosts + CommunicationHosts []CommunicationHostStatus `json:"communicationHosts,omitempty"` +} + +// +kubebuilder:object:generate=true +type CommunicationHostStatus struct { + // Connection protocol + Protocol string `json:"protocol,omitempty"` + + // Host domain + Host string `json:"host,omitempty"` + + // Connection port + Port uint32 `json:"port,omitempty"` +} diff --git a/pkg/api/v1beta3/dynakube/oneagent/zz_generated.deepcopy.go b/pkg/api/v1beta3/dynakube/oneagent/zz_generated.deepcopy.go new file mode 100644 index 0000000000..a2878735cc --- /dev/null +++ b/pkg/api/v1beta3/dynakube/oneagent/zz_generated.deepcopy.go @@ -0,0 +1,274 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package oneagent + +import ( + pkgv1 "github.com/google/go-containerregistry/pkg/v1" + "k8s.io/api/core/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AppInjectionSpec) DeepCopyInto(out *AppInjectionSpec) { + *out = *in + if in.InitResources != nil { + in, out := &in.InitResources, &out.InitResources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + in.NamespaceSelector.DeepCopyInto(&out.NamespaceSelector) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppInjectionSpec. +func (in *AppInjectionSpec) DeepCopy() *AppInjectionSpec { + if in == nil { + return nil + } + out := new(AppInjectionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationMonitoringSpec) DeepCopyInto(out *ApplicationMonitoringSpec) { + *out = *in + in.AppInjectionSpec.DeepCopyInto(&out.AppInjectionSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationMonitoringSpec. +func (in *ApplicationMonitoringSpec) DeepCopy() *ApplicationMonitoringSpec { + if in == nil { + return nil + } + out := new(ApplicationMonitoringSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CloudNativeFullStackSpec) DeepCopyInto(out *CloudNativeFullStackSpec) { + *out = *in + in.HostInjectSpec.DeepCopyInto(&out.HostInjectSpec) + in.AppInjectionSpec.DeepCopyInto(&out.AppInjectionSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudNativeFullStackSpec. +func (in *CloudNativeFullStackSpec) DeepCopy() *CloudNativeFullStackSpec { + if in == nil { + return nil + } + out := new(CloudNativeFullStackSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CodeModulesStatus) DeepCopyInto(out *CodeModulesStatus) { + *out = *in + in.VersionStatus.DeepCopyInto(&out.VersionStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CodeModulesStatus. +func (in *CodeModulesStatus) DeepCopy() *CodeModulesStatus { + if in == nil { + return nil + } + out := new(CodeModulesStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommunicationHostStatus) DeepCopyInto(out *CommunicationHostStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommunicationHostStatus. +func (in *CommunicationHostStatus) DeepCopy() *CommunicationHostStatus { + if in == nil { + return nil + } + out := new(CommunicationHostStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConnectionInfoStatus) DeepCopyInto(out *ConnectionInfoStatus) { + *out = *in + in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo) + if in.CommunicationHosts != nil { + in, out := &in.CommunicationHosts, &out.CommunicationHosts + *out = make([]CommunicationHostStatus, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectionInfoStatus. +func (in *ConnectionInfoStatus) DeepCopy() *ConnectionInfoStatus { + if in == nil { + return nil + } + out := new(ConnectionInfoStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HostInjectSpec) DeepCopyInto(out *HostInjectSpec) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.AutoUpdate != nil { + in, out := &in.AutoUpdate, &out.AutoUpdate + *out = new(bool) + **out = **in + } + in.OneAgentResources.DeepCopyInto(&out.OneAgentResources) + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostInjectSpec. +func (in *HostInjectSpec) DeepCopy() *HostInjectSpec { + if in == nil { + return nil + } + out := new(HostInjectSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Instance) DeepCopyInto(out *Instance) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Instance. +func (in *Instance) DeepCopy() *Instance { + if in == nil { + return nil + } + out := new(Instance) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Spec) DeepCopyInto(out *Spec) { + *out = *in + if in.ClassicFullStack != nil { + in, out := &in.ClassicFullStack, &out.ClassicFullStack + *out = new(HostInjectSpec) + (*in).DeepCopyInto(*out) + } + if in.CloudNativeFullStack != nil { + in, out := &in.CloudNativeFullStack, &out.CloudNativeFullStack + *out = new(CloudNativeFullStackSpec) + (*in).DeepCopyInto(*out) + } + if in.ApplicationMonitoring != nil { + in, out := &in.ApplicationMonitoring, &out.ApplicationMonitoring + *out = new(ApplicationMonitoringSpec) + (*in).DeepCopyInto(*out) + } + if in.HostMonitoring != nil { + in, out := &in.HostMonitoring, &out.HostMonitoring + *out = new(HostInjectSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. +func (in *Spec) DeepCopy() *Spec { + if in == nil { + return nil + } + out := new(Spec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in + in.VersionStatus.DeepCopyInto(&out.VersionStatus) + if in.Instances != nil { + in, out := &in.Instances, &out.Instances + *out = make(map[string]Instance, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.LastInstanceStatusUpdate != nil { + in, out := &in.LastInstanceStatusUpdate, &out.LastInstanceStatusUpdate + *out = (*in).DeepCopy() + } + if in.Healthcheck != nil { + in, out := &in.Healthcheck, &out.Healthcheck + *out = new(pkgv1.HealthConfig) + (*in).DeepCopyInto(*out) + } + in.ConnectionInfoStatus.DeepCopyInto(&out.ConnectionInfoStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/api/v1beta3/dynakube/oneagent_props.go b/pkg/api/v1beta3/dynakube/oneagent_props.go index 75ee227a4f..dd69c90bbd 100644 --- a/pkg/api/v1beta3/dynakube/oneagent_props.go +++ b/pkg/api/v1beta3/dynakube/oneagent_props.go @@ -1,299 +1,18 @@ package dynakube import ( - "fmt" - "strings" - - "github.com/Dynatrace/dynatrace-operator/pkg/api" - "github.com/Dynatrace/dynatrace-operator/pkg/util/dtversion" - "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - OneAgentTenantSecretSuffix = "-oneagent-tenant-secret" - OneAgentConnectionInfoConfigMapSuffix = "-oneagent-connection-info" - PodNameOsAgent = "oneagent" - DefaultOneAgentImageRegistrySubPath = "/linux/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" ) -func (dk *DynaKube) IsCSIAvailable() bool { - return installconfig.GetModules().CSIDriver -} - -// ApplicationMonitoringMode returns true when application only section is used. -func (dk *DynaKube) ApplicationMonitoringMode() bool { - return dk.Spec.OneAgent != OneAgentSpec{} && dk.Spec.OneAgent.ApplicationMonitoring != nil -} - -// CloudNativeFullstackMode returns true when cloud native fullstack section is used. -func (dk *DynaKube) CloudNativeFullstackMode() bool { - return dk.Spec.OneAgent != OneAgentSpec{} && dk.Spec.OneAgent.CloudNativeFullStack != nil -} - -// HostMonitoringMode returns true when host monitoring section is used. -func (dk *DynaKube) HostMonitoringMode() bool { - return dk.Spec.OneAgent != OneAgentSpec{} && dk.Spec.OneAgent.HostMonitoring != nil -} - -// ClassicFullStackMode returns true when classic fullstack section is used. -func (dk *DynaKube) ClassicFullStackMode() bool { - return dk.Spec.OneAgent != OneAgentSpec{} && dk.Spec.OneAgent.ClassicFullStack != nil -} - -// NeedsOneAgent returns true when a feature requires OneAgent instances. -func (dk *DynaKube) NeedsOneAgent() bool { - return dk.ClassicFullStackMode() || dk.CloudNativeFullstackMode() || dk.HostMonitoringMode() -} - -func (dk *DynaKube) OneAgentDaemonsetName() string { - return fmt.Sprintf("%s-%s", dk.Name, PodNameOsAgent) -} - -func (dk *DynaKube) NeedsOneAgentPrivileged() bool { - return dk.FeatureOneAgentPrivileged() -} - -func (dk *DynaKube) NeedsOneAgentReadinessProbe() bool { - return dk.Status.OneAgent.Healthcheck != nil -} - -func (dk *DynaKube) NeedsOneAgentLivenessProbe() bool { - return dk.Status.OneAgent.Healthcheck != nil && !dk.FeatureOneAgentSkipLivenessProbe() -} - -// ShouldAutoUpdateOneAgent returns true if the Operator should update OneAgent instances automatically. -func (dk *DynaKube) ShouldAutoUpdateOneAgent() bool { - switch { - case dk.CloudNativeFullstackMode(): - return dk.Spec.OneAgent.CloudNativeFullStack.AutoUpdate == nil || *dk.Spec.OneAgent.CloudNativeFullStack.AutoUpdate - case dk.HostMonitoringMode(): - return dk.Spec.OneAgent.HostMonitoring.AutoUpdate == nil || *dk.Spec.OneAgent.HostMonitoring.AutoUpdate - case dk.ClassicFullStackMode(): - return dk.Spec.OneAgent.ClassicFullStack.AutoUpdate == nil || *dk.Spec.OneAgent.ClassicFullStack.AutoUpdate - default: - return false - } -} - -// OneagentTenantSecret returns the name of the secret containing the token for the OneAgent. -func (dk *DynaKube) OneagentTenantSecret() string { - return dk.Name + OneAgentTenantSecretSuffix -} - -func (dk *DynaKube) OneAgentConnectionInfoConfigMapName() string { - return dk.Name + OneAgentConnectionInfoConfigMapSuffix -} - -func (dk *DynaKube) UseReadOnlyOneAgents() bool { - return dk.CloudNativeFullstackMode() || (dk.HostMonitoringMode() && dk.IsCSIAvailable()) -} - -func (dk *DynaKube) NeedAppInjection() bool { - return dk.CloudNativeFullstackMode() || dk.ApplicationMonitoringMode() -} - -func (dk *DynaKube) InitResources() *corev1.ResourceRequirements { - if dk.ApplicationMonitoringMode() { - return dk.Spec.OneAgent.ApplicationMonitoring.InitResources - } else if dk.CloudNativeFullstackMode() { - return dk.Spec.OneAgent.CloudNativeFullStack.InitResources - } - - return nil -} - -func (dk *DynaKube) OneAgentNamespaceSelector() *metav1.LabelSelector { - switch { - case dk.CloudNativeFullstackMode(): - return &dk.Spec.OneAgent.CloudNativeFullStack.NamespaceSelector - case dk.ApplicationMonitoringMode(): - return &dk.Spec.OneAgent.ApplicationMonitoring.NamespaceSelector - } - - return nil -} - -func (dk *DynaKube) OneAgentSecCompProfile() string { - switch { - case dk.CloudNativeFullstackMode(): - return dk.Spec.OneAgent.CloudNativeFullStack.SecCompProfile - case dk.HostMonitoringMode(): - return dk.Spec.OneAgent.HostMonitoring.SecCompProfile - case dk.ClassicFullStackMode(): - return dk.Spec.OneAgent.ClassicFullStack.SecCompProfile - default: - return "" - } -} - -func (dk *DynaKube) OneAgentNodeSelector() map[string]string { - switch { - case dk.ClassicFullStackMode(): - return dk.Spec.OneAgent.ClassicFullStack.NodeSelector - case dk.HostMonitoringMode(): - return dk.Spec.OneAgent.HostMonitoring.NodeSelector - case dk.CloudNativeFullstackMode(): - return dk.Spec.OneAgent.CloudNativeFullStack.NodeSelector - case dk.LogMonitoring().IsStandalone(): - return dk.LogMonitoring().Template().NodeSelector - } - - return nil -} - -// CodeModulesVersion provides version set in Status for the CodeModules. -func (dk *DynaKube) CodeModulesVersion() string { - return dk.Status.CodeModules.Version -} - -// CodeModulesImage provides the image reference set in Status for the CodeModules. -// Format: repo@sha256:digest. -func (dk *DynaKube) CodeModulesImage() string { - return dk.Status.CodeModules.ImageID -} - -// CustomCodeModulesImage provides the image reference for the CodeModules provided in the Spec. -func (dk *DynaKube) CustomCodeModulesImage() string { - if dk.CloudNativeFullstackMode() { - return dk.Spec.OneAgent.CloudNativeFullStack.CodeModulesImage - } else if dk.ApplicationMonitoringMode() && dk.IsCSIAvailable() { - return dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage - } - - return "" -} - -// CustomCodeModulesVersion provides the version for the CodeModules provided in the Spec. -func (dk *DynaKube) CustomCodeModulesVersion() string { - return dk.CustomOneAgentVersion() -} - -// OneAgentImage provides the image reference set in Status for the OneAgent. -// Format: repo@sha256:digest. -func (dk *DynaKube) OneAgentImage() string { - return dk.Status.OneAgent.ImageID -} - -// OneAgentVersion provides version set in Status for the OneAgent. -func (dk *DynaKube) OneAgentVersion() string { - return dk.Status.OneAgent.Version -} - -// CustomOneAgentVersion provides the version for the OneAgent provided in the Spec. -func (dk *DynaKube) CustomOneAgentVersion() string { - switch { - case dk.ClassicFullStackMode(): - return dk.Spec.OneAgent.ClassicFullStack.Version - case dk.CloudNativeFullstackMode(): - return dk.Spec.OneAgent.CloudNativeFullStack.Version - case dk.ApplicationMonitoringMode(): - return dk.Spec.OneAgent.ApplicationMonitoring.Version - case dk.HostMonitoringMode(): - return dk.Spec.OneAgent.HostMonitoring.Version - } - - return "" -} - -// CustomOneAgentImage provides the image reference for the OneAgent provided in the Spec. -func (dk *DynaKube) CustomOneAgentImage() string { - switch { - case dk.ClassicFullStackMode(): - return dk.Spec.OneAgent.ClassicFullStack.Image - case dk.HostMonitoringMode(): - return dk.Spec.OneAgent.HostMonitoring.Image - case dk.CloudNativeFullstackMode(): - return dk.Spec.OneAgent.CloudNativeFullStack.Image - } - - return "" -} - -// DefaultOneAgentImage provides the image reference for the OneAgent from tenant registry. -func (dk *DynaKube) DefaultOneAgentImage(version string) string { - apiUrlHost := dk.ApiUrlHost() - if apiUrlHost == "" { - return "" - } - - truncatedVersion := dtversion.ToImageTag(version) - tag := truncatedVersion - - if !strings.Contains(tag, api.RawTag) { - tag += "-" + api.RawTag - } - - return apiUrlHost + DefaultOneAgentImageRegistrySubPath + ":" + tag -} - -func (dk *DynaKube) HostGroup() string { - if dk.Spec.OneAgent.HostGroup != "" { - return dk.Spec.OneAgent.HostGroup - } - - return dk.HostGroupAsParam() -} - -func (dk *DynaKube) HostGroupAsParam() string { - var hostGroup string - - var args []string - - switch { - case dk.CloudNativeFullstackMode() && dk.Spec.OneAgent.CloudNativeFullStack.Args != nil: - args = dk.Spec.OneAgent.CloudNativeFullStack.Args - case dk.ClassicFullStackMode() && dk.Spec.OneAgent.ClassicFullStack.Args != nil: - args = dk.Spec.OneAgent.ClassicFullStack.Args - case dk.HostMonitoringMode() && dk.Spec.OneAgent.HostMonitoring.Args != nil: - args = dk.Spec.OneAgent.HostMonitoring.Args - } - - for _, arg := range args { - key, value := splitArg(arg) - if key == "--set-host-group" { - hostGroup = value - - break - } - } - - return hostGroup -} - -func splitArg(arg string) (key, value string) { - split := strings.Split(arg, "=") - - const expectedLen = 2 - - if len(split) != expectedLen { - return - } - - key = split[0] - value = split[1] - - return -} - -func (dk *DynaKube) IsOneAgentCommunicationRouteClear() bool { - return len(dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts) > 0 -} - -func (dk *DynaKube) GetOneAgentEnvironment() []corev1.EnvVar { - switch { - case dk.CloudNativeFullstackMode(): - return dk.Spec.OneAgent.CloudNativeFullStack.Env - case dk.ClassicFullStackMode(): - return dk.Spec.OneAgent.ClassicFullStack.Env - case dk.HostMonitoringMode(): - return dk.Spec.OneAgent.HostMonitoring.Env - } - - return []corev1.EnvVar{} -} - -func (dk *DynaKube) OneAgentEndpoints() string { - return dk.Status.OneAgent.ConnectionInfoStatus.Endpoints +func (dk *DynaKube) OneAgent() *oneagent.OneAgent { + oa := oneagent.NewOneAgent( + &dk.Spec.OneAgent, + &dk.Status.OneAgent, + &dk.Status.CodeModules, + dk.Name, + dk.ApiUrlHost(), + dk.FeatureOneAgentPrivileged(), + dk.FeatureOneAgentSkipLivenessProbe()) + + return oa } diff --git a/pkg/api/v1beta3/dynakube/oneagent_props_test.go b/pkg/api/v1beta3/dynakube/oneagent_props_test.go deleted file mode 100644 index 58f1ee879f..0000000000 --- a/pkg/api/v1beta3/dynakube/oneagent_props_test.go +++ /dev/null @@ -1,338 +0,0 @@ -/* -Copyright 2021 Dynatrace LLC. - -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. -*/ - -package dynakube - -import ( - "testing" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestNeedsReadonlyOneagent(t *testing.T) { - t.Run("cloud native fullstack always use readonly host agent", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - CloudNativeFullStack: &CloudNativeFullStackSpec{}, - }, - }, - } - assert.True(t, dk.UseReadOnlyOneAgents()) - }) - - t.Run("host monitoring with readonly host agent", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - HostMonitoring: &HostInjectSpec{}, - }, - }, - } - assert.True(t, dk.UseReadOnlyOneAgents()) - }) - - t.Run("host monitoring without readonly host agent", func(t *testing.T) { - setupDisabledCSIEnv(t) - - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - HostMonitoring: &HostInjectSpec{}, - }, - }, - } - assert.False(t, dk.UseReadOnlyOneAgents()) - }) -} - -func TestDefaultOneAgentImage(t *testing.T) { - t.Run("OneAgentImage with no API URL", func(t *testing.T) { - dk := DynaKube{} - assert.Equal(t, "", dk.DefaultOneAgentImage("")) - }) - - t.Run("OneAgentImage adds raw postfix", func(t *testing.T) { - dk := DynaKube{Spec: DynaKubeSpec{APIURL: testAPIURL}} - assert.Equal(t, "test-endpoint/linux/oneagent:1.234.5-raw", dk.DefaultOneAgentImage("1.234.5")) - }) - - t.Run("OneAgentImage doesn't add 'raw' postfix if present", func(t *testing.T) { - dk := DynaKube{Spec: DynaKubeSpec{APIURL: testAPIURL}} - assert.Equal(t, "test-endpoint/linux/oneagent:1.234.5-raw", dk.DefaultOneAgentImage("1.234.5-raw")) - }) - - t.Run("OneAgentImage with custom version truncates build date", func(t *testing.T) { - version := "1.239.14.20220325-164521" - expectedImage := "test-endpoint/linux/oneagent:1.239.14-raw" - dk := DynaKube{Spec: DynaKubeSpec{APIURL: testAPIURL}} - - assert.Equal(t, expectedImage, dk.DefaultOneAgentImage(version)) - }) -} - -func TestCustomOneAgentImage(t *testing.T) { - t.Run("OneAgentImage with custom image", func(t *testing.T) { - customImg := "registry/my/oneagent:latest" - dk := DynaKube{Spec: DynaKubeSpec{OneAgent: OneAgentSpec{ClassicFullStack: &HostInjectSpec{Image: customImg}}}} - assert.Equal(t, customImg, dk.CustomOneAgentImage()) - }) - - t.Run("OneAgentImage with no custom image", func(t *testing.T) { - dk := DynaKube{Spec: DynaKubeSpec{OneAgent: OneAgentSpec{ClassicFullStack: &HostInjectSpec{}}}} - assert.Equal(t, "", dk.CustomOneAgentImage()) - }) -} - -func TestOneAgentDaemonsetName(t *testing.T) { - dk := &DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-name", - }, - } - assert.Equal(t, "test-name-oneagent", dk.OneAgentDaemonsetName()) -} - -func TestCodeModulesVersion(t *testing.T) { - testVersion := "1.2.3" - - t.Run("use status", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - CloudNativeFullStack: &CloudNativeFullStackSpec{}, - }, - }, - Status: DynaKubeStatus{ - CodeModules: CodeModulesStatus{ - VersionStatus: status.VersionStatus{ - Version: testVersion, - }, - }, - }, - } - version := dk.CodeModulesVersion() - assert.Equal(t, testVersion, version) - }) - t.Run("use version ", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - ApplicationMonitoring: &ApplicationMonitoringSpec{ - Version: testVersion, - }, - }, - }, - Status: DynaKubeStatus{ - CodeModules: CodeModulesStatus{ - VersionStatus: status.VersionStatus{ - Version: "other", - }, - }, - }, - } - version := dk.CustomCodeModulesVersion() - assert.Equal(t, testVersion, version) - }) -} - -func TestIsOneAgentPrivileged(t *testing.T) { - t.Run("is false by default", func(t *testing.T) { - dk := DynaKube{} - - assert.False(t, dk.FeatureOneAgentPrivileged()) - }) - t.Run("is true when annotation is set to true", func(t *testing.T) { - dk := DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - AnnotationFeatureRunOneAgentContainerPrivileged: "true", - }, - }, - } - - assert.True(t, dk.FeatureOneAgentPrivileged()) - }) - t.Run("is false when annotation is set to false", func(t *testing.T) { - dk := DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - AnnotationFeatureRunOneAgentContainerPrivileged: "false", - }, - }, - } - - assert.False(t, dk.FeatureOneAgentPrivileged()) - }) -} - -func TestGetOneAgentEnvironment(t *testing.T) { - t.Run("get environment from classicFullstack", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - ClassicFullStack: &HostInjectSpec{ - Env: []corev1.EnvVar{ - { - Name: "classicFullstack", - Value: "true", - }, - }, - }, - }, - }, - } - env := dk.GetOneAgentEnvironment() - - require.Len(t, env, 1) - assert.Equal(t, "classicFullstack", env[0].Name) - }) - - t.Run("get environment from hostMonitoring", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - HostMonitoring: &HostInjectSpec{ - Env: []corev1.EnvVar{ - { - Name: "hostMonitoring", - Value: "true", - }, - }, - }, - }, - }, - } - env := dk.GetOneAgentEnvironment() - - require.Len(t, env, 1) - assert.Equal(t, "hostMonitoring", env[0].Name) - }) - - t.Run("get environment from cloudNative", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - CloudNativeFullStack: &CloudNativeFullStackSpec{ - HostInjectSpec: HostInjectSpec{ - Env: []corev1.EnvVar{ - { - Name: "cloudNative", - Value: "true", - }, - }, - }, - }, - }, - }, - } - env := dk.GetOneAgentEnvironment() - - require.Len(t, env, 1) - assert.Equal(t, "cloudNative", env[0].Name) - }) - - t.Run("get environment from applicationMonitoring", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - ApplicationMonitoring: &ApplicationMonitoringSpec{}, - }, - }, - } - env := dk.GetOneAgentEnvironment() - - require.NotNil(t, env) - assert.Empty(t, env) - }) - - t.Run("get environment from unconfigured dynakube", func(t *testing.T) { - dk := DynaKube{} - env := dk.GetOneAgentEnvironment() - - require.NotNil(t, env) - assert.Empty(t, env) - }) -} - -func TestOneAgentHostGroup(t *testing.T) { - t.Run("get host group from cloudNativeFullstack.args", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - CloudNativeFullStack: &CloudNativeFullStackSpec{ - HostInjectSpec: HostInjectSpec{ - Args: []string{ - "--set-host-group=arg", - }, - }, - }, - }, - }, - } - hostGroup := dk.HostGroup() - assert.Equal(t, "arg", hostGroup) - }) - - t.Run("get host group from oneagent.hostGroup", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - HostGroup: "field", - }, - }, - } - hostGroup := dk.HostGroup() - assert.Equal(t, "field", hostGroup) - }) - - t.Run("get host group if both methods used", func(t *testing.T) { - dk := DynaKube{ - Spec: DynaKubeSpec{ - OneAgent: OneAgentSpec{ - CloudNativeFullStack: &CloudNativeFullStackSpec{ - HostInjectSpec: HostInjectSpec{ - Args: []string{ - "--set-host-group=arg", - }, - }, - }, - HostGroup: "field", - }, - }, - } - hostGroup := dk.HostGroup() - assert.Equal(t, "field", hostGroup) - }) -} - -func setupDisabledCSIEnv(t *testing.T) { - t.Helper() - installconfig.SetModulesOverride(t, installconfig.Modules{ - CSIDriver: false, - ActiveGate: true, - OneAgent: true, - Extensions: true, - LogMonitoring: true, - EdgeConnect: true, - Supportability: true, - }) -} diff --git a/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go b/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go index e5b6963c55..f9813d44b4 100644 --- a/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go +++ b/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go @@ -22,97 +22,11 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - pkgv1 "github.com/google/go-containerregistry/pkg/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AppInjectionSpec) DeepCopyInto(out *AppInjectionSpec) { - *out = *in - if in.InitResources != nil { - in, out := &in.InitResources, &out.InitResources - *out = new(corev1.ResourceRequirements) - (*in).DeepCopyInto(*out) - } - in.NamespaceSelector.DeepCopyInto(&out.NamespaceSelector) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppInjectionSpec. -func (in *AppInjectionSpec) DeepCopy() *AppInjectionSpec { - if in == nil { - return nil - } - out := new(AppInjectionSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ApplicationMonitoringSpec) DeepCopyInto(out *ApplicationMonitoringSpec) { - *out = *in - in.AppInjectionSpec.DeepCopyInto(&out.AppInjectionSpec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationMonitoringSpec. -func (in *ApplicationMonitoringSpec) DeepCopy() *ApplicationMonitoringSpec { - if in == nil { - return nil - } - out := new(ApplicationMonitoringSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CloudNativeFullStackSpec) DeepCopyInto(out *CloudNativeFullStackSpec) { - *out = *in - in.HostInjectSpec.DeepCopyInto(&out.HostInjectSpec) - in.AppInjectionSpec.DeepCopyInto(&out.AppInjectionSpec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudNativeFullStackSpec. -func (in *CloudNativeFullStackSpec) DeepCopy() *CloudNativeFullStackSpec { - if in == nil { - return nil - } - out := new(CloudNativeFullStackSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CodeModulesStatus) DeepCopyInto(out *CodeModulesStatus) { - *out = *in - in.VersionStatus.DeepCopyInto(&out.VersionStatus) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CodeModulesStatus. -func (in *CodeModulesStatus) DeepCopy() *CodeModulesStatus { - if in == nil { - return nil - } - out := new(CodeModulesStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CommunicationHostStatus) DeepCopyInto(out *CommunicationHostStatus) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommunicationHostStatus. -func (in *CommunicationHostStatus) DeepCopy() *CommunicationHostStatus { - if in == nil { - return nil - } - out := new(CommunicationHostStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DynaKube) DeepCopyInto(out *DynaKube) { *out = *in @@ -341,67 +255,6 @@ func (in *ExtensionsSpec) DeepCopy() *ExtensionsSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HostInjectSpec) DeepCopyInto(out *HostInjectSpec) { - *out = *in - if in.Annotations != nil { - in, out := &in.Annotations, &out.Annotations - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.NodeSelector != nil { - in, out := &in.NodeSelector, &out.NodeSelector - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.AutoUpdate != nil { - in, out := &in.AutoUpdate, &out.AutoUpdate - *out = new(bool) - **out = **in - } - in.OneAgentResources.DeepCopyInto(&out.OneAgentResources) - if in.Tolerations != nil { - in, out := &in.Tolerations, &out.Tolerations - *out = make([]corev1.Toleration, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Env != nil { - in, out := &in.Env, &out.Env - *out = make([]corev1.EnvVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Args != nil { - in, out := &in.Args, &out.Args - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostInjectSpec. -func (in *HostInjectSpec) DeepCopy() *HostInjectSpec { - if in == nil { - return nil - } - out := new(HostInjectSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MetadataEnrichment) DeepCopyInto(out *MetadataEnrichment) { *out = *in @@ -443,110 +296,6 @@ func (in *MetadataEnrichmentStatus) DeepCopy() *MetadataEnrichmentStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *OneAgentConnectionInfoStatus) DeepCopyInto(out *OneAgentConnectionInfoStatus) { - *out = *in - in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo) - if in.CommunicationHosts != nil { - in, out := &in.CommunicationHosts, &out.CommunicationHosts - *out = make([]CommunicationHostStatus, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OneAgentConnectionInfoStatus. -func (in *OneAgentConnectionInfoStatus) DeepCopy() *OneAgentConnectionInfoStatus { - if in == nil { - return nil - } - out := new(OneAgentConnectionInfoStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *OneAgentInstance) DeepCopyInto(out *OneAgentInstance) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OneAgentInstance. -func (in *OneAgentInstance) DeepCopy() *OneAgentInstance { - if in == nil { - return nil - } - out := new(OneAgentInstance) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *OneAgentSpec) DeepCopyInto(out *OneAgentSpec) { - *out = *in - if in.ClassicFullStack != nil { - in, out := &in.ClassicFullStack, &out.ClassicFullStack - *out = new(HostInjectSpec) - (*in).DeepCopyInto(*out) - } - if in.CloudNativeFullStack != nil { - in, out := &in.CloudNativeFullStack, &out.CloudNativeFullStack - *out = new(CloudNativeFullStackSpec) - (*in).DeepCopyInto(*out) - } - if in.ApplicationMonitoring != nil { - in, out := &in.ApplicationMonitoring, &out.ApplicationMonitoring - *out = new(ApplicationMonitoringSpec) - (*in).DeepCopyInto(*out) - } - if in.HostMonitoring != nil { - in, out := &in.HostMonitoring, &out.HostMonitoring - *out = new(HostInjectSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OneAgentSpec. -func (in *OneAgentSpec) DeepCopy() *OneAgentSpec { - if in == nil { - return nil - } - out := new(OneAgentSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *OneAgentStatus) DeepCopyInto(out *OneAgentStatus) { - *out = *in - in.VersionStatus.DeepCopyInto(&out.VersionStatus) - if in.Instances != nil { - in, out := &in.Instances, &out.Instances - *out = make(map[string]OneAgentInstance, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.LastInstanceStatusUpdate != nil { - in, out := &in.LastInstanceStatusUpdate, &out.LastInstanceStatusUpdate - *out = (*in).DeepCopy() - } - if in.Healthcheck != nil { - in, out := &in.Healthcheck, &out.Healthcheck - *out = new(pkgv1.HealthConfig) - (*in).DeepCopyInto(*out) - } - in.ConnectionInfoStatus.DeepCopyInto(&out.ConnectionInfoStatus) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OneAgentStatus. -func (in *OneAgentStatus) DeepCopy() *OneAgentStatus { - if in == nil { - return nil - } - out := new(OneAgentStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenTelemetryCollectorSpec) DeepCopyInto(out *OpenTelemetryCollectorSpec) { *out = *in diff --git a/pkg/api/validation/dynakube/csi_daemonset.go b/pkg/api/validation/dynakube/csi_daemonset.go index 5d50e196b8..99f24e26bb 100644 --- a/pkg/api/validation/dynakube/csi_daemonset.go +++ b/pkg/api/validation/dynakube/csi_daemonset.go @@ -12,7 +12,7 @@ const ( ) func disabledCSIForReadonlyCSIVolume(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - isCSINotUsed := !dk.IsCSIAvailable() || (!isCSIRequired(dk) && !isCSIOptional(dk)) + isCSINotUsed := !dk.OneAgent().IsCSIAvailable() || (!isCSIRequired(dk) && !isCSIOptional(dk)) if dk.FeatureReadOnlyCsiVolume() && isCSINotUsed { log.Info("requested dynakube uses readonly csi volume, but csi driver is not enabled", "name", dk.Name, "namespace", dk.Namespace) @@ -24,5 +24,5 @@ func disabledCSIForReadonlyCSIVolume(_ context.Context, _ *Validator, dk *dynaku // IsCSIDriverOptional checks if the DynaKube may use the csi-driver if available, otherwise fallbacks exist to provide similar functionality. func isCSIOptional(dk *dynakube.DynaKube) bool { - return dk.HostMonitoringMode() || dk.ApplicationMonitoringMode() + return dk.OneAgent().IsHostMonitoringMode() || dk.OneAgent().IsApplicationMonitoringMode() } diff --git a/pkg/api/validation/dynakube/csi_daemonset_test.go b/pkg/api/validation/dynakube/csi_daemonset_test.go index d726215c40..305ca0c9cd 100644 --- a/pkg/api/validation/dynakube/csi_daemonset_test.go +++ b/pkg/api/validation/dynakube/csi_daemonset_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" ) func TestDisabledCSIForReadonlyCSIVolume(t *testing.T) { @@ -17,8 +18,8 @@ func TestDisabledCSIForReadonlyCSIVolume(t *testing.T) { ObjectMeta: *objectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, }) @@ -31,8 +32,8 @@ func TestDisabledCSIForReadonlyCSIVolume(t *testing.T) { ObjectMeta: *objectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, }) diff --git a/pkg/api/validation/dynakube/image.go b/pkg/api/validation/dynakube/image.go index 11bbf22c2f..eaee6ba5e3 100644 --- a/pkg/api/validation/dynakube/image.go +++ b/pkg/api/validation/dynakube/image.go @@ -26,7 +26,7 @@ func imageFieldHasTenantImage(_ context.Context, _ *Validator, dk *dynakube.Dyna }, { section: "OneAgent", - value: dk.CustomOneAgentImage(), + value: dk.OneAgent().GetCustomImage(), }, } diff --git a/pkg/api/validation/dynakube/image_test.go b/pkg/api/validation/dynakube/image_test.go index 8f5081339d..dc74cea41b 100644 --- a/pkg/api/validation/dynakube/image_test.go +++ b/pkg/api/validation/dynakube/image_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -26,8 +27,8 @@ func TestImageFieldHasTenantImage(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testTenantUrl + "/api", - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Image: "BOOM", }, }, @@ -48,8 +49,8 @@ func TestImageFieldHasTenantImage(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testTenantUrl + "/api", - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Image: testRegistryUrl + "/linux/oneagent:latest", }, }, @@ -70,8 +71,8 @@ func TestImageFieldHasTenantImage(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testTenantUrl + "/api", - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Image: testRegistryUrl + "/linux/oneagent:latest", }, }, @@ -86,8 +87,8 @@ func TestImageFieldHasTenantImage(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testTenantUrl + "/api", - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Image: "127.0.0.1:5000/test:tag", }, }, diff --git a/pkg/api/validation/dynakube/logmonitoring.go b/pkg/api/validation/dynakube/logmonitoring.go index 636c576f02..d0615cda37 100644 --- a/pkg/api/validation/dynakube/logmonitoring.go +++ b/pkg/api/validation/dynakube/logmonitoring.go @@ -16,7 +16,7 @@ func ignoredLogMonitoringTemplate(ctx context.Context, dv *Validator, dk *dynaku return "" } - if dk.NeedsOneAgent() && dk.LogMonitoring().TemplateSpec != nil { + if dk.OneAgent().IsDaemonsetRequired() && dk.LogMonitoring().TemplateSpec != nil { return warningLogMonitoringIgnoredTemplate } diff --git a/pkg/api/validation/dynakube/logmonitoring_test.go b/pkg/api/validation/dynakube/logmonitoring_test.go index 9d87857f3c..7bf9a11050 100644 --- a/pkg/api/validation/dynakube/logmonitoring_test.go +++ b/pkg/api/validation/dynakube/logmonitoring_test.go @@ -6,19 +6,20 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestIgnoredLogMonitoringTemplate(t *testing.T) { t.Run("no warning if logMonitoring template section is empty", func(t *testing.T) { dk := createStandaloneLogMonitoringDynakube(testName, testApiUrl, "") - dk.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} + dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} dk.Spec.Templates.LogMonitoring = nil assertAllowedWithoutWarnings(t, dk) }) t.Run("warning if logMonitoring template section is not empty", func(t *testing.T) { dk := createStandaloneLogMonitoringDynakube(testName, testApiUrl, "something") - dk.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} + dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} assertAllowedWithWarnings(t, 1, dk) }) } diff --git a/pkg/api/validation/dynakube/module_test.go b/pkg/api/validation/dynakube/module_test.go index 9b90e471dd..943defa509 100644 --- a/pkg/api/validation/dynakube/module_test.go +++ b/pkg/api/validation/dynakube/module_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/stretchr/testify/assert" ) @@ -26,56 +27,56 @@ func TestIsModuleDisabled(t *testing.T) { testCases := []testCase{ { title: "csi module disabled but also configured in dk => error", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}}}, + dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}}}, modules: installconfig.Modules{OneAgent: true, CSIDriver: false}, moduleFunc: isCSIModuleDisabled, expectedMessage: errorCSIModuleRequired, }, { title: "csi module disabled but not configured => no error", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: nil}}}, + dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: nil}}}, modules: installconfig.Modules{OneAgent: true, CSIDriver: false}, moduleFunc: isCSIModuleDisabled, expectedMessage: "", }, { title: "csi module enabled and also configured => no error", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}}}, + dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}}}, modules: installconfig.Modules{OneAgent: true, CSIDriver: true}, moduleFunc: isCSIModuleDisabled, expectedMessage: "", }, { title: "csi module disabled and app-monitoring configured => no error, as it's optional for app-monitoring", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: dynakube.OneAgentSpec{ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}}}}, + dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}}}}, modules: installconfig.Modules{OneAgent: true, CSIDriver: false}, moduleFunc: isCSIModuleDisabled, expectedMessage: "", }, { title: "csi module disabled and host-monitoring configured => no error, as it's optional for host-monitoring", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: dynakube.OneAgentSpec{HostMonitoring: &dynakube.HostInjectSpec{}}}}, + dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{HostMonitoring: &oneagent.HostInjectSpec{}}}}, modules: installconfig.Modules{OneAgent: true, CSIDriver: true}, moduleFunc: isCSIModuleDisabled, expectedMessage: "", }, { title: "oa module disabled but also configured in dk => error", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}}}, + dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}}}, modules: installconfig.Modules{OneAgent: false, CSIDriver: true}, moduleFunc: isOneAgentModuleDisabled, expectedMessage: errorOneAgentModuleDisabled, }, { title: "oa module disabled but not configured => no error", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: nil}}}, + dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: nil}}}, modules: installconfig.Modules{OneAgent: false, CSIDriver: true}, moduleFunc: isOneAgentModuleDisabled, expectedMessage: "", }, { title: "oa module enabled and also configured => no error", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}}}, + dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}}}, modules: installconfig.Modules{OneAgent: true, CSIDriver: true}, moduleFunc: isOneAgentModuleDisabled, expectedMessage: "", @@ -176,15 +177,15 @@ func TestIsModuleDisabled(t *testing.T) { func TestIsCSIDriverRequired(t *testing.T) { t.Run("DynaKube with cloud native", func(t *testing.T) { - dk := dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}}} + dk := dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}}} assert.True(t, isCSIRequired(&dk)) }) t.Run("DynaKube with host monitoring", func(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -194,8 +195,8 @@ func TestIsCSIDriverRequired(t *testing.T) { t.Run("DynaKube with application monitoring", func(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, }, } diff --git a/pkg/api/validation/dynakube/modules.go b/pkg/api/validation/dynakube/modules.go index 83526a49bb..1c3636f9ac 100644 --- a/pkg/api/validation/dynakube/modules.go +++ b/pkg/api/validation/dynakube/modules.go @@ -17,7 +17,7 @@ var ( ) func isOneAgentModuleDisabled(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { - if dk.NeedsOneAgent() && !v.modules.OneAgent { + if dk.OneAgent().IsDaemonsetRequired() && !v.modules.OneAgent { return errorOneAgentModuleDisabled } @@ -66,5 +66,5 @@ func isCSIModuleDisabled(_ context.Context, v *Validator, dk *dynakube.DynaKube) // isCSIRequired checks if the provided a DynaKube strictly needs the csi-driver, and no fallbacks exist to provide the same functionality. func isCSIRequired(dk *dynakube.DynaKube) bool { - return dk.CloudNativeFullstackMode() + return dk.OneAgent().IsCloudNativeFullstackMode() } diff --git a/pkg/api/validation/dynakube/namespace_selector.go b/pkg/api/validation/dynakube/namespace_selector.go index 782bc04a77..0d656712b7 100644 --- a/pkg/api/validation/dynakube/namespace_selector.go +++ b/pkg/api/validation/dynakube/namespace_selector.go @@ -18,7 +18,7 @@ Make sure the namespaceSelector doesn't conflict with other Dynakubes namespaceS ) func conflictingNamespaceSelector(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { - if !dk.NeedAppInjection() && !dk.MetadataEnrichmentEnabled() { + if !dk.OneAgent().IsAppInjectionNeeded() && !dk.MetadataEnrichmentEnabled() { return "" } @@ -35,7 +35,7 @@ func conflictingNamespaceSelector(ctx context.Context, dv *Validator, dk *dynaku } func namespaceSelectorViolateLabelSpec(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - errs := validation.ValidateLabelSelector(dk.OneAgentNamespaceSelector(), validation.LabelSelectorValidationOptions{AllowInvalidLabelValueInSelector: false}, field.NewPath("spec", "namespaceSelector")) + errs := validation.ValidateLabelSelector(dk.OneAgent().GetNamespaceSelector(), validation.LabelSelectorValidationOptions{AllowInvalidLabelValueInSelector: false}, field.NewPath("spec", "namespaceSelector")) if len(errs) == 0 { return "" } diff --git a/pkg/api/validation/dynakube/namespace_selector_test.go b/pkg/api/validation/dynakube/namespace_selector_test.go index 4dc546d438..112e5a27c6 100644 --- a/pkg/api/validation/dynakube/namespace_selector_test.go +++ b/pkg/api/validation/dynakube/namespace_selector_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -13,9 +14,9 @@ func TestConflictingNamespaceSelector(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: dummyLabels, }, @@ -28,9 +29,9 @@ func TestConflictingNamespaceSelector(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: dummyLabels, }, @@ -47,9 +48,9 @@ func TestConflictingNamespaceSelector(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: dummyLabels, }, @@ -65,9 +66,9 @@ func TestConflictingNamespaceSelector(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: dummyLabels, }, @@ -98,9 +99,9 @@ func TestConflictingNamespaceSelector(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ "dummy": label, @@ -120,9 +121,9 @@ func TestConflictingNamespaceSelector(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ { @@ -154,9 +155,9 @@ func TestConflictingNamespaceSelector(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ "dummy": label, @@ -178,9 +179,9 @@ func TestConflictingNamespaceSelector(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ { diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index 8df06d5cfb..dda3acb6f5 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -34,19 +34,19 @@ Use a nodeSelector to avoid this conflict. Conflicting DynaKubes: %s` func conflictingOneAgentConfiguration(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { counter := 0 - if dk.ApplicationMonitoringMode() { + if dk.OneAgent().IsApplicationMonitoringMode() { counter += 1 } - if dk.CloudNativeFullstackMode() { + if dk.OneAgent().IsCloudNativeFullstackMode() { counter += 1 } - if dk.ClassicFullStackMode() { + if dk.OneAgent().IsClassicFullStackMode() { counter += 1 } - if dk.HostMonitoringMode() { + if dk.OneAgent().IsHostMonitoringMode() { counter += 1 } @@ -60,7 +60,7 @@ func conflictingOneAgentConfiguration(_ context.Context, _ *Validator, dk *dynak } func conflictingOneAgentNodeSelector(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { - if !dk.NeedsOneAgent() && !dk.LogMonitoring().IsStandalone() { + if !dk.OneAgent().IsDaemonsetRequired() && !dk.LogMonitoring().IsStandalone() { return "" } @@ -71,7 +71,7 @@ func conflictingOneAgentNodeSelector(ctx context.Context, dv *Validator, dk *dyn return "" } - oneAgentNodeSelector := dk.OneAgentNodeSelector() + oneAgentNodeSelector := dk.OneAgent().GetNodeSelector(dk.LogMonitoring().GetNodeSelector()) conflictingDynakubes := make(map[string]bool) for _, item := range validDynakubes.Items { @@ -80,7 +80,7 @@ func conflictingOneAgentNodeSelector(ctx context.Context, dv *Validator, dk *dyn } if hasLogMonitoringSelectorConflict(dk, &item) || hasOneAgentSelectorConflict(dk, &item) { - if hasConflictingMatchLabels(oneAgentNodeSelector, item.OneAgentNodeSelector()) { + if hasConflictingMatchLabels(oneAgentNodeSelector, item.OneAgent().GetNodeSelector(dk.LogMonitoring().GetNodeSelector())) { log.Info("requested dynakube has conflicting OneAgent nodeSelector", "name", dk.Name, "namespace", dk.Namespace) conflictingDynakubes[item.Name] = true @@ -97,14 +97,16 @@ func conflictingOneAgentNodeSelector(ctx context.Context, dv *Validator, dk *dyn func hasLogMonitoringSelectorConflict(dk1, dk2 *dynakube.DynaKube) bool { return dk1.LogMonitoring().IsStandalone() && dk1.ApiUrl() == dk2.ApiUrl() && - (dk2.NeedsOneAgent() || dk2.LogMonitoring().IsStandalone()) && - hasConflictingMatchLabels(dk1.OneAgentNodeSelector(), dk2.OneAgentNodeSelector()) + (dk2.OneAgent().IsDaemonsetRequired() || dk2.LogMonitoring().IsStandalone()) && + hasConflictingMatchLabels(dk1.OneAgent().GetNodeSelector(dk1.LogMonitoring().GetNodeSelector()), + dk2.OneAgent().GetNodeSelector(dk2.LogMonitoring().GetNodeSelector())) } func hasOneAgentSelectorConflict(dk1, dk2 *dynakube.DynaKube) bool { - return dk1.NeedsOneAgent() && - (dk2.NeedsOneAgent() || dk2.LogMonitoring().IsStandalone() && dk1.ApiUrl() == dk2.ApiUrl()) && - hasConflictingMatchLabels(dk1.OneAgentNodeSelector(), dk2.OneAgentNodeSelector()) + return dk1.OneAgent().IsDaemonsetRequired() && + (dk2.OneAgent().IsDaemonsetRequired() || dk2.LogMonitoring().IsStandalone() && dk1.ApiUrl() == dk2.ApiUrl()) && + hasConflictingMatchLabels(dk1.OneAgent().GetNodeSelector(dk1.LogMonitoring().GetNodeSelector()), + dk2.OneAgent().GetNodeSelector(dk2.LogMonitoring().GetNodeSelector())) } func mapKeysToString(m map[string]bool, sep string) string { @@ -117,7 +119,7 @@ func mapKeysToString(m map[string]bool, sep string) string { } func imageFieldSetWithoutCSIFlag(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { - if dk.ApplicationMonitoringMode() { + if dk.OneAgent().IsApplicationMonitoringMode() { if len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) > 0 && !v.modules.CSIDriver { return errorImageFieldSetWithoutCSIFlag } @@ -140,7 +142,7 @@ func hasConflictingMatchLabels(labelMap, otherLabelMap map[string]string) bool { } func hasOneAgentVolumeStorageEnabled(dk *dynakube.DynaKube) (isEnabled bool, isSet bool) { - envVar := env.FindEnvVar(dk.GetOneAgentEnvironment(), oneagentEnableVolumeStorageEnvVarName) + envVar := env.FindEnvVar(dk.OneAgent().GetEnvironment(), oneagentEnableVolumeStorageEnvVarName) isSet = envVar != nil isEnabled = isSet && envVar.Value == "true" @@ -148,8 +150,8 @@ func hasOneAgentVolumeStorageEnabled(dk *dynakube.DynaKube) (isEnabled bool, isS } func unsupportedOneAgentImage(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - if env.FindEnvVar(dk.GetOneAgentEnvironment(), oneagentInstallerScriptUrlEnvVarName) != nil || - env.FindEnvVar(dk.GetOneAgentEnvironment(), oneagentInstallerTokenEnvVarName) != nil { + if env.FindEnvVar(dk.OneAgent().GetEnvironment(), oneagentInstallerScriptUrlEnvVarName) != nil || + env.FindEnvVar(dk.OneAgent().GetEnvironment(), oneagentInstallerTokenEnvVarName) != nil { return warningOneAgentInstallerEnvVars } @@ -158,7 +160,7 @@ func unsupportedOneAgentImage(_ context.Context, _ *Validator, dk *dynakube.Dyna func conflictingOneAgentVolumeStorageSettings(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { volumeStorageEnabled, volumeStorageSet := hasOneAgentVolumeStorageEnabled(dk) - if dk.UseReadOnlyOneAgents() && volumeStorageSet && !volumeStorageEnabled { + if dk.OneAgent().IsReadOnlyOneAgentsMode() && volumeStorageSet && !volumeStorageEnabled { return errorVolumeStorageReadOnlyModeConflict } @@ -166,7 +168,7 @@ func conflictingOneAgentVolumeStorageSettings(_ context.Context, _ *Validator, d } func conflictingHostGroupSettings(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - if dk.HostGroupAsParam() != "" { + if dk.OneAgent().GetHostGroupAsParam() != "" { return warningHostGroupConflict } @@ -174,7 +176,7 @@ func conflictingHostGroupSettings(_ context.Context, _ *Validator, dk *dynakube. } func isOneAgentVersionValid(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - agentVersion := dk.CustomOneAgentVersion() + agentVersion := dk.OneAgent().GetCustomVersion() if agentVersion == "" { return "" } diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index 5359077cd5..29d4e56254 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -16,7 +17,7 @@ func TestConflictingOneAgentConfiguration(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ ClassicFullStack: nil, HostMonitoring: nil, }, @@ -27,8 +28,8 @@ func TestConflictingOneAgentConfiguration(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, HostMonitoring: nil, }, }, @@ -38,9 +39,9 @@ func TestConflictingOneAgentConfiguration(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ ClassicFullStack: nil, - HostMonitoring: &dynakube.HostInjectSpec{}, + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, }) @@ -52,9 +53,9 @@ func TestConflictingOneAgentConfiguration(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, }) @@ -65,9 +66,9 @@ func TestConflictingOneAgentConfiguration(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, }) @@ -83,9 +84,9 @@ func TestConflictingNodeSelector(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: apiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ NodeSelector: map[string]string{ "node": nodeSelectorValue, }, @@ -102,8 +103,8 @@ func TestConflictingNodeSelector(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ NodeSelector: map[string]string{ "node": "1", }, @@ -118,8 +119,8 @@ func TestConflictingNodeSelector(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ NodeSelector: map[string]string{ "node": "2", }, @@ -137,9 +138,9 @@ func TestConflictingNodeSelector(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ NodeSelector: map[string]string{ "node": "1", }, @@ -152,8 +153,8 @@ func TestConflictingNodeSelector(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ NodeSelector: map[string]string{ "node": "2", }, @@ -193,9 +194,9 @@ func TestConflictingNodeSelector(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: api1, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ NodeSelector: map[string]string{ "node": "1", }, @@ -211,8 +212,8 @@ func TestConflictingNodeSelector(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: api2, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ NodeSelector: map[string]string{ "node": "1", }, @@ -276,9 +277,9 @@ func TestImageFieldSetWithoutCSIFlag(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ CodeModulesImage: testImage, }, }, @@ -295,9 +296,9 @@ func TestImageFieldSetWithoutCSIFlag(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ CodeModulesImage: testImage, }, }, @@ -323,9 +324,9 @@ func createDynakube(oaEnvVar ...string) *dynakube.DynaKube { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ Env: envVars, }, }, @@ -400,8 +401,8 @@ func TestOneAgentHostGroup(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Args: []string{"--set-host-group=arg"}, }, HostGroup: "", @@ -415,8 +416,8 @@ func TestOneAgentHostGroup(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ Args: []string{"--set-host-group=arg"}, }, HostGroup: "", @@ -431,9 +432,9 @@ func createDynakubeWithHostGroup(args []string, hostGroup string) *dynakube.Dyna ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ Args: args, }, }, @@ -448,8 +449,8 @@ func TestIsOneAgentVersionValid(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } diff --git a/pkg/api/validation/dynakube/preview_test.go b/pkg/api/validation/dynakube/preview_test.go index 8a36372634..30c65e50da 100644 --- a/pkg/api/validation/dynakube/preview_test.go +++ b/pkg/api/validation/dynakube/preview_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" ) func TestPreviewWarning(t *testing.T) { @@ -12,8 +13,8 @@ func TestPreviewWarning(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, }, }) diff --git a/pkg/api/validation/dynakube/validation_test.go b/pkg/api/validation/dynakube/validation_test.go index b5f536c2fa..caead5ec50 100644 --- a/pkg/api/validation/dynakube/validation_test.go +++ b/pkg/api/validation/dynakube/validation_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -57,14 +58,14 @@ func TestDynakubeValidator_Handle(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ NodeSelector: map[string]string{ "node": "1", }, }, - AppInjectionSpec: dynakube.AppInjectionSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: dummyLabels, }, @@ -84,14 +85,14 @@ func TestDynakubeValidator_Handle(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ NodeSelector: map[string]string{ "node": "2", }, }, - AppInjectionSpec: dynakube.AppInjectionSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: dummyLabels2, }, @@ -118,9 +119,9 @@ func TestDynakubeValidator_Handle(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: "", - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: dummyLabels, }, @@ -143,9 +144,9 @@ func TestDynakubeValidator_Handle(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: dummyLabels, }, @@ -161,8 +162,8 @@ func TestDynakubeValidator_Handle(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, }, &dummyNamespace, &dummyNamespace2) diff --git a/pkg/clients/dynatrace/processmoduleconfig.go b/pkg/clients/dynatrace/processmoduleconfig.go index de5821ee7a..5ff169bcc7 100644 --- a/pkg/clients/dynatrace/processmoduleconfig.go +++ b/pkg/clients/dynatrace/processmoduleconfig.go @@ -7,7 +7,7 @@ import ( "net/http" "strconv" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/clients/utils" "github.com/pkg/errors" ) @@ -88,7 +88,7 @@ func (pmc *ProcessModuleConfig) removeProperty(index int) { pmc.Properties = append(pmc.Properties[0:index], pmc.Properties[index+1:]...) } -func (pmc *ProcessModuleConfig) AddConnectionInfo(oneAgentConnectionInfo dynakube.OneAgentConnectionInfoStatus, tenantToken string) *ProcessModuleConfig { +func (pmc *ProcessModuleConfig) AddConnectionInfo(oneAgentConnectionInfo oneagent.ConnectionInfoStatus, tenantToken string) *ProcessModuleConfig { tenant := ProcessModuleProperty{ Section: generalSectionName, Key: "tenant", diff --git a/pkg/controllers/csi/gc/reconciler.go b/pkg/controllers/csi/gc/reconciler.go index c86f9c8aa9..5e549d4366 100644 --- a/pkg/controllers/csi/gc/reconciler.go +++ b/pkg/controllers/csi/gc/reconciler.go @@ -58,7 +58,7 @@ func (gc *CSIGarbageCollector) Reconcile(ctx context.Context, request reconcile. return defaultReconcileResult, nil } - if !dynakube.NeedAppInjection() { + if !dynakube.OneAgent().IsAppInjectionNeeded() { log.Info("app injection not enabled, skip garbage collection", "dynakube", dynakube.Name) return defaultReconcileResult, nil diff --git a/pkg/controllers/csi/provisioner/controller.go b/pkg/controllers/csi/provisioner/controller.go index a0ae0fc70d..5287797105 100644 --- a/pkg/controllers/csi/provisioner/controller.go +++ b/pkg/controllers/csi/provisioner/controller.go @@ -120,13 +120,13 @@ func (provisioner *OneAgentProvisioner) Reconcile(ctx context.Context, request r return reconcile.Result{}, err } - if !dk.NeedAppInjection() { + if !dk.OneAgent().IsAppInjectionNeeded() { log.Info("app injection not necessary, skip agent codemodule download", "dynakube", dk.Name) return reconcile.Result{RequeueAfter: longRequeueDuration}, nil } - if dk.CodeModulesImage() == "" && dk.CodeModulesVersion() == "" { + if dk.OneAgent().GetCodeModulesImage() == "" && dk.OneAgent().GetCodeModulesVersion() == "" { log.Info("dynakube status is not yet ready, requeuing", "dynakube", dk.Name) return reconcile.Result{RequeueAfter: shortRequeueDuration}, err @@ -146,9 +146,9 @@ func (provisioner *OneAgentProvisioner) Reconcile(ctx context.Context, request r } func isProvisionerNeeded(dk *dynakube.DynaKube) bool { - return dk.CloudNativeFullstackMode() || - dk.ApplicationMonitoringMode() || - dk.HostMonitoringMode() + return dk.OneAgent().IsCloudNativeFullstackMode() || + dk.OneAgent().IsApplicationMonitoringMode() || + dk.OneAgent().IsHostMonitoringMode() } func (provisioner *OneAgentProvisioner) setupFileSystem(dk *dynakube.DynaKube) error { @@ -220,7 +220,7 @@ func (provisioner *OneAgentProvisioner) updateAgentInstallation( return false, err } - if dk.CodeModulesImage() != "" { + if dk.OneAgent().GetCodeModulesImage() != "" { updatedDigest, err := provisioner.installAgentImage(ctx, *dk, latestProcessModuleConfig) if err != nil { log.Info("error when updating agent from image", "error", err.Error()) diff --git a/pkg/controllers/csi/provisioner/controller_test.go b/pkg/controllers/csi/provisioner/controller_test.go index 97bf7951fa..5ef4034869 100644 --- a/pkg/controllers/csi/provisioner/controller_test.go +++ b/pkg/controllers/csi/provisioner/controller_test.go @@ -12,6 +12,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" @@ -101,8 +102,8 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { Name: dynakubeName, }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, }, @@ -125,8 +126,8 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testAPIURL, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, }, @@ -175,12 +176,12 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testAPIURL, - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), }, }, Status: dynakube.DynaKubeStatus{ - CodeModules: dynakube.CodeModulesStatus{ + CodeModules: oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ Version: "1.2.3", }, @@ -215,12 +216,12 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testAPIURL, - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), }, }, Status: dynakube.DynaKubeStatus{ - CodeModules: dynakube.CodeModulesStatus{ + CodeModules: oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ Version: "1.2.3", }, @@ -262,7 +263,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testAPIURL, - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), }, }, @@ -302,7 +303,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testAPIURL, - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), }, }, @@ -323,7 +324,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { }, &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: dynakube.OneagentTenantSecret(), + Name: dynakube.OneAgent().GetTenantSecret(), }, Data: map[string][]byte{ connectioninfo.TenantTokenKey: []byte("tenant-token"), @@ -365,12 +366,12 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testAPIURL, - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), }, }, Status: dynakube.DynaKubeStatus{ - CodeModules: dynakube.CodeModulesStatus{ + CodeModules: oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ Version: "1.2.3", }, @@ -405,8 +406,8 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testAPIURL, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, }, @@ -436,8 +437,8 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { }) } -func buildValidApplicationMonitoringSpec(_ *testing.T) *dynakube.ApplicationMonitoringSpec { - return &dynakube.ApplicationMonitoringSpec{} +func buildValidApplicationMonitoringSpec(_ *testing.T) *oneagent.ApplicationMonitoringSpec { + return &oneagent.ApplicationMonitoringSpec{} } func TestProvisioner_CreateDynakube(t *testing.T) { @@ -509,7 +510,7 @@ func TestUpdateAgentInstallation(t *testing.T) { require.NoError(t, err) path := metadata.PathResolver{RootDir: "test"} - base64Image := base64.StdEncoding.EncodeToString([]byte(dynakube.CodeModulesImage())) + base64Image := base64.StdEncoding.EncodeToString([]byte(dynakube.OneAgent().GetCodeModulesImage())) targetDir := path.AgentSharedBinaryDirForAgent(base64Image) mockK8sClient := createMockK8sClient(ctx, dynakube) @@ -555,7 +556,7 @@ func TestUpdateAgentInstallation(t *testing.T) { require.NoError(t, err) path := metadata.PathResolver{RootDir: "test"} - base64Image := base64.StdEncoding.EncodeToString([]byte(dynakube.CodeModulesImage())) + base64Image := base64.StdEncoding.EncodeToString([]byte(dynakube.OneAgent().GetCodeModulesImage())) targetDir := path.AgentSharedBinaryDirForAgent(base64Image) mockK8sClient := createMockK8sClient(ctx, dynakube) @@ -684,13 +685,13 @@ func getDynakube() *dynakube.DynaKube { }, Spec: dynakube.DynaKubeSpec{ APIURL: testAPIURL, - OneAgent: dynakube.OneAgentSpec{}, + OneAgent: oneagent.Spec{}, }, }) } func enableCodeModules(dk *dynakube.DynaKube) { - dk.Status.CodeModules = dynakube.CodeModulesStatus{ + dk.Status.CodeModules = oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ Version: testVersion, ImageID: testImageID, diff --git a/pkg/controllers/csi/provisioner/install.go b/pkg/controllers/csi/provisioner/install.go index 18c4510ed6..e5a593be86 100644 --- a/pkg/controllers/csi/provisioner/install.go +++ b/pkg/controllers/csi/provisioner/install.go @@ -27,7 +27,7 @@ func (provisioner *OneAgentProvisioner) installAgentImage( return "", err } - targetImage := dk.CodeModulesImage() + targetImage := dk.OneAgent().GetCodeModulesImage() // An image URI often contains one or several /-s, which is problematic when trying to use it as a folder name. // Easiest to just base64 encode it base64Image := base64.StdEncoding.EncodeToString([]byte(targetImage)) @@ -66,7 +66,7 @@ func (provisioner *OneAgentProvisioner) installAgentZip(ctx context.Context, dk return "", err } - targetVersion := dk.CodeModulesVersion() + targetVersion := dk.OneAgent().GetCodeModulesVersion() urlInstaller := provisioner.urlInstallerBuilder(provisioner.fs, dtc, getUrlProperties(targetVersion, provisioner.path)) targetDir := provisioner.path.AgentSharedBinaryDirForAgent(targetVersion) diff --git a/pkg/controllers/csi/provisioner/install_test.go b/pkg/controllers/csi/provisioner/install_test.go index d7255f2956..b70c818fe6 100644 --- a/pkg/controllers/csi/provisioner/install_test.go +++ b/pkg/controllers/csi/provisioner/install_test.go @@ -10,6 +10,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" @@ -41,7 +42,7 @@ func TestUpdateAgent(t *testing.T) { t.Run("zip install", func(t *testing.T) { dk := createTestDynaKubeWithZip(testVersion) provisioner := createTestProvisioner() - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.CodeModulesVersion()) + targetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.OneAgent().GetCodeModulesVersion()) var revision uint = 3 processModule := createTestProcessModuleConfig(revision) @@ -68,14 +69,14 @@ func TestUpdateAgent(t *testing.T) { t.Run("zip update", func(t *testing.T) { dk := createTestDynaKubeWithZip(testVersion) provisioner := createTestProvisioner() - previousTargetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.CodeModulesVersion()) + previousTargetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.OneAgent().GetCodeModulesVersion()) previousSourceConfigPath := filepath.Join(previousTargetDir, processmoduleconfig.RuxitAgentProcPath) _ = provisioner.fs.MkdirAll(previousTargetDir, 0755) _, _ = provisioner.fs.Create(previousSourceConfigPath) newVersion := "new" dk.Status.CodeModules.Version = newVersion - newTargetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.CodeModulesVersion()) + newTargetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.OneAgent().GetCodeModulesVersion()) var revision uint = 3 processModule := createTestProcessModuleConfig(revision) @@ -93,7 +94,7 @@ func TestUpdateAgent(t *testing.T) { t.Run("only process module config update", func(t *testing.T) { dk := createTestDynaKubeWithZip(testVersion) provisioner := createTestProvisioner() - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.CodeModulesVersion()) + targetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.OneAgent().GetCodeModulesVersion()) sourceConfigPath := filepath.Join(targetDir, processmoduleconfig.RuxitAgentProcPath) _ = provisioner.fs.MkdirAll(targetDir, 0755) _, _ = provisioner.fs.Create(sourceConfigPath) @@ -280,7 +281,7 @@ func createTestDynaKubeWithImage(image string) dynakube.DynaKube { APIURL: "https://" + testTenantUUID + ".dynatrace.com", }, Status: dynakube.DynaKubeStatus{ - CodeModules: dynakube.CodeModulesStatus{ + CodeModules: oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ ImageID: image, }, @@ -299,7 +300,7 @@ func createTestDynaKubeWithZip(version string) dynakube.DynaKube { APIURL: "https://" + testTenantUUID + ".dynatrace.com", }, Status: dynakube.DynaKubeStatus{ - CodeModules: dynakube.CodeModulesStatus{ + CodeModules: oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ Version: version, }, diff --git a/pkg/controllers/dynakube/apimonitoring/reconciler_test.go b/pkg/controllers/dynakube/apimonitoring/reconciler_test.go index 2c6e52569d..b07cec8b83 100644 --- a/pkg/controllers/dynakube/apimonitoring/reconciler_test.go +++ b/pkg/controllers/dynakube/apimonitoring/reconciler_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/pkg/errors" @@ -324,8 +325,8 @@ func newDynaKube() *dynakube.DynaKube { }, }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, Status: dynakube.DynaKubeStatus{ diff --git a/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts_test.go b/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts_test.go index d63c6fbf7c..cd826eb6a6 100644 --- a/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts_test.go +++ b/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts_test.go @@ -5,6 +5,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -16,8 +17,8 @@ func TestParseCommunicationHostsFromActiveGateEndpoints(t *testing.T) { Name: "test-name", }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{}, }, }, diff --git a/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts_test.go b/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts_test.go index ec6b41c7ff..c9479fa1e7 100644 --- a/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts_test.go +++ b/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts_test.go @@ -5,6 +5,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -17,8 +18,8 @@ func TestGetCommunicationHosts(t *testing.T) { Name: testName, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{}, }, }, @@ -39,7 +40,7 @@ func TestGetCommunicationHosts(t *testing.T) { }) t.Run(`communication-hosts field found`, func(t *testing.T) { - dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []dynakube.CommunicationHostStatus{ + dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{ { Protocol: "protocol", Host: "host", diff --git a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go index 6cf7703832..2c69933623 100644 --- a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go +++ b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go @@ -2,6 +2,7 @@ package oaconnectioninfo import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" @@ -43,20 +44,20 @@ func NewReconciler(clt client.Client, apiReader client.Reader, dtc dtclient.Clie var NoOneAgentCommunicationHostsError = errors.New("no communication hosts for OneAgent are available") func (r *reconciler) Reconcile(ctx context.Context) error { - if !r.dk.NeedAppInjection() && !r.dk.NeedsOneAgent() && !r.dk.LogMonitoring().IsEnabled() { + if !r.dk.OneAgent().IsAppInjectionNeeded() && !r.dk.OneAgent().IsDaemonsetRequired() && !r.dk.LogMonitoring().IsEnabled() { if meta.FindStatusCondition(*r.dk.Conditions(), oaConnectionInfoConditionType) == nil { return nil // no condition == nothing is there to clean up } query := k8ssecret.Query(r.client, r.apiReader, log) - err := query.Delete(ctx, &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: r.dk.OneagentTenantSecret(), Namespace: r.dk.Namespace}}) + err := query.Delete(ctx, &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: r.dk.OneAgent().GetTenantSecret(), Namespace: r.dk.Namespace}}) if err != nil { log.Error(err, "failed to clean-up OneAgent tenant-secret") } meta.RemoveStatusCondition(r.dk.Conditions(), oaConnectionInfoConditionType) - r.dk.Status.OneAgent.ConnectionInfoStatus = dynakube.OneAgentConnectionInfoStatus{} + r.dk.Status.OneAgent.ConnectionInfoStatus = oneagent.ConnectionInfoStatus{} return nil // clean-up shouldn't cause a failure } @@ -79,7 +80,7 @@ func (r *reconciler) Reconcile(ctx context.Context) error { } func (r *reconciler) reconcileConnectionInfo(ctx context.Context) error { - secretNamespacedName := types.NamespacedName{Name: r.dk.OneagentTenantSecret(), Namespace: r.dk.Namespace} + secretNamespacedName := types.NamespacedName{Name: r.dk.OneAgent().GetTenantSecret(), Namespace: r.dk.Namespace} if !conditions.IsOutdated(r.timeProvider, r.dk, oaConnectionInfoConditionType) { isSecretPresent, err := connectioninfo.IsTenantSecretPresent(ctx, r.apiReader, secretNamespacedName, log) @@ -122,7 +123,7 @@ func (r *reconciler) reconcileConnectionInfo(ctx context.Context) error { return NoOneAgentCommunicationHostsError } - err = r.createTenantTokenSecret(ctx, r.dk.OneagentTenantSecret(), connectionInfo.ConnectionInfo) + err = r.createTenantTokenSecret(ctx, r.dk.OneAgent().GetTenantSecret(), connectionInfo.ConnectionInfo) if err != nil { return err } @@ -138,10 +139,10 @@ func (r *reconciler) setDynakubeStatus(connectionInfo dtclient.OneAgentConnectio copyCommunicationHosts(&r.dk.Status.OneAgent.ConnectionInfoStatus, connectionInfo.CommunicationHosts) } -func copyCommunicationHosts(dest *dynakube.OneAgentConnectionInfoStatus, src []dtclient.CommunicationHost) { - dest.CommunicationHosts = make([]dynakube.CommunicationHostStatus, 0, len(src)) +func copyCommunicationHosts(dest *oneagent.ConnectionInfoStatus, src []dtclient.CommunicationHost) { + dest.CommunicationHosts = make([]oneagent.CommunicationHostStatus, 0, len(src)) for _, host := range src { - dest.CommunicationHosts = append(dest.CommunicationHosts, dynakube.CommunicationHostStatus{ + dest.CommunicationHosts = append(dest.CommunicationHosts, oneagent.CommunicationHostStatus{ Protocol: host.Protocol, Host: host.Host, Port: host.Port, diff --git a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go index d1ab62ca84..a16e811877 100644 --- a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go +++ b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" @@ -38,7 +39,7 @@ func TestReconcile(t *testing.T) { t.Run("cleanup when oneagent is not needed", func(t *testing.T) { dk := getTestDynakube() - dk.Status.OneAgent.ConnectionInfoStatus = dynakube.OneAgentConnectionInfoStatus{ + dk.Status.OneAgent.ConnectionInfoStatus = oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: testOutdated, Endpoints: testOutdated, @@ -48,7 +49,7 @@ func TestReconcile(t *testing.T) { dk.Spec = dynakube.DynaKubeSpec{} - fakeClient := fake.NewClient(&corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: dk.OneagentTenantSecret(), Namespace: dk.Namespace}}) + fakeClient := fake.NewClient(&corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: dk.OneAgent().GetTenantSecret(), Namespace: dk.Namespace}}) dtc := dtclientmock.NewClient(t) r := NewReconciler(fakeClient, fakeClient, dtc, dk) @@ -60,21 +61,21 @@ func TestReconcile(t *testing.T) { require.Nil(t, condition) var actualSecret corev1.Secret - err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneagentTenantSecret(), Namespace: testNamespace}, &actualSecret) + err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneAgent().GetTenantSecret(), Namespace: testNamespace}, &actualSecret) require.Error(t, err) assert.True(t, k8serrors.IsNotFound(err)) }) t.Run("does not cleanup when only host oneagent is needed", func(t *testing.T) { dk := getTestDynakube() - dk.Status.OneAgent.ConnectionInfoStatus = dynakube.OneAgentConnectionInfoStatus{ + dk.Status.OneAgent.ConnectionInfoStatus = oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: testOutdated, Endpoints: testOutdated, }, } dk.Spec = dynakube.DynaKubeSpec{} - dk.Spec.OneAgent.ClassicFullStack = &dynakube.HostInjectSpec{} + dk.Spec.OneAgent.ClassicFullStack = &oneagent.HostInjectSpec{} conditions.SetSecretCreated(dk.Conditions(), oaConnectionInfoConditionType, "testing") @@ -135,7 +136,7 @@ func TestReconcile(t *testing.T) { assert.Equal(t, getTestCommunicationHosts(), dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts) var actualSecret corev1.Secret - err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneagentTenantSecret(), Namespace: testNamespace}, &actualSecret) + err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneAgent().GetTenantSecret(), Namespace: testNamespace}, &actualSecret) require.NoError(t, err) assert.Equal(t, []byte(testTenantToken), actualSecret.Data[connectioninfo.TenantTokenKey]) @@ -150,7 +151,7 @@ func TestReconcile(t *testing.T) { dtc := dtclientmock.NewClient(t) dtc.On("GetOneAgentConnectionInfo", mock.AnythingOfType("context.backgroundCtx")).Return(getTestOneAgentConnectionInfo(), nil) - dk.Status.OneAgent.ConnectionInfoStatus = dynakube.OneAgentConnectionInfoStatus{ + dk.Status.OneAgent.ConnectionInfoStatus = oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: testOutdated, Endpoints: testOutdated, @@ -169,7 +170,7 @@ func TestReconcile(t *testing.T) { assert.Equal(t, testTenantEndpoints, dk.Status.OneAgent.ConnectionInfoStatus.Endpoints) var actualSecret corev1.Secret - err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneagentTenantSecret(), Namespace: testNamespace}, &actualSecret) + err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneAgent().GetTenantSecret(), Namespace: testNamespace}, &actualSecret) require.NoError(t, err) assert.Equal(t, []byte(testTenantToken), actualSecret.Data[connectioninfo.TenantTokenKey]) @@ -184,7 +185,7 @@ func TestReconcile(t *testing.T) { fakeClient := fake.NewClient(dk, buildOneAgentTenantSecret(dk, testOutdated)) dtc := dtclientmock.NewClient(t) - dk.Status.OneAgent.ConnectionInfoStatus = dynakube.OneAgentConnectionInfoStatus{ + dk.Status.OneAgent.ConnectionInfoStatus = oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: testOutdated, Endpoints: testOutdated, @@ -200,7 +201,7 @@ func TestReconcile(t *testing.T) { assert.Equal(t, testOutdated, dk.Status.OneAgent.ConnectionInfoStatus.Endpoints) var actualSecret corev1.Secret - err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneagentTenantSecret(), Namespace: testNamespace}, &actualSecret) + err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneAgent().GetTenantSecret(), Namespace: testNamespace}, &actualSecret) require.NoError(t, err) assert.Equal(t, []byte(testOutdated), actualSecret.Data[connectioninfo.TenantTokenKey]) @@ -216,7 +217,7 @@ func TestReconcile(t *testing.T) { dtc := dtclientmock.NewClient(t) dtc.On("GetOneAgentConnectionInfo", mock.AnythingOfType("context.backgroundCtx")).Return(getTestOneAgentConnectionInfo(), nil) - dk.Status.OneAgent.ConnectionInfoStatus = dynakube.OneAgentConnectionInfoStatus{ + dk.Status.OneAgent.ConnectionInfoStatus = oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: testOutdated, Endpoints: testOutdated, @@ -232,7 +233,7 @@ func TestReconcile(t *testing.T) { assert.Equal(t, testTenantEndpoints, dk.Status.OneAgent.ConnectionInfoStatus.Endpoints) var actualSecret corev1.Secret - err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneagentTenantSecret(), Namespace: testNamespace}, &actualSecret) + err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneAgent().GetTenantSecret(), Namespace: testNamespace}, &actualSecret) require.NoError(t, err) assert.Equal(t, []byte(testTenantToken), actualSecret.Data[connectioninfo.TenantTokenKey]) @@ -249,7 +250,7 @@ func TestReconcile(t *testing.T) { dtc := dtclientmock.NewClient(t) dtc.On("GetOneAgentConnectionInfo", mock.AnythingOfType("context.backgroundCtx")).Return(getTestOneAgentConnectionInfo(), nil) - dk.Status.OneAgent.ConnectionInfoStatus = dynakube.OneAgentConnectionInfoStatus{ + dk.Status.OneAgent.ConnectionInfoStatus = oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: testOutdated, Endpoints: testOutdated, @@ -265,7 +266,7 @@ func TestReconcile(t *testing.T) { assert.Equal(t, testTenantEndpoints, dk.Status.OneAgent.ConnectionInfoStatus.Endpoints) var actualSecret corev1.Secret - err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneagentTenantSecret(), Namespace: testNamespace}, &actualSecret) + err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneAgent().GetTenantSecret(), Namespace: testNamespace}, &actualSecret) require.NoError(t, err) assert.Equal(t, []byte(testTenantToken), actualSecret.Data[connectioninfo.TenantTokenKey]) @@ -284,8 +285,8 @@ func TestReconcile_NoOneAgentCommunicationHosts(t *testing.T) { Name: testName, }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, } @@ -323,8 +324,8 @@ func getTestDynakube() *dynakube.DynaKube { Name: testName, }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, } @@ -333,7 +334,7 @@ func getTestDynakube() *dynakube.DynaKube { func buildOneAgentTenantSecret(dk *dynakube.DynaKube, token string) *corev1.Secret { return &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: dk.OneagentTenantSecret(), + Name: dk.OneAgent().GetTenantSecret(), Namespace: testNamespace, }, Data: map[string][]byte{ @@ -342,8 +343,8 @@ func buildOneAgentTenantSecret(dk *dynakube.DynaKube, token string) *corev1.Secr } } -func getTestCommunicationHosts() []dynakube.CommunicationHostStatus { - return []dynakube.CommunicationHostStatus{ +func getTestCommunicationHosts() []oneagent.CommunicationHostStatus { + return []oneagent.CommunicationHostStatus{ { Protocol: "http", Host: "dummyhost", diff --git a/pkg/controllers/dynakube/controller_system_test.go b/pkg/controllers/dynakube/controller_system_test.go index d43f8c7927..1d48ec7593 100644 --- a/pkg/controllers/dynakube/controller_system_test.go +++ b/pkg/controllers/dynakube/controller_system_test.go @@ -11,6 +11,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" ag "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" @@ -20,7 +21,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/injection" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/kspm" logmon "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/oneagent" + oneagentcontroller "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" @@ -291,7 +292,7 @@ func TestAPIError(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{HostInjectSpec: dynakube.HostInjectSpec{}}}, + OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{HostInjectSpec: oneagent.HostInjectSpec{}}}, ActiveGate: activegate.Spec{ Capabilities: []activegate.CapabilityDisplayName{ activegate.KubeMonCapability.DisplayName, @@ -433,7 +434,7 @@ func createFakeClientAndReconciler(t *testing.T, mockClient dtclient.Client, dk activeGateReconcilerBuilder: ag.NewReconciler, apiMonitoringReconcilerBuilder: apimonitoring.NewReconciler, injectionReconcilerBuilder: injection.NewReconciler, - oneAgentReconcilerBuilder: oneagent.NewReconciler, + oneAgentReconcilerBuilder: oneagentcontroller.NewReconciler, logMonitoringReconcilerBuilder: logmon.NewReconciler, proxyReconcilerBuilder: proxy.NewReconciler, extensionReconcilerBuilder: extension.NewReconciler, diff --git a/pkg/controllers/dynakube/controller_test.go b/pkg/controllers/dynakube/controller_test.go index a4048126eb..e72ed465d8 100644 --- a/pkg/controllers/dynakube/controller_test.go +++ b/pkg/controllers/dynakube/controller_test.go @@ -12,6 +12,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" ag "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate" @@ -22,7 +23,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/istio" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/oneagent" + oneagentcontroller "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" @@ -327,7 +328,7 @@ func TestReconcileComponents(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: "this-is-an-api-url", - OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}, + OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}, ActiveGate: activegate.Spec{Capabilities: []activegate.CapabilityDisplayName{activegate.KubeMonCapability.DisplayName}}, }, } @@ -420,7 +421,7 @@ func createActivegateReconcilerBuilder(reconciler controllers.Reconciler) ag.Rec } } -func createOneAgentReconcilerBuilder(reconciler controllers.Reconciler) oneagent.ReconcilerBuilder { +func createOneAgentReconcilerBuilder(reconciler controllers.Reconciler) oneagentcontroller.ReconcilerBuilder { return func(_ client.Client, _ client.Reader, _ dtclient.Client, _ *dynakube.DynaKube, _ token.Tokens, _ string) controllers.Reconciler { return reconciler } @@ -472,8 +473,8 @@ func TestGetDynakube(t *testing.T) { Namespace: testNamespace, }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, }) @@ -689,13 +690,13 @@ func getTestDynkubeStatus() *dynakube.DynaKubeStatus { Endpoints: "endpoint", }, }, - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: testUUID, Endpoints: "endpoint", }, - CommunicationHosts: []dynakube.CommunicationHostStatus{ + CommunicationHosts: []oneagent.CommunicationHostStatus{ { Protocol: "http", Host: "localhost", @@ -712,7 +713,7 @@ func createTenantSecrets(dk *dynakube.DynaKube) []client.Object { return []client.Object{ &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: dk.OneagentTenantSecret(), + Name: dk.OneAgent().GetTenantSecret(), Namespace: testNamespace, }, Data: map[string][]byte{ diff --git a/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata.go b/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata.go index 6f64886154..d38cb81e9a 100644 --- a/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata.go +++ b/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata.go @@ -15,13 +15,13 @@ type DeploymentMetadata struct { func GetOneAgentDeploymentType(dk dynakube.DynaKube) string { switch { - case dk.HostMonitoringMode(): + case dk.OneAgent().IsHostMonitoringMode(): return HostMonitoringDeploymentType - case dk.CloudNativeFullstackMode(): + case dk.OneAgent().IsCloudNativeFullstackMode(): return CloudNativeDeploymentType - case dk.ClassicFullStackMode(): + case dk.OneAgent().IsClassicFullStackMode(): return ClassicFullStackDeploymentType - case dk.ApplicationMonitoringMode(): + case dk.OneAgent().IsApplicationMonitoringMode(): return ApplicationMonitoringDeploymentType } diff --git a/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata_test.go b/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata_test.go index 06e6a7869b..b30493039d 100644 --- a/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata_test.go +++ b/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/stretchr/testify/assert" ) @@ -46,13 +47,13 @@ func TestFormatKeyValue(t *testing.T) { func TestGetOneAgentDeploymentType(t *testing.T) { tests := []struct { - oneAgentSpec dynakube.OneAgentSpec + oneAgentSpec oneagent.Spec expectedDeploymentType string }{ - {dynakube.OneAgentSpec{HostMonitoring: &dynakube.HostInjectSpec{}}, HostMonitoringDeploymentType}, - {dynakube.OneAgentSpec{ClassicFullStack: &dynakube.HostInjectSpec{}}, ClassicFullStackDeploymentType}, - {dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}, CloudNativeDeploymentType}, - {dynakube.OneAgentSpec{ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}}, ApplicationMonitoringDeploymentType}, + {oneagent.Spec{HostMonitoring: &oneagent.HostInjectSpec{}}, HostMonitoringDeploymentType}, + {oneagent.Spec{ClassicFullStack: &oneagent.HostInjectSpec{}}, ClassicFullStackDeploymentType}, + {oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}, CloudNativeDeploymentType}, + {oneagent.Spec{ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}}, ApplicationMonitoringDeploymentType}, } for _, test := range tests { diff --git a/pkg/controllers/dynakube/deploymentmetadata/reconciler.go b/pkg/controllers/dynakube/deploymentmetadata/reconciler.go index f95edf532a..936c081a79 100644 --- a/pkg/controllers/dynakube/deploymentmetadata/reconciler.go +++ b/pkg/controllers/dynakube/deploymentmetadata/reconciler.go @@ -40,7 +40,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { } func (r *Reconciler) addOneAgentDeploymentMetadata(configMapData map[string]string) { - if !r.dk.NeedsOneAgent() { + if !r.dk.OneAgent().IsDaemonsetRequired() { return } @@ -56,7 +56,7 @@ func (r *Reconciler) addActiveGateDeploymentMetadata(configMapData map[string]st } func (r *Reconciler) addOperatorVersionInfo(configMapData map[string]string) { - if !r.dk.NeedsOneAgent() { // Currently only used for oneAgent args + if !r.dk.OneAgent().IsDaemonsetRequired() { // Currently only used for oneAgent args return } diff --git a/pkg/controllers/dynakube/deploymentmetadata/reconciler_test.go b/pkg/controllers/dynakube/deploymentmetadata/reconciler_test.go index 3781d6bf2a..202f170bc6 100644 --- a/pkg/controllers/dynakube/deploymentmetadata/reconciler_test.go +++ b/pkg/controllers/dynakube/deploymentmetadata/reconciler_test.go @@ -6,6 +6,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -71,8 +72,8 @@ func TestReconcile(t *testing.T) { t.Run(`create configmap with 1 key, if only oneagent is needed`, func(t *testing.T) { dk := createTestDynakube( &dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }) @@ -112,8 +113,8 @@ func TestReconcile(t *testing.T) { t.Run(`create configmap with 2 keys, if both oneagent and activegate is needed`, func(t *testing.T) { dk := createTestDynakube( &dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, ActiveGate: activegate.Spec{ Capabilities: []activegate.CapabilityDisplayName{ diff --git a/pkg/controllers/dynakube/dtpullsecret/generate_test.go b/pkg/controllers/dynakube/dtpullsecret/generate_test.go index 6840d07917..f2022097aa 100644 --- a/pkg/controllers/dynakube/dtpullsecret/generate_test.go +++ b/pkg/controllers/dynakube/dtpullsecret/generate_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/stretchr/testify/assert" @@ -39,8 +40,8 @@ func TestReconciler_GenerateData(t *testing.T) { APIURL: testApiUrl, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: testTenant, }, diff --git a/pkg/controllers/dynakube/dtpullsecret/reconciler.go b/pkg/controllers/dynakube/dtpullsecret/reconciler.go index 8be1154caf..4b2f16a13e 100644 --- a/pkg/controllers/dynakube/dtpullsecret/reconciler.go +++ b/pkg/controllers/dynakube/dtpullsecret/reconciler.go @@ -39,7 +39,7 @@ func NewReconciler(clt client.Client, apiReader client.Reader, dk *dynakube.Dyna } func (r *Reconciler) Reconcile(ctx context.Context) error { - if !(r.dk.NeedsOneAgent() || r.dk.ActiveGate().IsEnabled()) { + if !(r.dk.OneAgent().IsDaemonsetRequired() || r.dk.ActiveGate().IsEnabled()) { if meta.FindStatusCondition(*r.dk.Conditions(), PullSecretConditionType) == nil { return nil // no condition == nothing is there to clean up } diff --git a/pkg/controllers/dynakube/dtpullsecret/reconciler_test.go b/pkg/controllers/dynakube/dtpullsecret/reconciler_test.go index e18c64e2fc..65734bc261 100644 --- a/pkg/controllers/dynakube/dtpullsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/dtpullsecret/reconciler_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/stretchr/testify/assert" @@ -75,7 +76,7 @@ func TestReconciler_Reconcile(t *testing.T) { Name: testName, }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}, + OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}, }, } fakeClient := errorClient{} @@ -230,7 +231,7 @@ func TestReconciler_Reconcile(t *testing.T) { require.NoError(t, err) - dk.Spec.OneAgent = dynakube.OneAgentSpec{} + dk.Spec.OneAgent = oneagent.Spec{} err = r.Reconcile(context.Background()) require.NoError(t, err) @@ -251,7 +252,7 @@ func createTestDynakube() *dynakube.DynaKube { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}, + OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}, }, }) } diff --git a/pkg/controllers/dynakube/dynatraceclient/builder.go b/pkg/controllers/dynakube/dynatraceclient/builder.go index 7dfe81f72a..9eb33dcd46 100644 --- a/pkg/controllers/dynakube/dynatraceclient/builder.go +++ b/pkg/controllers/dynakube/dynatraceclient/builder.go @@ -76,7 +76,7 @@ func (dynatraceClientBuilder builder) Build() (dtclient.Client, error) { opts := newOptions(dynatraceClientBuilder.context()) opts.appendCertCheck(dynatraceClientBuilder.dk.Spec.SkipCertCheck) opts.appendNetworkZone(dynatraceClientBuilder.dk.Spec.NetworkZone) - opts.appendHostGroup(dynatraceClientBuilder.dk.HostGroup()) + opts.appendHostGroup(dynatraceClientBuilder.dk.OneAgent().GetHostGroup()) err := opts.appendProxySettings(apiReader, &dynatraceClientBuilder.dk) if err != nil { diff --git a/pkg/controllers/dynakube/injection/reconciler.go b/pkg/controllers/dynakube/injection/reconciler.go index c8cb201644..bd6069d402 100644 --- a/pkg/controllers/dynakube/injection/reconciler.go +++ b/pkg/controllers/dynakube/injection/reconciler.go @@ -75,7 +75,7 @@ func (r *reconciler) Reconcile(ctx context.Context) error { // because the 2 injection type we have share the label that the webhook is listening to, we can only clean that label up if both are disabled // but we should only clean-up the labels after everything else is cleaned up because the clean-up for the secrets depend on the label still being there // but we have to do the mapping before everything when its necessary - if !r.dk.NeedAppInjection() && !r.dk.MetadataEnrichmentEnabled() { + if !r.dk.OneAgent().IsAppInjectionNeeded() && !r.dk.MetadataEnrichmentEnabled() { defer r.unmapDynakube(ctx) } else { dkMapper := r.createDynakubeMapper(ctx) @@ -145,7 +145,7 @@ func (r *reconciler) setupOneAgentInjection(ctx context.Context) error { } } - if !r.dk.NeedAppInjection() { + if !r.dk.OneAgent().IsAppInjectionNeeded() { r.cleanupOneAgentInjection(ctx) return nil @@ -160,7 +160,7 @@ func (r *reconciler) setupOneAgentInjection(ctx context.Context) error { return err } - if r.dk.ApplicationMonitoringMode() { + if r.dk.OneAgent().IsApplicationMonitoringMode() { r.dk.Status.SetPhase(status.Running) } diff --git a/pkg/controllers/dynakube/injection/reconciler_test.go b/pkg/controllers/dynakube/injection/reconciler_test.go index 85c5f782d4..f3b17de950 100644 --- a/pkg/controllers/dynakube/injection/reconciler_test.go +++ b/pkg/controllers/dynakube/injection/reconciler_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" @@ -85,9 +86,9 @@ func TestReconciler(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ testNamespaceSelectorLabel: testDynakube, @@ -130,7 +131,7 @@ func TestReconciler(t *testing.T) { err := rec.Reconcile(context.Background()) require.NoError(t, err) - assertSecretFound(t, clt, dk.OneagentTenantSecret(), dk.Namespace) + assertSecretFound(t, clt, dk.OneAgent().GetTenantSecret(), dk.Namespace) assertSecretFound(t, clt, consts.AgentInitSecretName, testNamespace) assertSecretNotFound(t, clt, consts.AgentInitSecretName, testNamespace2) assertSecretFound(t, clt, consts.EnrichmentEndpointSecretName, testNamespace) @@ -222,9 +223,9 @@ func TestReconciler(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ testNamespaceSelectorLabel: testDynakube, @@ -262,7 +263,7 @@ func TestReconciler(t *testing.T) { func TestRemoveAppInjection(t *testing.T) { clt := clientRemoveAppInjection() - rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, dynakube.OneAgentSpec{ + rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, oneagent.Spec{ CloudNativeFullStack: nil, }) rec.versionReconciler = createVersionReconcilerMock(t) @@ -296,8 +297,8 @@ func TestRemoveAppInjection(t *testing.T) { func TestSetupOneAgentInjection(t *testing.T) { t.Run(`no injection - ClassicFullStack`, func(t *testing.T) { clt := clientNoInjection() - rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }) rec.versionReconciler = createVersionReconcilerMock(t) rec.connectionInfoReconciler = createGenericReconcilerMock(t) @@ -313,8 +314,8 @@ func TestSetupOneAgentInjection(t *testing.T) { t.Run(`no injection - HostMonitoring`, func(t *testing.T) { clt := clientNoInjection() - rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }) rec.versionReconciler = createVersionReconcilerMock(t) rec.connectionInfoReconciler = createGenericReconcilerMock(t) @@ -330,8 +331,8 @@ func TestSetupOneAgentInjection(t *testing.T) { t.Run(`injection - ApplicationMonitoring`, func(t *testing.T) { clt := clientOneAgentInjection() - rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }) rec.versionReconciler = createVersionReconcilerMock(t) rec.connectionInfoReconciler = createGenericReconcilerMock(t) @@ -356,8 +357,8 @@ func TestSetupOneAgentInjection(t *testing.T) { t.Run(`injection - CloudNativeFullStack`, func(t *testing.T) { clt := clientOneAgentInjection() - rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }) rec.versionReconciler = createVersionReconcilerMock(t) rec.connectionInfoReconciler = createGenericReconcilerMock(t) @@ -384,8 +385,8 @@ func TestSetupOneAgentInjection(t *testing.T) { func TestSetupEnrichmentInjection(t *testing.T) { t.Run(`no enrichment injection`, func(t *testing.T) { clt := clientNoInjection() - rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }) rec.enrichmentRulesReconciler = createGenericReconcilerMock(t) rec.monitoredEntitiesReconciler = createGenericReconcilerMock(t) @@ -400,8 +401,8 @@ func TestSetupEnrichmentInjection(t *testing.T) { t.Run(`enrichment injection`, func(t *testing.T) { clt := clientEnrichmentInjection() - rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }) rec.enrichmentRulesReconciler = createGenericReconcilerMock(t) rec.monitoredEntitiesReconciler = createGenericReconcilerMock(t) @@ -422,7 +423,7 @@ func newIstioTestingClient(fakeClient *fakeistio.Clientset, dk *dynakube.DynaKub } } -func createReconciler(clt client.Client, dynakubeName string, dynakubeNamespace string, oneAgentSpec dynakube.OneAgentSpec) reconciler { +func createReconciler(clt client.Client, dynakubeName string, dynakubeNamespace string, oneAgentSpec oneagent.Spec) reconciler { return reconciler{ client: clt, apiReader: clt, diff --git a/pkg/controllers/dynakube/istio/reconciler.go b/pkg/controllers/dynakube/istio/reconciler.go index 10fc874808..2bbef178ac 100644 --- a/pkg/controllers/dynakube/istio/reconciler.go +++ b/pkg/controllers/dynakube/istio/reconciler.go @@ -67,7 +67,7 @@ func (r *reconciler) ReconcileCodeModuleCommunicationHosts(ctx context.Context, return errors.New("can't reconcile oneagent communication hosts of nil dynakube") } - if !dk.NeedAppInjection() { + if !dk.OneAgent().IsAppInjectionNeeded() { if isIstioConfigured(dk, CodeModuleComponent) { log.Info("appinjection disabled, cleaning up") diff --git a/pkg/controllers/dynakube/istio/reconciler_test.go b/pkg/controllers/dynakube/istio/reconciler_test.go index 9ebf9d88f3..14ed772966 100644 --- a/pkg/controllers/dynakube/istio/reconciler_test.go +++ b/pkg/controllers/dynakube/istio/reconciler_test.go @@ -9,6 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -300,7 +301,7 @@ func TestReconcileOneAgentCommunicationHosts(t *testing.T) { require.Equal(t, "IstioForCodeModuleChanged", statusCondition.Reason) dk.Spec.OneAgent.CloudNativeFullStack = nil - dk.Spec.OneAgent.HostMonitoring = &dynakube.HostInjectSpec{} + dk.Spec.OneAgent.HostMonitoring = &oneagent.HostInjectSpec{} err = r.ReconcileCodeModuleCommunicationHosts(ctx, dk) require.NoError(t, err) @@ -490,15 +491,15 @@ func createTestDynaKube() *dynakube.DynaKube { activegate.RoutingCapability.DisplayName, }, }, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, DynatraceApiRequestThreshold: ptr.To(uint16(15)), }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ - CommunicationHosts: []dynakube.CommunicationHostStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ + CommunicationHosts: []oneagent.CommunicationHostStatus{ { Protocol: fqdnHost.Protocol, Host: fqdnHost.Host, diff --git a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go index e6f88b4479..8240decfcf 100644 --- a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go @@ -109,7 +109,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) func (r *Reconciler) getSecretData(ctx context.Context) (map[string][]byte, error) { tenantToken, err := k8ssecret.GetDataFromSecretName(ctx, r.apiReader, types.NamespacedName{ - Name: r.dk.OneagentTenantSecret(), + Name: r.dk.OneAgent().GetTenantSecret(), Namespace: r.dk.Namespace, }, connectioninfo.TenantTokenKey, log) if err != nil { @@ -126,7 +126,7 @@ func (r *Reconciler) getSecretData(ctx context.Context) (map[string][]byte, erro } deploymentConfigContent := map[string]string{ - serverKey: fmt.Sprintf("{%s}", r.dk.OneAgentEndpoints()), + serverKey: fmt.Sprintf("{%s}", r.dk.OneAgent().GetEndpoints()), tenantKey: tenantUUID, tenantTokenKey: tenantToken, hostIdSourceKey: "k8s-node-name", diff --git a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go index f34ed4aad9..4c7067cae8 100644 --- a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go @@ -10,6 +10,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/pkg/errors" @@ -35,7 +36,7 @@ func TestReconcile(t *testing.T) { t.Run("Only clean up if not standalone", func(t *testing.T) { dk := createDynakube(true) - dk.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} + dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} conditions.SetSecretCreated(dk.Conditions(), lmcConditionType, "testing") mockK8sClient := createK8sClientWithConfigSecret() @@ -157,8 +158,8 @@ func createDynakube(isLogMonitoringEnabled bool) *dynakube.DynaKube { LogMonitoring: logMonitoringSpec, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: "test-uuid", Endpoints: "https://endpoint1.com;https://endpoint2.com", @@ -194,7 +195,7 @@ func createK8sClientWithOneAgentTenantSecret(dk *dynakube.DynaKube, token string &corev1.Secret{ Data: map[string][]byte{connectioninfo.TenantTokenKey: []byte(token)}, ObjectMeta: metav1.ObjectMeta{ - Name: dk.OneagentTenantSecret(), + Name: dk.OneAgent().GetTenantSecret(), Namespace: dkNamespace, }, }, diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go index 0db87b730b..6ae01c42c3 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/pkg/errors" @@ -34,7 +35,7 @@ func TestReconcile(t *testing.T) { t.Run("Only clean up if not standalone", func(t *testing.T) { dk := createDynakube(true) - dk.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} + dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} conditions.SetDaemonSetCreated(dk.Conditions(), conditionType, "testing") previousDaemonSet := appsv1.DaemonSet{} @@ -298,8 +299,8 @@ func createDynakube(isEnabled bool) *dynakube.DynaKube { LogMonitoring: logMonitoring, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: "test-uuid", }, diff --git a/pkg/controllers/dynakube/oneagent/daemonset/arguments.go b/pkg/controllers/dynakube/oneagent/daemonset/arguments.go index a41ec89c52..11e11467a2 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/arguments.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/arguments.go @@ -21,7 +21,7 @@ func (b *builder) arguments() ([]string, error) { prioritymap.WithAllowDuplicates(), ) - isProxyAsEnvDeprecated, err := isProxyAsEnvVarDeprecated(b.dk.OneAgentVersion()) + isProxyAsEnvDeprecated, err := isProxyAsEnvVarDeprecated(b.dk.OneAgent().GetVersion()) if err != nil { return []string{}, err } @@ -38,9 +38,9 @@ func (b *builder) arguments() ([]string, error) { appendOperatorVersionArg(argMap) appendImmutableImageArgs(argMap) - if b.dk.ClassicFullStackMode() { + if b.dk.OneAgent().IsClassicFullStackMode() { argMap.Append(argumentPrefix+"set-host-id-source", classicHostIdSource) - } else if b.dk.HostMonitoringMode() || b.dk.CloudNativeFullstackMode() { + } else if b.dk.OneAgent().IsHostMonitoringMode() || b.dk.OneAgent().IsCloudNativeFullstackMode() { argMap.Append(argumentPrefix+"set-host-id-source", inframonHostIdSource) } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go b/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go index 351c688fab..e74a69e525 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -49,8 +50,8 @@ func TestArguments(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Args: []string{testValue}, }, }, @@ -72,7 +73,7 @@ func TestArguments(t *testing.T) { args := []string{testValue} builder := builder{ dk: &dynakube.DynaKube{}, - hostInjectSpec: &dynakube.HostInjectSpec{Args: args}, + hostInjectSpec: &oneagent.HostInjectSpec{Args: args}, } arguments, _ := builder.arguments() @@ -96,7 +97,7 @@ func TestArguments(t *testing.T) { } builder := builder{ dk: &dynakube.DynaKube{}, - hostInjectSpec: &dynakube.HostInjectSpec{Args: args}, + hostInjectSpec: &oneagent.HostInjectSpec{Args: args}, } arguments, _ := builder.arguments() @@ -121,7 +122,7 @@ func TestArguments(t *testing.T) { Proxy: &value.Source{Value: "something"}, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ Version: "1.285.0.20240122-141707", }, @@ -201,7 +202,7 @@ func TestArguments(t *testing.T) { } builder := builder{ dk: &dynakube.DynaKube{}, - hostInjectSpec: &dynakube.HostInjectSpec{Args: args}, + hostInjectSpec: &oneagent.HostInjectSpec{Args: args}, } arguments, _ := builder.arguments() @@ -231,8 +232,8 @@ func TestArguments(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ Proxy: &value.Source{Value: testValue}, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, ActiveGate: activegate.Spec{ Capabilities: []activegate.CapabilityDisplayName{activegate.RoutingCapability.DisplayName}, @@ -253,8 +254,8 @@ func TestArguments(t *testing.T) { func TestPodSpec_Arguments(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Args: []string{testKey, testValue, testUID}, }, }, @@ -317,8 +318,8 @@ func TestPodSpec_Arguments(t *testing.T) { t.Run(`has host-id-source arg for hostMonitoring`, func(t *testing.T) { hostMonInstance := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ Args: []string{testKey, testValue, testUID}, }, }, @@ -341,9 +342,9 @@ func TestPodSpec_Arguments(t *testing.T) { t.Run(`has host-id-source arg for cloudNativeFullstack`, func(t *testing.T) { cloudNativeInstance := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{Args: []string{testKey, testValue, testUID}}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{Args: []string{testKey, testValue, testUID}}, }, }, }, @@ -363,9 +364,9 @@ func TestPodSpec_Arguments(t *testing.T) { t.Run(`has host-group for classicFullstack`, func(t *testing.T) { classicInstance := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ HostGroup: testNewHostGroupName, - ClassicFullStack: &dynakube.HostInjectSpec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Args: []string{testOldHostGroupArgument}, }, }, @@ -385,10 +386,10 @@ func TestPodSpec_Arguments(t *testing.T) { t.Run(`has host-group for cloudNativeFullstack`, func(t *testing.T) { cloudNativeInstance := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ HostGroup: testNewHostGroupName, - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{Args: []string{testOldHostGroupArgument}}, + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{Args: []string{testOldHostGroupArgument}}, }, }, }, @@ -407,9 +408,9 @@ func TestPodSpec_Arguments(t *testing.T) { t.Run(`has host-group for HostMonitoring`, func(t *testing.T) { hostMonitoringInstance := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ + OneAgent: oneagent.Spec{ HostGroup: testNewHostGroupName, - HostMonitoring: &dynakube.HostInjectSpec{ + HostMonitoring: &oneagent.HostInjectSpec{ Args: []string{testOldHostGroupArgument}, }, }, diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go index b8c1c11026..0a8abd97f4 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go @@ -3,6 +3,7 @@ package daemonset import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/Dynatrace/dynatrace-operator/pkg/util/dtversion" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" @@ -59,7 +60,7 @@ type classicFullStack struct { type builder struct { dk *dynakube.DynaKube - hostInjectSpec *dynakube.HostInjectSpec + hostInjectSpec *oneagent.HostInjectSpec clusterID string deploymentType string } @@ -107,7 +108,7 @@ func (hm *hostMonitoring) BuildDaemonSet() (*appsv1.DaemonSet, error) { return nil, err } - daemonSet.Name = hm.dk.OneAgentDaemonsetName() + daemonSet.Name = hm.dk.OneAgent().GetDaemonsetName() if len(daemonSet.Spec.Template.Spec.Containers) > 0 { hm.appendInfraMonEnvVars(daemonSet) @@ -122,7 +123,7 @@ func (classic *classicFullStack) BuildDaemonSet() (*appsv1.DaemonSet, error) { return nil, err } - result.Name = classic.dk.OneAgentDaemonsetName() + result.Name = classic.dk.OneAgent().GetDaemonsetName() return result, nil } @@ -135,7 +136,7 @@ func (b *builder) BuildDaemonSet() (*appsv1.DaemonSet, error) { return nil, err } - versionLabelValue := dk.OneAgentVersion() + versionLabelValue := dk.OneAgent().GetVersion() appLabels := labels.NewAppLabels(labels.OneAgentComponentLabel, dk.Name, b.deploymentType, versionLabelValue) @@ -224,11 +225,11 @@ func (b *builder) podSpec() (corev1.PodSpec, error) { TerminationGracePeriodSeconds: ptr.To(defaultTerminationGracePeriod), } - if b.dk.NeedsOneAgentReadinessProbe() { + if b.dk.OneAgent().IsReadinessProbeNeeded() { podSpec.Containers[0].ReadinessProbe = b.getReadinessProbe() } - if b.dk.NeedsOneAgentLivenessProbe() { + if b.dk.OneAgent().IsLivenessProbeNeeded() { podSpec.Containers[0].LivenessProbe = b.getDefaultProbeFromStatus() } @@ -240,7 +241,7 @@ func (b *builder) immutableOneAgentImage() string { return "" } - return b.dk.OneAgentImage() + return b.dk.OneAgent().GetImage() } func (b *builder) tolerations() []corev1.Toleration { @@ -315,7 +316,7 @@ func (b *builder) imagePullSecrets() []corev1.LocalObjectReference { func (b *builder) securityContext() *corev1.SecurityContext { var securityContext corev1.SecurityContext - if b.dk != nil && b.dk.UseReadOnlyOneAgents() { + if b.dk != nil && b.dk.OneAgent().IsReadOnlyOneAgentsMode() { securityContext.RunAsNonRoot = ptr.To(true) securityContext.RunAsUser = ptr.To(int64(1000)) securityContext.RunAsGroup = ptr.To(int64(1000)) @@ -324,26 +325,26 @@ func (b *builder) securityContext() *corev1.SecurityContext { securityContext.ReadOnlyRootFilesystem = ptr.To(false) } - if b.dk != nil && b.dk.NeedsOneAgentPrivileged() { + if b.dk != nil && b.dk.OneAgent().IsPrivilegedNeeded() { securityContext.Privileged = ptr.To(true) } else { securityContext.Capabilities = defaultSecurityContextCapabilities() if b.dk != nil { switch { - case b.dk.HostMonitoringMode() && b.dk.Spec.OneAgent.HostMonitoring.SecCompProfile != "": + case b.dk.OneAgent().IsHostMonitoringMode() && b.dk.Spec.OneAgent.HostMonitoring.SecCompProfile != "": secCompName := b.dk.Spec.OneAgent.HostMonitoring.SecCompProfile securityContext.SeccompProfile = &corev1.SeccompProfile{ Type: corev1.SeccompProfileTypeLocalhost, LocalhostProfile: &secCompName, } - case b.dk.ClassicFullStackMode() && b.dk.Spec.OneAgent.ClassicFullStack.SecCompProfile != "": + case b.dk.OneAgent().IsClassicFullStackMode() && b.dk.Spec.OneAgent.ClassicFullStack.SecCompProfile != "": secCompName := b.dk.Spec.OneAgent.ClassicFullStack.SecCompProfile securityContext.SeccompProfile = &corev1.SeccompProfile{ Type: corev1.SeccompProfileTypeLocalhost, LocalhostProfile: &secCompName, } - case b.dk.CloudNativeFullstackMode() && b.dk.Spec.OneAgent.CloudNativeFullStack.SecCompProfile != "": + case b.dk.OneAgent().IsCloudNativeFullstackMode() && b.dk.Spec.OneAgent.CloudNativeFullStack.SecCompProfile != "": secCompName := b.dk.Spec.OneAgent.CloudNativeFullStack.SecCompProfile securityContext.SeccompProfile = &corev1.SeccompProfile{ Type: corev1.SeccompProfileTypeLocalhost, @@ -411,12 +412,12 @@ func (b *builder) getReadinessProbe() *corev1.Probe { // if the version is not set, ie.: unknown, we consider the OneAgent to support `ReadOnlyRootFilesystem`. func (b *builder) isRootFsReadonly() bool { if b.dk != nil && - b.dk.UseReadOnlyOneAgents() && - b.dk.OneAgentVersion() != "" && - b.dk.OneAgentVersion() != string(status.CustomImageVersionSource) { - agentSemver, err := dtversion.ToSemver(b.dk.OneAgentVersion()) + b.dk.OneAgent().IsReadOnlyOneAgentsMode() && + b.dk.OneAgent().GetVersion() != "" && + b.dk.OneAgent().GetVersion() != string(status.CustomImageVersionSource) { + agentSemver, err := dtversion.ToSemver(b.dk.OneAgent().GetVersion()) if err != nil { - log.Debug("Unable to determine OneAgent version to enable readonly pod filesystem, skipping", "version", b.dk.OneAgentVersion(), "error", err.Error()) + log.Debug("Unable to determine OneAgent version to enable readonly pod filesystem, skipping", "version", b.dk.OneAgent().GetVersion(), "error", err.Error()) return true } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go index 0735ba2a04..204a66c916 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/version" @@ -30,12 +31,12 @@ func TestUseImmutableImage(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ ImageID: imageID, }, @@ -59,12 +60,12 @@ func TestLabels(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ Version: testImageTag, }, @@ -97,8 +98,8 @@ func TestLabels(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } @@ -135,8 +136,8 @@ func TestCustomPullSecret(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, CustomPullSecret: testName, }, @@ -157,8 +158,8 @@ func TestResources(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } @@ -182,8 +183,8 @@ func TestResources(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ OneAgentResources: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceCPU: *cpuRequest, @@ -256,8 +257,8 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -283,12 +284,12 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ Version: "1.290.18.20240520-124108", }, @@ -312,12 +313,12 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ Version: "1.291.18.20240520-124108", }, @@ -346,8 +347,8 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -377,8 +378,8 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } @@ -405,8 +406,8 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { ObjectMeta: metav1.ObjectMeta{}, Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ SecCompProfile: customSecCompProfile, }, }, @@ -440,8 +441,8 @@ func TestHostMonitoring_SecurityContext(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: testURL, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ SecCompProfile: customSecCompProfile, }, }, @@ -518,7 +519,7 @@ func TestPodSpecProbes(t *testing.T) { builder := builder{ dk: &dynakube.DynaKube{ Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ Healthcheck: &expectedHealthcheck, }, }, @@ -551,7 +552,7 @@ func TestPodSpecProbes(t *testing.T) { builder := builder{ dk: &dynakube.DynaKube{ Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ Healthcheck: updatedHealthCheck, }, }, @@ -585,7 +586,7 @@ func TestPodSpecProbes(t *testing.T) { }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ Healthcheck: &expectedHealthcheck, }, }, @@ -607,7 +608,7 @@ func TestOneAgentResources(t *testing.T) { }) t.Run("get resources if hostInjection spec is set", func(t *testing.T) { builder := builder{ - hostInjectSpec: &dynakube.HostInjectSpec{ + hostInjectSpec: &oneagent.HostInjectSpec{ OneAgentResources: corev1.ResourceRequirements{ Requests: map[corev1.ResourceName]resource.Quantity{ corev1.ResourceCPU: *resource.NewScaledQuantity(2, 1), @@ -643,7 +644,7 @@ func TestNodeSelector(t *testing.T) { }) t.Run("returns nodeselector", func(t *testing.T) { dsBuilder := builder{ - hostInjectSpec: &dynakube.HostInjectSpec{ + hostInjectSpec: &oneagent.HostInjectSpec{ NodeSelector: map[string]string{testKey: testValue}, }, } @@ -662,7 +663,7 @@ func TestPriorityClass(t *testing.T) { }) t.Run("returns nodeselector", func(t *testing.T) { dsBuilder := builder{ - hostInjectSpec: &dynakube.HostInjectSpec{ + hostInjectSpec: &oneagent.HostInjectSpec{ PriorityClassName: testName, }, } @@ -681,7 +682,7 @@ func TestTolerations(t *testing.T) { }) t.Run("returns tolerations", func(t *testing.T) { dsBuilder := builder{ - hostInjectSpec: &dynakube.HostInjectSpec{ + hostInjectSpec: &oneagent.HostInjectSpec{ Tolerations: []corev1.Toleration{ { Key: testKey, @@ -752,7 +753,7 @@ func TestImmutableOneAgentImage(t *testing.T) { } image := dsBuilder.immutableOneAgentImage() - assert.Equal(t, dsBuilder.dk.OneAgentImage(), image) + assert.Equal(t, dsBuilder.dk.OneAgent().GetImage(), image) }) } @@ -760,9 +761,9 @@ func TestAnnotations(t *testing.T) { t.Run("cloud native has apparmor annotation by default", func(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{}, }, }, }, @@ -782,8 +783,8 @@ func TestAnnotations(t *testing.T) { t.Run("host monitoring has apparmor annotation by default", func(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -802,8 +803,8 @@ func TestAnnotations(t *testing.T) { t.Run("classic fullstack has apparmor annotation by default", func(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } @@ -822,9 +823,9 @@ func TestAnnotations(t *testing.T) { t.Run("annotations are added with cloud native", func(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ Annotations: map[string]string{ testKey: testName, }, @@ -849,8 +850,8 @@ func TestAnnotations(t *testing.T) { t.Run("annotations are added with host monitoring", func(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ Annotations: map[string]string{ testKey: testName, }, @@ -874,8 +875,8 @@ func TestAnnotations(t *testing.T) { t.Run("annotations are added with classic fullstack", func(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Annotations: map[string]string{ testKey: testName, }, @@ -902,9 +903,9 @@ func TestOneAgentHostGroup(t *testing.T) { t.Run("cloud native - host group settings", func(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ Args: []string{ "--set-host-group=oldgroup", }, @@ -935,12 +936,12 @@ func TestDefaultArguments(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: "https://ENVIRONMENTID.live.dynatrace.com/api", Tokens: name, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } - base.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []dynakube.CommunicationHostStatus{ + base.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{ { Protocol: "http", Host: "dummyhost", diff --git a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go index 5de52b8eca..09db67f88a 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go @@ -45,7 +45,7 @@ func (b *builder) environmentVariables() ([]corev1.EnvVar, error) { b.addReadOnlyEnv(envMap) b.addLogMonitoringEnv(envMap) - isProxyAsEnvDeprecated, err := isProxyAsEnvVarDeprecated(b.dk.OneAgentVersion()) + isProxyAsEnvDeprecated, err := isProxyAsEnvVarDeprecated(b.dk.OneAgent().GetVersion()) if err != nil { return []corev1.EnvVar{}, err } @@ -89,14 +89,14 @@ func (b *builder) addOperatorVersionInfoEnv(envVarMap *prioritymap.Map) { func (b *builder) addConnectionInfoEnvs(envVarMap *prioritymap.Map) { addDefaultValueSource(envVarMap, connectioninfo.EnvDtTenant, &corev1.EnvVarSource{ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ LocalObjectReference: corev1.LocalObjectReference{ - Name: b.dk.OneAgentConnectionInfoConfigMapName(), + Name: b.dk.OneAgent().GetConnectionInfoConfigMapName(), }, Key: connectioninfo.TenantUUIDKey, Optional: ptr.To(false), }}) addDefaultValueSource(envVarMap, connectioninfo.EnvDtServer, &corev1.EnvVarSource{ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ LocalObjectReference: corev1.LocalObjectReference{ - Name: b.dk.OneAgentConnectionInfoConfigMapName(), + Name: b.dk.OneAgent().GetConnectionInfoConfigMapName(), }, Key: connectioninfo.CommunicationEndpointsKey, Optional: ptr.To(false), @@ -122,7 +122,7 @@ func (b *builder) addProxyEnv(envVarMap *prioritymap.Map) { } func (b *builder) addReadOnlyEnv(envVarMap *prioritymap.Map) { - if b.dk != nil && b.dk.UseReadOnlyOneAgents() { + if b.dk != nil && b.dk.OneAgent().IsReadOnlyOneAgentsMode() { addDefaultValue(envVarMap, oneagentReadOnlyMode, "true") } } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go b/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go index fe6580d8d9..10d43fb9c6 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" logmonitoringds "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/daemonset" @@ -38,8 +39,8 @@ func TestEnvironmentVariables(t *testing.T) { Proxy: &value.Source{ Value: "test", }, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, LogMonitoring: &logmonitoring.Spec{}, }, @@ -70,7 +71,7 @@ func TestEnvironmentVariables(t *testing.T) { } builder := builder{ dk: &dynakube.DynaKube{}, - hostInjectSpec: &dynakube.HostInjectSpec{Env: potentiallyOverriddenEnvVars}, + hostInjectSpec: &oneagent.HostInjectSpec{Env: potentiallyOverriddenEnvVars}, } envVars, _ := builder.environmentVariables() @@ -176,7 +177,7 @@ func assertConnectionInfoEnv(t *testing.T, envs []corev1.EnvVar, dk *dynakube.Dy env := k8senv.FindEnvVar(envs, connectioninfo.EnvDtTenant) assert.Equal(t, connectioninfo.EnvDtTenant, env.Name) assert.Equal(t, - dk.OneAgentConnectionInfoConfigMapName(), + dk.OneAgent().GetConnectionInfoConfigMapName(), env.ValueFrom.ConfigMapKeyRef.Name, ) assert.Equal(t, @@ -187,7 +188,7 @@ func assertConnectionInfoEnv(t *testing.T, envs []corev1.EnvVar, dk *dynakube.Dy env = k8senv.FindEnvVar(envs, connectioninfo.EnvDtServer) assert.Equal(t, connectioninfo.EnvDtServer, env.Name) assert.Equal(t, - dk.OneAgentConnectionInfoConfigMapName(), + dk.OneAgent().GetConnectionInfoConfigMapName(), env.ValueFrom.ConfigMapKeyRef.Name, ) assert.Equal(t, @@ -258,8 +259,8 @@ func TestAddReadOnlyEnv(t *testing.T) { Name: "test", }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go index 029a292fc1..e94697e308 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go @@ -15,7 +15,7 @@ func prepareVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { volumeMounts = append(volumeMounts, getOneAgentSecretVolumeMount()) - if dk != nil && dk.UseReadOnlyOneAgents() { + if dk != nil && dk.OneAgent().IsReadOnlyOneAgentsMode() { volumeMounts = append(volumeMounts, getReadOnlyRootMount()) volumeMounts = append(volumeMounts, getCSIStorageMount()) } else { @@ -94,7 +94,7 @@ func prepareVolumes(dk *dynakube.DynaKube) []corev1.Volume { volumes = append(volumes, getOneAgentSecretVolume(dk)) - if dk.UseReadOnlyOneAgents() { + if dk.OneAgent().IsReadOnlyOneAgentsMode() { volumes = append(volumes, getCSIStorageVolume(dk)) } @@ -181,7 +181,7 @@ func getOneAgentSecretVolume(dk *dynakube.DynaKube) corev1.Volume { Name: connectioninfo.TenantSecretVolumeName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: dk.OneagentTenantSecret(), + SecretName: dk.OneAgent().GetTenantSecret(), }, }, } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go index 9204bf86ec..853c60c337 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go @@ -6,6 +6,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -21,8 +22,8 @@ func TestPrepareVolumes(t *testing.T) { t.Run(`has root volume`, func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -45,8 +46,8 @@ func TestPrepareVolumes(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ TrustedCAs: testName, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -77,8 +78,8 @@ func TestPrepareVolumes(t *testing.T) { }, TlsSecretName: "testing", }, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -88,8 +89,8 @@ func TestPrepareVolumes(t *testing.T) { t.Run(`csi volume not supported on classicFullStack`, func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } @@ -100,8 +101,8 @@ func TestPrepareVolumes(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ TrustedCAs: testName, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, ActiveGate: activegate.Spec{ Capabilities: []activegate.CapabilityDisplayName{ @@ -139,8 +140,8 @@ func TestPrepareVolumeMounts(t *testing.T) { t.Run(`has root volume mount`, func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -152,8 +153,8 @@ func TestPrepareVolumeMounts(t *testing.T) { t.Run(`has cluster certificate volume mount`, func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, TrustedCAs: testName, }, @@ -167,8 +168,8 @@ func TestPrepareVolumeMounts(t *testing.T) { t.Run(`has ActiveGate CA volume mount`, func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, TrustedCAs: testName, ActiveGate: activegate.Spec{ @@ -188,8 +189,8 @@ func TestPrepareVolumeMounts(t *testing.T) { t.Run(`readonly volume not supported on classicFullStack`, func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } @@ -202,8 +203,8 @@ func TestPrepareVolumeMounts(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ TrustedCAs: testName, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, ActiveGate: activegate.Spec{ Capabilities: []activegate.CapabilityDisplayName{ @@ -240,8 +241,8 @@ func TestPrepareVolumeMounts(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ Proxy: &value.Source{ValueFrom: proxy.BuildSecretName("Dynakube")}, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } diff --git a/pkg/controllers/dynakube/oneagent/oneagent_reconciler.go b/pkg/controllers/dynakube/oneagent/oneagent_reconciler.go index 45a5665849..e5ff5a511d 100644 --- a/pkg/controllers/dynakube/oneagent/oneagent_reconciler.go +++ b/pkg/controllers/dynakube/oneagent/oneagent_reconciler.go @@ -10,6 +10,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" @@ -110,7 +111,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { return err } - if !r.dk.NeedsOneAgent() { + if !r.dk.OneAgent().IsDaemonsetRequired() { return r.cleanUp(ctx) } @@ -194,7 +195,7 @@ func (r *Reconciler) createOneAgentTenantConnectionInfoConfigMap(ctx context.Con configMapData := extractPublicData(r.dk) configMap, err := configmap.Build(r.dk, - r.dk.OneAgentConnectionInfoConfigMapName(), + r.dk.OneAgent().GetConnectionInfoConfigMapName(), configMapData, ) if err != nil { @@ -216,7 +217,7 @@ func (r *Reconciler) createOneAgentTenantConnectionInfoConfigMap(ctx context.Con func (r *Reconciler) deleteOneAgentTenantConnectionInfoConfigMap(ctx context.Context) error { cm, _ := configmap.Build(r.dk, - r.dk.OneAgentConnectionInfoConfigMapName(), + r.dk.OneAgent().GetConnectionInfoConfigMapName(), nil, ) query := configmap.Query(r.client, r.apiReader, log) @@ -288,7 +289,7 @@ func (r *Reconciler) reconcileRollout(ctx context.Context) error { } func (r *Reconciler) getOneagentPods(ctx context.Context, dk *dynakube.DynaKube, feature string) ([]corev1.Pod, []client.ListOption, error) { - agentVersion := dk.OneAgentVersion() + agentVersion := dk.OneAgent().GetVersion() appLabels := labels.NewAppLabels(labels.OneAgentComponentLabel, dk.Name, feature, agentVersion) podList := &corev1.PodList{} @@ -307,11 +308,11 @@ func (r *Reconciler) buildDesiredDaemonSet(dk *dynakube.DynaKube) (*appsv1.Daemo var err error switch { - case dk.ClassicFullStackMode(): + case dk.OneAgent().IsClassicFullStackMode(): ds, err = daemonset.NewClassicFullStack(dk, r.clusterID).BuildDaemonSet() - case dk.HostMonitoringMode(): + case dk.OneAgent().IsHostMonitoringMode(): ds, err = daemonset.NewHostMonitoring(dk, r.clusterID).BuildDaemonSet() - case dk.CloudNativeFullstackMode(): + case dk.OneAgent().IsCloudNativeFullstackMode(): ds, err = daemonset.NewCloudNativeFullStack(dk, r.clusterID).BuildDaemonSet() } @@ -352,16 +353,16 @@ func (r *Reconciler) reconcileInstanceStatuses(ctx context.Context, dk *dynakube } func (r *Reconciler) removeOneAgentDaemonSet(ctx context.Context, dk *dynakube.DynaKube) error { - oneAgentDaemonSet := appsv1.DaemonSet{ObjectMeta: metav1.ObjectMeta{Name: dk.OneAgentDaemonsetName(), Namespace: dk.Namespace}} + oneAgentDaemonSet := appsv1.DaemonSet{ObjectMeta: metav1.ObjectMeta{Name: dk.OneAgent().GetDaemonsetName(), Namespace: dk.Namespace}} return client.IgnoreNotFound(r.client.Delete(ctx, &oneAgentDaemonSet)) } -func getInstanceStatuses(pods []corev1.Pod) map[string]dynakube.OneAgentInstance { - instanceStatuses := make(map[string]dynakube.OneAgentInstance) +func getInstanceStatuses(pods []corev1.Pod) map[string]oneagent.Instance { + instanceStatuses := make(map[string]oneagent.Instance) for _, pod := range pods { - instanceStatuses[pod.Spec.NodeName] = dynakube.OneAgentInstance{ + instanceStatuses[pod.Spec.NodeName] = oneagent.Instance{ PodName: pod.Name, IPAddress: pod.Status.HostIP, } diff --git a/pkg/controllers/dynakube/oneagent/oneagent_reconciler_test.go b/pkg/controllers/dynakube/oneagent/oneagent_reconciler_test.go index f388a77dea..32ce05f6fb 100644 --- a/pkg/controllers/dynakube/oneagent/oneagent_reconciler_test.go +++ b/pkg/controllers/dynakube/oneagent/oneagent_reconciler_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" @@ -48,8 +49,8 @@ func TestReconcile(t *testing.T) { dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{Name: dkName, Namespace: namespace}, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, } @@ -69,10 +70,10 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) dsActual := &appsv1.DaemonSet{} - err = fakeClient.Get(ctx, types.NamespacedName{Name: dk.OneAgentDaemonsetName(), Namespace: namespace}, dsActual) + err = fakeClient.Get(ctx, types.NamespacedName{Name: dk.OneAgent().GetDaemonsetName(), Namespace: namespace}, dsActual) require.NoError(t, err, "failed to get DaemonSet") assert.Equal(t, namespace, dsActual.Namespace, "wrong namespace") - assert.Equal(t, dk.OneAgentDaemonsetName(), dsActual.GetObjectMeta().GetName(), "wrong name") + assert.Equal(t, dk.OneAgent().GetDaemonsetName(), dsActual.GetObjectMeta().GetName(), "wrong name") assert.NotNil(t, dsActual.Spec.Template.Spec.Affinity) }) @@ -80,7 +81,7 @@ func TestReconcile(t *testing.T) { t.Run("remove DaemonSet in case OneAgent is not needed + remove condition", func(t *testing.T) { dk := &dynakube.DynaKube{ObjectMeta: metav1.ObjectMeta{Name: dkName, Namespace: namespace}} setDaemonSetCreatedCondition(dk.Conditions()) - fakeClient := fake.NewClient(dk, &appsv1.DaemonSet{ObjectMeta: metav1.ObjectMeta{Name: dk.OneAgentDaemonsetName(), Namespace: dk.Namespace}}) + fakeClient := fake.NewClient(dk, &appsv1.DaemonSet{ObjectMeta: metav1.ObjectMeta{Name: dk.OneAgent().GetDaemonsetName(), Namespace: dk.Namespace}}) reconciler := &Reconciler{ client: fakeClient, @@ -94,7 +95,7 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) dsActual := &appsv1.DaemonSet{} - err = fakeClient.Get(ctx, types.NamespacedName{Name: dk.OneAgentDaemonsetName(), Namespace: namespace}, dsActual) + err = fakeClient.Get(ctx, types.NamespacedName{Name: dk.OneAgent().GetDaemonsetName(), Namespace: namespace}, dsActual) require.Error(t, err) assert.True(t, k8serrors.IsNotFound(err)) @@ -123,8 +124,8 @@ func TestReconcile(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: "https://ENVIRONMENTID.live.dynatrace.com/api", NetworkZone: "test", - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, } @@ -151,8 +152,8 @@ func TestReconcile(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: dkName, Namespace: namespace}, Spec: dynakube.DynaKubeSpec{ APIURL: "https://ENVIRONMENTID.live.dynatrace.com/api", - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, } @@ -184,8 +185,8 @@ func TestReconcileOneAgent_ReconcileOnEmptyEnvironmentAndDNSPolicy(t *testing.T) dkSpec := dynakube.DynaKubeSpec{ APIURL: "https://ENVIRONMENTID.live.dynatrace.com/api", Tokens: dkName, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ DNSPolicy: corev1.DNSClusterFirstWithHostNet, Labels: map[string]string{ "label_key": "label_value", @@ -201,7 +202,7 @@ func TestReconcileOneAgent_ReconcileOnEmptyEnvironmentAndDNSPolicy(t *testing.T) } dk.Status.OneAgent.ConnectionInfoStatus.ConnectionInfo.TenantUUID = "test-tenant" - dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []dynakube.CommunicationHostStatus{ + dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{ { Protocol: "http", Host: "dummyhost", @@ -225,10 +226,10 @@ func TestReconcileOneAgent_ReconcileOnEmptyEnvironmentAndDNSPolicy(t *testing.T) require.NoError(t, err) dsActual := &appsv1.DaemonSet{} - err = fakeClient.Get(ctx, types.NamespacedName{Name: dk.OneAgentDaemonsetName(), Namespace: namespace}, dsActual) + err = fakeClient.Get(ctx, types.NamespacedName{Name: dk.OneAgent().GetDaemonsetName(), Namespace: namespace}, dsActual) require.NoError(t, err, "failed to get DaemonSet") assert.Equal(t, namespace, dsActual.Namespace, "wrong namespace") - assert.Equal(t, dk.OneAgentDaemonsetName(), dsActual.GetObjectMeta().GetName(), "wrong name") + assert.Equal(t, dk.OneAgent().GetDaemonsetName(), dsActual.GetObjectMeta().GetName(), "wrong name") assert.Equal(t, corev1.DNSClusterFirstWithHostNet, dsActual.Spec.Template.Spec.DNSPolicy, "wrong policy") mock.AssertExpectationsForObjects(t, dtClient) @@ -251,13 +252,13 @@ func TestReconcile_InstancesSet(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: "https://ENVIRONMENTID.live.dynatrace.com/api", Tokens: name, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } base.Status.OneAgent.ConnectionInfoStatus.TenantUUID = "test-tenant" - base.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []dynakube.CommunicationHostStatus{ + base.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{ { Protocol: "http", Host: "dummyhost", @@ -357,8 +358,8 @@ func TestMigrationForDaemonSetWithoutAnnotation(t *testing.T) { dk := &dynakube.DynaKube{ ObjectMeta: dkKey, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -507,16 +508,16 @@ func TestHasSpecChanged(t *testing.T) { oldInstance := dynakube.DynaKube{ ObjectMeta: key, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } newInstance := dynakube.DynaKube{ ObjectMeta: key, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -608,8 +609,8 @@ func newDynaKube() *dynakube.DynaKube { UID: "69e98f18-805a-42de-84b5-3eae66534f75", }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -624,8 +625,8 @@ func TestInstanceStatus(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: "https://ENVIRONMENTID.live.dynatrace.com/api", Tokens: dkName, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -678,8 +679,8 @@ func TestEmptyInstancesWithWrongLabels(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: "https://ENVIRONMENTID.live.dynatrace.com/api", Tokens: dkName, - OneAgent: dynakube.OneAgentSpec{ - HostMonitoring: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, }, }, } @@ -723,13 +724,13 @@ func TestReconcile_OneAgentConfigMap(t *testing.T) { ctx := context.Background() dk := newDynaKube() dk.Status = dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: testTenantUUID, Endpoints: testTenantEndpoints, }, - CommunicationHosts: []dynakube.CommunicationHostStatus{ + CommunicationHosts: []oneagent.CommunicationHostStatus{ { Protocol: "http", Host: "dummyhost", @@ -757,7 +758,7 @@ func TestReconcile_OneAgentConfigMap(t *testing.T) { require.NoError(t, err) var actual corev1.ConfigMap - err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneAgentConnectionInfoConfigMapName(), Namespace: dk.Namespace}, &actual) + err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneAgent().GetConnectionInfoConfigMapName(), Namespace: dk.Namespace}, &actual) require.NoError(t, err) assert.Equal(t, testTenantUUID, actual.Data[connectioninfo.TenantUUIDKey]) assert.Equal(t, testTenantEndpoints, actual.Data[connectioninfo.CommunicationEndpointsKey]) diff --git a/pkg/controllers/dynakube/phase.go b/pkg/controllers/dynakube/phase.go index 67409f43ab..4c97ed2e41 100644 --- a/pkg/controllers/dynakube/phase.go +++ b/pkg/controllers/dynakube/phase.go @@ -93,7 +93,7 @@ func (controller *Controller) determinePrometheusStatefulsetPhase(dk *dynakube.D } func (controller *Controller) determineOneAgentPhase(dk *dynakube.DynaKube) status.DeploymentPhase { - if dk.CloudNativeFullstackMode() || dk.ClassicFullStackMode() || dk.HostMonitoringMode() { + if dk.OneAgent().IsCloudNativeFullstackMode() || dk.OneAgent().IsClassicFullStackMode() || dk.OneAgent().IsHostMonitoringMode() { oneAgentPods, err := controller.numberOfMissingOneagentPods(dk) if k8serrors.IsNotFound(err) { log.Info("oneagent daemonset not yet available", "dynakube", dk.Name) @@ -119,7 +119,7 @@ func (controller *Controller) determineOneAgentPhase(dk *dynakube.DynaKube) stat func (controller *Controller) numberOfMissingOneagentPods(dk *dynakube.DynaKube) (int32, error) { oneAgentDaemonSet := &appsv1.DaemonSet{} - instanceName := dk.OneAgentDaemonsetName() + instanceName := dk.OneAgent().GetDaemonsetName() err := controller.client.Get(context.Background(), types.NamespacedName{Name: instanceName, Namespace: dk.Namespace}, oneAgentDaemonSet) if err != nil { diff --git a/pkg/controllers/dynakube/phase_test.go b/pkg/controllers/dynakube/phase_test.go index 46d60d1996..abc07fc48e 100644 --- a/pkg/controllers/dynakube/phase_test.go +++ b/pkg/controllers/dynakube/phase_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -99,8 +100,8 @@ func TestOneAgentPhaseChanges(t *testing.T) { Namespace: testNamespace, }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } @@ -265,8 +266,8 @@ func TestDynakubePhaseChanges(t *testing.T) { Namespace: testNamespace, }, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, Extensions: &dynakube.ExtensionsSpec{}, diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go index 859c2e7ef4..9f303ec32a 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go @@ -49,7 +49,7 @@ func NewReconciler(clt client.Client, } func (r *Reconciler) Reconcile(ctx context.Context) error { - if !(r.dk.CloudNativeFullstackMode() || r.dk.ApplicationMonitoringMode()) { + if !(r.dk.OneAgent().IsCloudNativeFullstackMode() || r.dk.OneAgent().IsApplicationMonitoringMode()) { if meta.FindStatusCondition(*r.dk.Conditions(), pmcConditionType) == nil { return nil } @@ -126,7 +126,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) } tenantToken, err := k8ssecret.GetDataFromSecretName(ctx, r.apiReader, types.NamespacedName{ - Name: r.dk.OneagentTenantSecret(), + Name: r.dk.OneAgent().GetTenantSecret(), Namespace: r.dk.Namespace, }, connectioninfo.TenantTokenKey, log) if err != nil { @@ -136,7 +136,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) } pmc = pmc. - AddHostGroup(r.dk.HostGroup()). + AddHostGroup(r.dk.OneAgent().GetHostGroup()). AddConnectionInfo(r.dk.Status.OneAgent.ConnectionInfoStatus, tenantToken). // set proxy explicitly empty, so old proxy settings get deleted where necessary AddProxy("") diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go index 7a2f0d7b76..06c07a739b 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go @@ -9,6 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" @@ -34,8 +35,8 @@ const ( func TestReconcile(t *testing.T) { t.Run("Create and update works with minimal setup", func(t *testing.T) { - dk := createDynakube(dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}) + dk := createDynakube(oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}) mockK8sClient := createK8sClientWithOneAgentTenantSecret(testTokenValue) @@ -80,8 +81,8 @@ func TestReconcile(t *testing.T) { assert.Equal(t, metav1.ConditionTrue, condition.Status) }) t.Run("Only runs when required, and cleans up condition and pmc secret", func(t *testing.T) { - dk := createDynakube(dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}}) + dk := createDynakube(oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}}) conditions.SetSecretCreated(dk.Conditions(), pmcConditionType, "this is a test") secret := &corev1.Secret{ @@ -101,8 +102,8 @@ func TestReconcile(t *testing.T) { assert.Error(t, mockK8sClient.Get(context.Background(), client.ObjectKey{Name: extendWithSuffix(testName), Namespace: testNamespace}, &corev1.Secret{})) }) t.Run("No proxy is set when proxy enabled and custom no proxy set", func(t *testing.T) { - dk := createDynakube(dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}) + dk := createDynakube(oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}) dk.Spec.Proxy = &value.Source{ Value: "myproxy.at", } @@ -119,8 +120,8 @@ func TestReconcile(t *testing.T) { }) t.Run("problem with k8s request => visible in conditions", func(t *testing.T) { - dk := createDynakube(dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}) + dk := createDynakube(oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}) boomClient := createBOOMK8sClient() @@ -139,8 +140,8 @@ func TestReconcile(t *testing.T) { }) t.Run("problem with dynatrace request => visible in conditions", func(t *testing.T) { - dk := createDynakube(dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}) + dk := createDynakube(oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}) mockK8sClient := fake.NewClient(dk) _ = createK8sClientWithOneAgentTenantSecret(testTokenValue) @@ -170,7 +171,7 @@ func checkSecretForValue(t *testing.T, k8sClient client.Client, shouldContain st require.Contains(t, string(processModuleConfig), shouldContain) } -func createDynakube(oneAgentSpec dynakube.OneAgentSpec) *dynakube.DynaKube { +func createDynakube(oneAgentSpec oneagent.Spec) *dynakube.DynaKube { return &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Namespace: testNamespace, @@ -235,8 +236,8 @@ func createK8sClientWithOneAgentTenantSecret(token string) client.Client { func TestGetSecretData(t *testing.T) { t.Run("unmarshal secret data into struct", func(t *testing.T) { // use Reconcile to automatically create the secret to test - dk := createDynakube(dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}}) + dk := createDynakube(oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}) mockK8sClient := createK8sClientWithOneAgentTenantSecret(testTokenValue) mockTime := timeprovider.New().Freeze() diff --git a/pkg/controllers/dynakube/version/activegate.go b/pkg/controllers/dynakube/version/activegate.go index 808a0b447c..4e9181285f 100644 --- a/pkg/controllers/dynakube/version/activegate.go +++ b/pkg/controllers/dynakube/version/activegate.go @@ -71,7 +71,7 @@ func (updater activeGateUpdater) IsAutoUpdateEnabled() bool { } func (updater activeGateUpdater) IsPublicRegistryEnabled() bool { - isPublicRegistry := updater.dk.FeaturePublicRegistry() && !updater.dk.ClassicFullStackMode() + isPublicRegistry := updater.dk.FeaturePublicRegistry() && !updater.dk.OneAgent().IsClassicFullStackMode() if isPublicRegistry { setVerifiedCondition(updater.dk.Conditions(), activeGateVersionConditionType) // Bit hacky, as things can still go wrong, but if so we will just overwrite this is LatestImageInfo. } diff --git a/pkg/controllers/dynakube/version/codemodules.go b/pkg/controllers/dynakube/version/codemodules.go index a12c8a02f1..b03178fc25 100644 --- a/pkg/controllers/dynakube/version/codemodules.go +++ b/pkg/controllers/dynakube/version/codemodules.go @@ -5,6 +5,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "k8s.io/apimachinery/pkg/api/meta" @@ -31,7 +32,7 @@ func (updater codeModulesUpdater) Name() string { } func (updater codeModulesUpdater) IsEnabled() bool { - if updater.dk.NeedAppInjection() { + if updater.dk.OneAgent().IsAppInjectionNeeded() { return true } @@ -46,7 +47,7 @@ func (updater *codeModulesUpdater) Target() *status.VersionStatus { } func (updater codeModulesUpdater) CustomImage() string { - customImage := updater.dk.CustomCodeModulesImage() + customImage := updater.dk.OneAgent().GetCustomCodeModulesImage() if customImage != "" { setVerificationSkippedReasonCondition(updater.dk.Conditions(), cmConditionType) } @@ -55,7 +56,7 @@ func (updater codeModulesUpdater) CustomImage() string { } func (updater codeModulesUpdater) CustomVersion() string { - return updater.dk.CustomCodeModulesVersion() + return updater.dk.OneAgent().GetCustomCodeModulesVersion() } func (updater codeModulesUpdater) IsAutoUpdateEnabled() bool { @@ -87,7 +88,7 @@ func (updater *codeModulesUpdater) CheckForDowngrade(_ string) (bool, error) { func (updater *codeModulesUpdater) UseTenantRegistry(ctx context.Context) error { customVersion := updater.CustomVersion() if customVersion != "" { - updater.dk.Status.CodeModules = dynakube.CodeModulesStatus{ + updater.dk.Status.CodeModules = oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ Version: customVersion, }, @@ -106,7 +107,7 @@ func (updater *codeModulesUpdater) UseTenantRegistry(ctx context.Context) error return err } - updater.dk.Status.CodeModules = dynakube.CodeModulesStatus{ + updater.dk.Status.CodeModules = oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ Version: latestAgentVersionUnixPaas, }, diff --git a/pkg/controllers/dynakube/version/codemodules_test.go b/pkg/controllers/dynakube/version/codemodules_test.go index 26990d47b7..daf524a522 100644 --- a/pkg/controllers/dynakube/version/codemodules_test.go +++ b/pkg/controllers/dynakube/version/codemodules_test.go @@ -6,6 +6,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" @@ -25,10 +26,10 @@ func TestCodeModulesUpdater(t *testing.T) { t.Run("Getters work as expected", func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ Version: testImage.Tag, - AppInjectionSpec: dynakube.AppInjectionSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ CodeModulesImage: testImage.String(), }, }, @@ -57,8 +58,8 @@ func TestCodeModulesUseDefault(t *testing.T) { t.Run("Set according to version field, unset previous status", func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ Version: testVersion, }, }, @@ -80,8 +81,8 @@ func TestCodeModulesUseDefault(t *testing.T) { t.Run("Set according to default, unset previous status", func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, }, Status: dynakube.DynaKubeStatus{ @@ -102,8 +103,8 @@ func TestCodeModulesUseDefault(t *testing.T) { t.Run("problem with Dynatrace request => visible in conditions", func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, }, Status: dynakube.DynaKubeStatus{ @@ -125,7 +126,7 @@ func TestCodeModulesIsEnabled(t *testing.T) { t.Run("cleans up condition if not enabled", func(t *testing.T) { dk := &dynakube.DynaKube{ Status: dynakube.DynaKubeStatus{ - CodeModules: dynakube.CodeModulesStatus{ + CodeModules: oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ Version: "prev", }, @@ -201,15 +202,15 @@ func TestCodeModulesLatestImageInfo(t *testing.T) { }) } -func oldCodeModulesStatus() dynakube.CodeModulesStatus { - return dynakube.CodeModulesStatus{ +func oldCodeModulesStatus() oneagent.CodeModulesStatus { + return oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ ImageID: "prev", }, } } -func assertDefaultCodeModulesStatus(t *testing.T, expectedVersion string, codeModulesStatus dynakube.CodeModulesStatus) { +func assertDefaultCodeModulesStatus(t *testing.T, expectedVersion string, codeModulesStatus oneagent.CodeModulesStatus) { assert.Equal(t, expectedVersion, codeModulesStatus.Version) assert.Empty(t, codeModulesStatus.ImageID) } diff --git a/pkg/controllers/dynakube/version/oneagent.go b/pkg/controllers/dynakube/version/oneagent.go index c4d5500f61..17419b83ca 100644 --- a/pkg/controllers/dynakube/version/oneagent.go +++ b/pkg/controllers/dynakube/version/oneagent.go @@ -39,7 +39,7 @@ func (updater oneAgentUpdater) Name() string { } func (updater oneAgentUpdater) IsEnabled() bool { - if updater.dk.NeedsOneAgent() { + if updater.dk.OneAgent().IsDaemonsetRequired() { return true } @@ -47,7 +47,7 @@ func (updater oneAgentUpdater) IsEnabled() bool { updater.dk.Status.OneAgent.Healthcheck = nil _ = meta.RemoveStatusCondition(updater.dk.Conditions(), oaConditionType) - return updater.dk.NeedsOneAgent() + return updater.dk.OneAgent().IsDaemonsetRequired() } func (updater *oneAgentUpdater) Target() *status.VersionStatus { @@ -55,7 +55,7 @@ func (updater *oneAgentUpdater) Target() *status.VersionStatus { } func (updater oneAgentUpdater) CustomImage() string { - customImage := updater.dk.CustomOneAgentImage() + customImage := updater.dk.OneAgent().GetCustomImage() if customImage != "" { setVerificationSkippedReasonCondition(updater.dk.Conditions(), oaConditionType) } @@ -64,15 +64,15 @@ func (updater oneAgentUpdater) CustomImage() string { } func (updater oneAgentUpdater) CustomVersion() string { - return updater.dk.CustomOneAgentVersion() + return updater.dk.OneAgent().GetCustomVersion() } func (updater oneAgentUpdater) IsAutoUpdateEnabled() bool { - return updater.dk.ShouldAutoUpdateOneAgent() + return updater.dk.OneAgent().IsAutoUpdateEnabled() } func (updater oneAgentUpdater) IsPublicRegistryEnabled() bool { - isPublicRegistry := updater.dk.FeaturePublicRegistry() && !updater.dk.ClassicFullStackMode() + isPublicRegistry := updater.dk.FeaturePublicRegistry() && !updater.dk.OneAgent().IsClassicFullStackMode() if isPublicRegistry { setVerifiedCondition(updater.dk.Conditions(), oaConditionType) // Bit hacky, as things can still go wrong, but if so we will just overwrite this is LatestImageInfo. } @@ -110,7 +110,7 @@ func (updater oneAgentUpdater) UseTenantRegistry(ctx context.Context) error { return err } - defaultImage := updater.dk.DefaultOneAgentImage(latestVersion) + defaultImage := updater.dk.OneAgent().GetDefaultImage(latestVersion) err = updateVersionStatusForTenantRegistry(updater.Target(), defaultImage, latestVersion) if err != nil { @@ -165,7 +165,7 @@ func (updater oneAgentUpdater) ValidateStatus() error { } if imageType == status.ImmutableImageType { - if updater.dk.ClassicFullStackMode() { + if updater.dk.OneAgent().IsClassicFullStackMode() { return errors.New("immutable OneAgent image in combination with classicFullStack mode is not possible") } } diff --git a/pkg/controllers/dynakube/version/oneagent_test.go b/pkg/controllers/dynakube/version/oneagent_test.go index 3544068c34..86dca3d3ba 100644 --- a/pkg/controllers/dynakube/version/oneagent_test.go +++ b/pkg/controllers/dynakube/version/oneagent_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" @@ -27,8 +28,8 @@ func TestOneAgentUpdater(t *testing.T) { t.Run("Getters work as expected", func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ AutoUpdate: ptr.To(false), Image: testImage.String(), Version: testImage.Tag, @@ -56,7 +57,7 @@ func TestOneAgentIsEnabled(t *testing.T) { t.Run("cleans up condition if not enabled", func(t *testing.T) { dk := &dynakube.DynaKube{ Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ Version: "prev", }, @@ -141,14 +142,14 @@ func TestOneAgentUseDefault(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ Version: testVersion, }, }, }, } - expectedImage := dk.DefaultOneAgentImage(testVersion) + expectedImage := dk.OneAgent().GetDefaultImage(testVersion) mockClient := dtclientmock.NewClient(t) @@ -166,12 +167,12 @@ func TestOneAgentUseDefault(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } - expectedImage := dk.DefaultOneAgentImage(testVersion) + expectedImage := dk.OneAgent().GetDefaultImage(testVersion) mockClient := dtclientmock.NewClient(t) mockLatestAgentVersion(mockClient, testVersion) @@ -191,12 +192,12 @@ func TestOneAgentUseDefault(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ ImageID: "some.registry.com:" + previousVersion, Version: previousVersion, @@ -225,12 +226,12 @@ func TestOneAgentUseDefault(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ ImageID: "some.registry.com:" + previousVersion, Version: previousVersion, @@ -257,12 +258,12 @@ func TestOneAgentUseDefault(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ ImageID: "BOOM", Source: status.PublicRegistryVersionSource, @@ -295,7 +296,7 @@ type CheckForDowngradeTestCase struct { func newDynakubeWithOneAgentStatus(status status.VersionStatus) *dynakube.DynaKube { return &dynakube.DynaKube{ Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status, }, }, @@ -378,10 +379,10 @@ func TestCheckForDowngrade(t *testing.T) { func newDynakubeForCheckLabelTest(versionStatus status.VersionStatus) *dynakube.DynaKube { return &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{}, + OneAgent: oneagent.Spec{}, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: versionStatus, }, }, @@ -400,26 +401,26 @@ func TestCheckLabels(t *testing.T) { t.Run("Validate immutable oneAgent image with default cloudNative", func(t *testing.T) { dk := newDynakubeForCheckLabelTest(versionStatus) - dk.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} + dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} updater := newOneAgentUpdater(dk, fake.NewClient(), nil) require.NoError(t, updater.ValidateStatus()) }) t.Run("Validate immutable oneAgent image with classicFullStack", func(t *testing.T) { dk := newDynakubeForCheckLabelTest(versionStatus) - dk.Spec.OneAgent.ClassicFullStack = &dynakube.HostInjectSpec{} + dk.Spec.OneAgent.ClassicFullStack = &oneagent.HostInjectSpec{} updater := newOneAgentUpdater(dk, fake.NewClient(), nil) require.Error(t, updater.ValidateStatus()) }) t.Run("Validate immutable oneAgent image when image version is not set", func(t *testing.T) { dk := newDynakubeForCheckLabelTest(versionStatus) - dk.Spec.OneAgent.CloudNativeFullStack = &dynakube.CloudNativeFullStackSpec{} + dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} dk.Status.OneAgent.VersionStatus.Version = "" updater := newOneAgentUpdater(dk, fake.NewClient(), nil) require.Error(t, updater.ValidateStatus()) }) t.Run("Validate mutable oneAgent image with classicFullStack", func(t *testing.T) { dk := newDynakubeForCheckLabelTest(versionStatus) - dk.Spec.OneAgent.ClassicFullStack = &dynakube.HostInjectSpec{} + dk.Spec.OneAgent.ClassicFullStack = &oneagent.HostInjectSpec{} dk.Status.OneAgent.VersionStatus.Type = "mutable" updater := newOneAgentUpdater(dk, fake.NewClient(), nil) require.NoError(t, updater.ValidateStatus()) diff --git a/pkg/controllers/dynakube/version/reconciler.go b/pkg/controllers/dynakube/version/reconciler.go index a479f984d8..7d1187430a 100644 --- a/pkg/controllers/dynakube/version/reconciler.go +++ b/pkg/controllers/dynakube/version/reconciler.go @@ -79,7 +79,7 @@ func (r *reconciler) updateVersionStatuses(ctx context.Context, updater StatusUp _, ok := updater.(*oneAgentUpdater) if ok { - healthConfig, err := getOneAgentHealthConfig(dk.OneAgentVersion()) + healthConfig, err := getOneAgentHealthConfig(dk.OneAgent().GetVersion()) if err != nil { log.Error(err, "could not set OneAgent healthcheck") } else { diff --git a/pkg/controllers/dynakube/version/reconciler_test.go b/pkg/controllers/dynakube/version/reconciler_test.go index a72b0ad625..a91441e854 100644 --- a/pkg/controllers/dynakube/version/reconciler_test.go +++ b/pkg/controllers/dynakube/version/reconciler_test.go @@ -10,6 +10,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dtpullsecret" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" @@ -39,8 +40,8 @@ func TestReconcile(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace}, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, ActiveGate: activegate.Spec{ Capabilities: []activegate.CapabilityDisplayName{ @@ -100,7 +101,7 @@ func TestReconcile(t *testing.T) { assert.Equal(t, "Version verified for component.", condition.Message) assertStatusBasedOnTenantRegistry(t, dk.ActiveGate().GetDefaultImage(testActiveGateImage.Tag), testActiveGateImage.Tag, dkStatus.ActiveGate.VersionStatus) - assertStatusBasedOnTenantRegistry(t, dk.DefaultOneAgentImage(testOneAgentImage.Tag), testOneAgentImage.Tag, dkStatus.OneAgent.VersionStatus) + assertStatusBasedOnTenantRegistry(t, dk.OneAgent().GetDefaultImage(testOneAgentImage.Tag), testOneAgentImage.Tag, dkStatus.OneAgent.VersionStatus) assert.Equal(t, latestAgentVersion, dkStatus.CodeModules.VersionStatus.Version) // no change if probe not old enough @@ -203,12 +204,12 @@ func TestNeedsUpdate(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ + OneAgent: oneagent.Status{ VersionStatus: status.VersionStatus{ Source: status.TenantRegistryVersionSource, }, @@ -282,8 +283,8 @@ func TestNeedsUpdate(t *testing.T) { func TestHasCustomFieldChanged(t *testing.T) { dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ClassicFullStack: &dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, }, }, } diff --git a/pkg/controllers/nodes/nodes_controller_test.go b/pkg/controllers/nodes/nodes_controller_test.go index a3edbd3643..1bae2e478e 100644 --- a/pkg/controllers/nodes/nodes_controller_test.go +++ b/pkg/controllers/nodes/nodes_controller_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dynatraceclient" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" @@ -40,8 +41,8 @@ func TestReconcile(t *testing.T) { &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{Name: "oneagent1", Namespace: testNamespace}, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - Instances: map[string]dynakube.OneAgentInstance{node.Name: {IPAddress: "1.2.3.4"}}, + OneAgent: oneagent.Status{ + Instances: map[string]oneagent.Instance{node.Name: {IPAddress: "1.2.3.4"}}, }, }, }, @@ -289,16 +290,16 @@ func createDefaultFakeClient() client.Client { &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{Name: "oneagent1", Namespace: testNamespace}, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - Instances: map[string]dynakube.OneAgentInstance{"node1": {IPAddress: "1.2.3.4"}}, + OneAgent: oneagent.Status{ + Instances: map[string]oneagent.Instance{"node1": {IPAddress: "1.2.3.4"}}, }, }, }, &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{Name: "oneagent2", Namespace: testNamespace}, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - Instances: map[string]dynakube.OneAgentInstance{"node2": {IPAddress: "5.6.7.8"}}, + OneAgent: oneagent.Status{ + Instances: map[string]oneagent.Instance{"node2": {IPAddress: "5.6.7.8"}}, }, }, }, diff --git a/pkg/injection/namespace/initgeneration/initgeneration.go b/pkg/injection/namespace/initgeneration/initgeneration.go index fd97f6d630..1364a9855f 100644 --- a/pkg/injection/namespace/initgeneration/initgeneration.go +++ b/pkg/injection/namespace/initgeneration/initgeneration.go @@ -175,13 +175,13 @@ func (g *InitGenerator) createSecretConfigForDynaKube(ctx context.Context, dk *d OneAgentNoProxy: strings.Join(oneAgentNoProxyValues, ","), NetworkZone: dk.Spec.NetworkZone, SkipCertCheck: dk.Spec.SkipCertCheck, - HasHost: dk.CloudNativeFullstackMode(), + HasHost: dk.OneAgent().IsCloudNativeFullstackMode(), MonitoringNodes: hostMonitoringNodes, - HostGroup: dk.HostGroup(), + HostGroup: dk.OneAgent().GetHostGroup(), InitialConnectRetry: dk.FeatureAgentInitialConnectRetry(), EnforcementMode: dk.FeatureEnforcementMode(), ReadOnlyCSIDriver: dk.FeatureReadOnlyCsiVolume(), - CSIMode: dk.IsCSIAvailable(), + CSIMode: dk.OneAgent().IsCSIAvailable(), }, nil } @@ -208,7 +208,7 @@ func (g *InitGenerator) getHostMonitoringNodes(dk *dynakube.DynaKube) (map[strin tenantUUID := dk.Status.OneAgent.ConnectionInfoStatus.TenantUUID imNodes := map[string]string{} - if !dk.CloudNativeFullstackMode() { + if !dk.OneAgent().IsCloudNativeFullstackMode() { return imNodes, nil } @@ -232,7 +232,7 @@ func (g *InitGenerator) calculateImNodes(dk *dynakube.DynaKube, tenantUUID strin return nil, err } - nodeSelector := labels.SelectorFromSet(dk.OneAgentNodeSelector()) + nodeSelector := labels.SelectorFromSet(dk.OneAgent().GetNodeSelector(nil)) updateNodeInfImNodes(dk, nodeInf, nodeSelector, tenantUUID) return nodeInf.imNodes, nil diff --git a/pkg/injection/namespace/initgeneration/initgeneration_test.go b/pkg/injection/namespace/initgeneration/initgeneration_test.go index 71d63e9985..2b725ec176 100644 --- a/pkg/injection/namespace/initgeneration/initgeneration_test.go +++ b/pkg/injection/namespace/initgeneration/initgeneration_test.go @@ -11,6 +11,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" @@ -467,14 +468,14 @@ func createDynakube() *dynakube.DynaKube { Spec: dynakube.DynaKubeSpec{ APIURL: "https://test-url/e/tenant/api", Tokens: "dynakube-test", - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{}, }}, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: "test-tenant", Endpoints: "beep.com;bop.com", @@ -522,9 +523,9 @@ func setTlsSecret(dk *dynakube.DynaKube, value string) { } func setNodesToInstances(dk *dynakube.DynaKube, nodeNames ...string) { - instances := map[string]dynakube.OneAgentInstance{} + instances := map[string]oneagent.Instance{} for _, name := range nodeNames { - instances[name] = dynakube.OneAgentInstance{} + instances[name] = oneagent.Instance{} } dk.Status.OneAgent.Instances = instances diff --git a/pkg/injection/namespace/mapper/mapper.go b/pkg/injection/namespace/mapper/mapper.go index 44ff29e554..f81a2dc868 100644 --- a/pkg/injection/namespace/mapper/mapper.go +++ b/pkg/injection/namespace/mapper/mapper.go @@ -18,7 +18,7 @@ type ConflictChecker struct { } func (c *ConflictChecker) check(dk *dynakube.DynaKube) error { - if !dk.NeedAppInjection() && !dk.MetadataEnrichmentEnabled() { + if !dk.OneAgent().IsAppInjectionNeeded() && !dk.MetadataEnrichmentEnabled() { return nil } @@ -82,13 +82,13 @@ func match(dk *dynakube.DynaKube, namespace *corev1.Namespace) (bool, error) { // matchOneAgent uses the namespace selector in the dynakube to check if it matches a given namespace // if the namespace selector is not set on the dynakube its an automatic match func matchOneAgent(dk *dynakube.DynaKube, namespace *corev1.Namespace) (bool, error) { - if !dk.NeedAppInjection() { + if !dk.OneAgent().IsAppInjectionNeeded() { return false, nil - } else if dk.OneAgentNamespaceSelector() == nil { + } else if dk.OneAgent().GetNamespaceSelector() == nil { return true, nil } - selector, err := metav1.LabelSelectorAsSelector(dk.OneAgentNamespaceSelector()) + selector, err := metav1.LabelSelectorAsSelector(dk.OneAgent().GetNamespaceSelector()) if err != nil { return false, errors.WithStack(err) } diff --git a/pkg/injection/namespace/mapper/mapper_test.go b/pkg/injection/namespace/mapper/mapper_test.go index 875a027db5..85fb5433fd 100644 --- a/pkg/injection/namespace/mapper/mapper_test.go +++ b/pkg/injection/namespace/mapper/mapper_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -22,8 +23,8 @@ func createBaseDynakube(name string, appInjection bool, metadataEnrichment bool) } if appInjection { - dk.Spec.OneAgent = dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}} + dk.Spec.OneAgent = oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}} } return dk diff --git a/pkg/oci/registry/client_test.go b/pkg/oci/registry/client_test.go index f4824aacc1..8c89263232 100644 --- a/pkg/oci/registry/client_test.go +++ b/pkg/oci/registry/client_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -28,8 +29,8 @@ func TestProxy(t *testing.T) { Spec: dynakube.DynaKubeSpec{ Proxy: &value.Source{Value: proxyRawURL}, APIURL: "https://testApiUrl.dev.dynatracelabs.com/api", - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, } @@ -57,8 +58,8 @@ func TestSkipCertCheck(t *testing.T) { }, Spec: dynakube.DynaKubeSpec{ APIURL: "https://testApiUrl.dev.dynatracelabs.com/api", - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, } diff --git a/pkg/webhook/mutation/namespace/webhook_test.go b/pkg/webhook/mutation/namespace/webhook_test.go index fb1b146823..d4271c29c2 100644 --- a/pkg/webhook/mutation/namespace/webhook_test.go +++ b/pkg/webhook/mutation/namespace/webhook_test.go @@ -6,6 +6,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" jsonpatch "github.com/evanphx/json-patch" "github.com/stretchr/testify/assert" @@ -22,9 +23,9 @@ func TestInjection(t *testing.T) { dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{Name: "codeModules-1", Namespace: "dynatrace"}, Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ NamespaceSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ "inject": "true", diff --git a/pkg/webhook/mutation/pod/init_container.go b/pkg/webhook/mutation/pod/init_container.go index 545625369f..90013eec66 100644 --- a/pkg/webhook/mutation/pod/init_container.go +++ b/pkg/webhook/mutation/pod/init_container.go @@ -39,12 +39,12 @@ func createInstallInitContainerBase(webhookImage, clusterID string, pod *corev1. } func initContainerResources(dk dynakube.DynaKube) corev1.ResourceRequirements { - customInitResources := dk.InitResources() + customInitResources := dk.OneAgent().GetInitResources() if customInitResources != nil { return *customInitResources } - if !dk.IsCSIAvailable() { + if !dk.OneAgent().IsCSIAvailable() { return corev1.ResourceRequirements{} } diff --git a/pkg/webhook/mutation/pod/metadata/mutator_test.go b/pkg/webhook/mutation/pod/metadata/mutator_test.go index 30d5f08f19..20b04cab12 100644 --- a/pkg/webhook/mutation/pod/metadata/mutator_test.go +++ b/pkg/webhook/mutation/pod/metadata/mutator_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" @@ -373,16 +374,16 @@ func getTestDynakube() *dynakube.DynaKube { }, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, ActiveGate: activegate.Spec{ Capabilities: []activegate.CapabilityDisplayName{activegate.MetricsIngestCapability.DisplayName}, }, }, Status: dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: "test-tenant", }, diff --git a/pkg/webhook/mutation/pod/oneagent/annotations.go b/pkg/webhook/mutation/pod/oneagent/annotations.go index 3aea944516..2c29e3672b 100644 --- a/pkg/webhook/mutation/pod/oneagent/annotations.go +++ b/pkg/webhook/mutation/pod/oneagent/annotations.go @@ -40,6 +40,6 @@ func getInstallerInfo(pod *corev1.Pod, dk dynakube.DynaKube) installerInfo { technologies: url.QueryEscape(maputils.GetField(pod.Annotations, dtwebhook.AnnotationTechnologies, "all")), installPath: maputils.GetField(pod.Annotations, dtwebhook.AnnotationInstallPath, dtwebhook.DefaultInstallPath), installerURL: maputils.GetField(pod.Annotations, dtwebhook.AnnotationInstallerUrl, ""), - version: dk.CodeModulesVersion(), + version: dk.OneAgent().GetCodeModulesVersion(), } } diff --git a/pkg/webhook/mutation/pod/oneagent/env_test.go b/pkg/webhook/mutation/pod/oneagent/env_test.go index 9afe5edf8d..d10c0c66e1 100644 --- a/pkg/webhook/mutation/pod/oneagent/env_test.go +++ b/pkg/webhook/mutation/pod/oneagent/env_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/stretchr/testify/assert" @@ -107,8 +108,8 @@ func TestAddDeploymentMetadataEnv(t *testing.T) { container := &corev1.Container{} dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, } @@ -122,8 +123,8 @@ func TestAddDeploymentMetadataEnv(t *testing.T) { container := &corev1.Container{} dk := dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, }, } diff --git a/pkg/webhook/mutation/pod/oneagent/mutator.go b/pkg/webhook/mutation/pod/oneagent/mutator.go index ef8790066c..43e30a3057 100644 --- a/pkg/webhook/mutation/pod/oneagent/mutator.go +++ b/pkg/webhook/mutation/pod/oneagent/mutator.go @@ -40,12 +40,12 @@ func NewMutator(image, clusterID, webhookNamespace string, client client.Client, func (mut *Mutator) Enabled(request *dtwebhook.BaseRequest) bool { enabledOnPod := maputils.GetFieldBool(request.Pod.Annotations, dtwebhook.AnnotationOneAgentInject, request.DynaKube.FeatureAutomaticInjection()) - enabledOnDynakube := request.DynaKube.OneAgentNamespaceSelector() != nil + enabledOnDynakube := request.DynaKube.OneAgent().GetNamespaceSelector() != nil matchesNamespaceSelector := true // if no namespace selector is configured, we just pass set this to true - if request.DynaKube.OneAgentNamespaceSelector().Size() > 0 { - selector, _ := metav1.LabelSelectorAsSelector(request.DynaKube.OneAgentNamespaceSelector()) + if request.DynaKube.OneAgent().GetNamespaceSelector().Size() > 0 { + selector, _ := metav1.LabelSelectorAsSelector(request.DynaKube.OneAgent().GetNamespaceSelector()) matchesNamespaceSelector = selector.Matches(labels.Set(request.Namespace.Labels)) } @@ -126,13 +126,13 @@ func (mut *Mutator) isInjectionPossible(request *dtwebhook.MutationRequest) (boo reasons = append(reasons, EmptyTenantUUIDReason) } - if !dk.IsOneAgentCommunicationRouteClear() { + if !dk.OneAgent().IsCommunicationRouteClear() { log.Info("OneAgent communication route is not clear, OneAgent cannot be injected", "pod", request.PodName()) reasons = append(reasons, EmptyConnectionInfoReason) } - if dk.CodeModulesVersion() == "" && dk.CodeModulesImage() == "" { + if dk.OneAgent().GetCodeModulesVersion() == "" && dk.OneAgent().GetCodeModulesImage() == "" { log.Info("information about the codemodules (version or image) is not available, OneAgent cannot be injected", "pod", request.PodName()) reasons = append(reasons, UnknownCodeModuleReason) diff --git a/pkg/webhook/mutation/pod/oneagent/mutator_test.go b/pkg/webhook/mutation/pod/oneagent/mutator_test.go index 1b7aaf47fe..af577420eb 100644 --- a/pkg/webhook/mutation/pod/oneagent/mutator_test.go +++ b/pkg/webhook/mutation/pod/oneagent/mutator_test.go @@ -10,6 +10,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" @@ -42,7 +43,7 @@ func TestEnabled(t *testing.T) { t.Run("on by default", func(t *testing.T) { mutator := createTestPodMutator(nil) request := createTestMutationRequest(nil, nil, getTestNamespace(nil)) - request.DynaKube.Spec.OneAgent.ApplicationMonitoring = &dynakube.ApplicationMonitoringSpec{} + request.DynaKube.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} enabled := mutator.Enabled(request.BaseRequest) @@ -60,7 +61,7 @@ func TestEnabled(t *testing.T) { t.Run("on with feature flag", func(t *testing.T) { mutator := createTestPodMutator(nil) request := createTestMutationRequest(nil, nil, getTestNamespace(nil)) - request.DynaKube.Spec.OneAgent.ApplicationMonitoring = &dynakube.ApplicationMonitoringSpec{} + request.DynaKube.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} request.DynaKube.Annotations = map[string]string{dynakube.AnnotationFeatureAutomaticInjection: "true"} enabled := mutator.Enabled(request.BaseRequest) @@ -332,7 +333,7 @@ func injectionNotPossibleWithoutTenantUUID(t *testing.T) { func injectionNotPossibleWithoutCommunicationRoute(t *testing.T) { mutator := createTestPodMutator(nil) dk := getTestDynakube() - dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []dynakube.CommunicationHostStatus{} + dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{} request := createTestMutationRequest(dk, nil, getTestNamespace(nil)) ok, reason := mutator.isInjectionPossible(request) @@ -357,7 +358,7 @@ func injectionNotPossibleWithMultipleIssues(t *testing.T) { mutator := createTestPodMutator(nil) dk := getTestDynakube() dk.Status.OneAgent.ConnectionInfoStatus.TenantUUID = "" - dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []dynakube.CommunicationHostStatus{} + dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{} dk.Status.CodeModules.VersionStatus.Version = "" request := createTestMutationRequest(dk, nil, getTestNamespace(nil)) @@ -389,7 +390,7 @@ func getTestInitSecret() *corev1.Secret { } func addNamespaceSelector(dk *dynakube.DynaKube) *dynakube.DynaKube { - dk.Spec.OneAgent.ApplicationMonitoring = &dynakube.ApplicationMonitoringSpec{} + dk.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} dk.Spec.OneAgent.ApplicationMonitoring.NamespaceSelector = metav1.LabelSelector{ MatchLabels: map[string]string{ @@ -427,8 +428,8 @@ func getTestCSIDynakube() *dynakube.DynaKube { return &dynakube.DynaKube{ ObjectMeta: getTestDynakubeMeta(), Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{}, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, Status: getTestDynakubeStatus(), @@ -444,7 +445,7 @@ func getTestReadOnlyCSIDynakube() *dynakube.DynaKube { func getTestNoInjectionDynakube() *dynakube.DynaKube { dk := getTestCSIDynakube() - dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []dynakube.CommunicationHostStatus{} + dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{} dk.Status.CodeModules.VersionStatus.Version = "" dk.Status.OneAgent.ConnectionInfoStatus.TenantUUID = "" @@ -455,8 +456,8 @@ func getTestDynakube() *dynakube.DynaKube { return &dynakube.DynaKube{ ObjectMeta: getTestDynakubeMeta(), Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, }, Status: getTestDynakubeStatus(), @@ -467,8 +468,8 @@ func getTestDynakubeWithContainerExclusion() *dynakube.DynaKube { dk := &dynakube.DynaKube{ ObjectMeta: getTestDynakubeMeta(), Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, }, Status: getTestDynakubeStatus(), @@ -480,12 +481,12 @@ func getTestDynakubeWithContainerExclusion() *dynakube.DynaKube { func getTestDynakubeStatus() dynakube.DynaKubeStatus { return dynakube.DynaKubeStatus{ - OneAgent: dynakube.OneAgentStatus{ - ConnectionInfoStatus: dynakube.OneAgentConnectionInfoStatus{ + OneAgent: oneagent.Status{ + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ ConnectionInfo: communication.ConnectionInfo{ TenantUUID: "test-tenant-uuid", }, - CommunicationHosts: []dynakube.CommunicationHostStatus{ + CommunicationHosts: []oneagent.CommunicationHostStatus{ { Protocol: "http", Host: "dummyhost", @@ -494,7 +495,7 @@ func getTestDynakubeStatus() dynakube.DynaKubeStatus { }, }, }, - CodeModules: dynakube.CodeModulesStatus{ + CodeModules: oneagent.CodeModulesStatus{ VersionStatus: status.VersionStatus{ Version: "test-version", }, diff --git a/pkg/webhook/mutation/pod/oneagent/volumes.go b/pkg/webhook/mutation/pod/oneagent/volumes.go index 29c38f2045..dbe60aca44 100644 --- a/pkg/webhook/mutation/pod/oneagent/volumes.go +++ b/pkg/webhook/mutation/pod/oneagent/volumes.go @@ -161,7 +161,7 @@ func addVolumesForReadOnlyCSI(pod *corev1.Pod) { func getInstallerVolumeSource(dk dynakube.DynaKube) corev1.VolumeSource { volumeSource := corev1.VolumeSource{} - if dk.IsCSIAvailable() { + if dk.OneAgent().IsCSIAvailable() { volumeSource.CSI = &corev1.CSIVolumeSource{ Driver: dtcsi.DriverName, ReadOnly: ptr.To(dk.FeatureReadOnlyCsiVolume()), diff --git a/pkg/webhook/mutation/pod/webhook_test.go b/pkg/webhook/mutation/pod/webhook_test.go index 693af2004c..18765527fb 100644 --- a/pkg/webhook/mutation/pod/webhook_test.go +++ b/pkg/webhook/mutation/pod/webhook_test.go @@ -9,6 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" @@ -202,7 +203,7 @@ func TestDoubleInjection(t *testing.T) { // adding communicationHost to the dynakube to make the scenario more complicated // it shouldn't try to mutate the pod because now it could be enabled, that is just asking for trouble. communicationHostDK := getTestDynakube() - communicationHostDK.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []dynakube.CommunicationHostStatus{{Host: "test"}} + communicationHostDK.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{{Host: "test"}} fakeClient = fake.NewClient(communicationHostDK, getTestNamespace()) podWebhook.apiReader = fakeClient @@ -440,8 +441,8 @@ func getTestDynakubeDefaultAppMon() *dynakube.DynaKube { return &dynakube.DynaKube{ ObjectMeta: getTestDynakubeMeta(), Spec: dynakube.DynaKubeSpec{ - OneAgent: dynakube.OneAgentSpec{ - ApplicationMonitoring: &dynakube.ApplicationMonitoringSpec{}, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, }, } @@ -454,10 +455,10 @@ func getTestDynakubeMeta() metav1.ObjectMeta { } } -func getCloudNativeSpec(initResources *corev1.ResourceRequirements) dynakube.OneAgentSpec { - return dynakube.OneAgentSpec{ - CloudNativeFullStack: &dynakube.CloudNativeFullStackSpec{ - AppInjectionSpec: dynakube.AppInjectionSpec{ +func getCloudNativeSpec(initResources *corev1.ResourceRequirements) oneagent.Spec { + return oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ InitResources: initResources, }, }, diff --git a/test/features/applicationmonitoring/label_version_detection.go b/test/features/applicationmonitoring/label_version_detection.go index 97b8565f79..7d3898c426 100644 --- a/test/features/applicationmonitoring/label_version_detection.go +++ b/test/features/applicationmonitoring/label_version_detection.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/namespace" @@ -102,7 +103,7 @@ func LabelVersionDetection(t *testing.T) features.Feature { defaultDynakube := *dynakubeComponents.New( dynakubeComponents.WithName("dynakube-components-default"), dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), - dynakubeComponents.WithApplicationMonitoringSpec(&dynakube.ApplicationMonitoringSpec{}), + dynakubeComponents.WithApplicationMonitoringSpec(&oneagent.ApplicationMonitoringSpec{}), dynakubeComponents.WithNameBasedOneAgentNamespaceSelector(), ) @@ -110,7 +111,7 @@ func LabelVersionDetection(t *testing.T) features.Feature { dynakubeComponents.WithName("dynakube-components-labels"), dynakubeComponents.WithAnnotations(map[string]string{dynakube.AnnotationFeatureLabelVersionDetection: "true"}), dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), - dynakubeComponents.WithApplicationMonitoringSpec(&dynakube.ApplicationMonitoringSpec{}), + dynakubeComponents.WithApplicationMonitoringSpec(&oneagent.ApplicationMonitoringSpec{}), dynakubeComponents.WithNameBasedOneAgentNamespaceSelector(), ) @@ -221,7 +222,7 @@ func assertValue(ctx context.Context, t *testing.T, resource *resources.Resource } func buildDisabledBuildLabelNamespace(dk dynakube.DynaKube) corev1.Namespace { - return *namespace.New(disabledBuildLabelsNamespace, namespace.WithLabels(dk.OneAgentNamespaceSelector().MatchLabels)) + return *namespace.New(disabledBuildLabelsNamespace, namespace.WithLabels(dk.OneAgent().GetNamespaceSelector().MatchLabels)) } func buildDisabledBuildLabelSampleApp(t *testing.T, dk dynakube.DynaKube) *sample.App { @@ -229,7 +230,7 @@ func buildDisabledBuildLabelSampleApp(t *testing.T, dk dynakube.DynaKube) *sampl } func buildDefaultBuildLabelNamespace(dk dynakube.DynaKube) corev1.Namespace { - return *namespace.New(defaultBuildLabelsNamespace, namespace.WithLabels(dk.OneAgentNamespaceSelector().MatchLabels)) + return *namespace.New(defaultBuildLabelsNamespace, namespace.WithLabels(dk.OneAgent().GetNamespaceSelector().MatchLabels)) } func buildDefaultBuildLabelSampleApp(t *testing.T, dk dynakube.DynaKube) *sample.App { @@ -252,7 +253,7 @@ func buildDefaultBuildLabelSampleApp(t *testing.T, dk dynakube.DynaKube) *sample func buildCustomBuildLabelNamespace(dk dynakube.DynaKube) corev1.Namespace { return *namespace.New( customBuildLabelsNamespace, - namespace.WithLabels(dk.OneAgentNamespaceSelector().MatchLabels), + namespace.WithLabels(dk.OneAgent().GetNamespaceSelector().MatchLabels), namespace.WithAnnotation(map[string]string{ "mapping.release.dynatrace.com/version": "metadata.labels['my.domain/version']", "mapping.release.dynatrace.com/product": "metadata.labels['my.domain/product']", @@ -282,7 +283,7 @@ func buildCustomBuildLabelSampleApp(t *testing.T, dk dynakube.DynaKube) *sample. func buildPreservedBuildLabelNamespace(dk dynakube.DynaKube) corev1.Namespace { return *namespace.New( preservedBuildLabelsNamespace, - namespace.WithLabels(dk.OneAgentNamespaceSelector().MatchLabels), + namespace.WithLabels(dk.OneAgent().GetNamespaceSelector().MatchLabels), namespace.WithAnnotation(map[string]string{ "mapping.release.dynatrace.com/version": "metadata.labels['my.domain/version']", "mapping.release.dynatrace.com/product": "metadata.labels['my.domain/product']", @@ -350,7 +351,7 @@ func buildPreservedBuildLabelSampleApp(t *testing.T, dk dynakube.DynaKube) *samp func buildInvalidBuildLabelNamespace(dk dynakube.DynaKube) corev1.Namespace { return *namespace.New( invalidBuildLabelsNamespace, - namespace.WithLabels(dk.OneAgentNamespaceSelector().MatchLabels), + namespace.WithLabels(dk.OneAgent().GetNamespaceSelector().MatchLabels), namespace.WithAnnotation(map[string]string{ "mapping.release.dynatrace.com/stage": "metadata.labels['my.domain/invalid-stage']", "mapping.release.dynatrace.com/build-version": "metadata.labels['my.domain/invalid-build-version']", diff --git a/test/features/applicationmonitoring/metadata_enrichment.go b/test/features/applicationmonitoring/metadata_enrichment.go index b699d99a0f..9f7237939e 100644 --- a/test/features/applicationmonitoring/metadata_enrichment.go +++ b/test/features/applicationmonitoring/metadata_enrichment.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" maputil "github.com/Dynatrace/dynatrace-operator/pkg/util/map" @@ -47,7 +47,7 @@ func MetadataEnrichment(t *testing.T) features.Feature { testDynakube := *dynakubeComponents.New( dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), dynakubeComponents.WithMetadataEnrichment(), - dynakubeComponents.WithApplicationMonitoringSpec(&dynakube.ApplicationMonitoringSpec{}), + dynakubeComponents.WithApplicationMonitoringSpec(&oneagent.ApplicationMonitoringSpec{}), dynakubeComponents.WithNameBasedMetadataEnrichmentNamespaceSelector(), dynakubeComponents.WithNameBasedOneAgentNamespaceSelector(), ) @@ -59,7 +59,7 @@ func MetadataEnrichment(t *testing.T) features.Feature { } injectEverythingLabels := maputil.MergeMap( - testDynakube.OneAgentNamespaceSelector().MatchLabels, + testDynakube.OneAgent().GetNamespaceSelector().MatchLabels, testDynakube.MetadataEnrichmentNamespaceSelector().MatchLabels, ) @@ -119,7 +119,7 @@ func MetadataEnrichment(t *testing.T) features.Feature { name: "control oneagent-injection with namespace-selector - pod", app: sample.NewApp(t, &testDynakube, sample.WithName("pod-oa-label"), - sample.WithNamespaceLabels(testDynakube.OneAgentNamespaceSelector().MatchLabels), + sample.WithNamespaceLabels(testDynakube.OneAgent().GetNamespaceSelector().MatchLabels), ), assess: podHasOnlyOneAgentInitContainer, }, diff --git a/test/features/applicationmonitoring/read_only_csi_volume.go b/test/features/applicationmonitoring/read_only_csi_volume.go index 677978a75e..7473b6c991 100644 --- a/test/features/applicationmonitoring/read_only_csi_volume.go +++ b/test/features/applicationmonitoring/read_only_csi_volume.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/codemodules" @@ -33,7 +34,7 @@ func ReadOnlyCSIVolume(t *testing.T) features.Feature { testDynakube := *dynakubeComponents.New( dynakubeComponents.WithAnnotations(readOnlyInjection), dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), - dynakubeComponents.WithApplicationMonitoringSpec(&dynakube.ApplicationMonitoringSpec{}), + dynakubeComponents.WithApplicationMonitoringSpec(&oneagent.ApplicationMonitoringSpec{}), ) sampleDeployment := sample.NewApp(t, &testDynakube, sample.AsDeployment()) builder.Assess("install sample deployment namespace", sampleDeployment.InstallNamespace()) diff --git a/test/features/applicationmonitoring/without_csi.go b/test/features/applicationmonitoring/without_csi.go index 59386ddcbf..8129e8bd2c 100644 --- a/test/features/applicationmonitoring/without_csi.go +++ b/test/features/applicationmonitoring/without_csi.go @@ -6,7 +6,7 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" @@ -25,7 +25,7 @@ func WithoutCSI(t *testing.T) features.Feature { secretConfig := tenant.GetSingleTenantSecret(t) appOnlyDynakube := *dynakubeComponents.New( dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), - dynakubeComponents.WithApplicationMonitoringSpec(&dynakube.ApplicationMonitoringSpec{}), + dynakubeComponents.WithApplicationMonitoringSpec(&oneagent.ApplicationMonitoringSpec{}), ) dynakubeComponents.Install(builder, helpers.LevelAssess, &secretConfig, appOnlyDynakube) diff --git a/test/features/classic/classic.go b/test/features/classic/classic.go index 6a7bfacdda..3b467cd39d 100644 --- a/test/features/classic/classic.go +++ b/test/features/classic/classic.go @@ -5,7 +5,7 @@ package classic import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" @@ -22,7 +22,7 @@ func Feature(t *testing.T) features.Feature { secretConfig := tenant.GetSingleTenantSecret(t) testDynakube := *dynakubeComponents.New( dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), - dynakubeComponents.WithClassicFullstackSpec(&dynakube.HostInjectSpec{}), + dynakubeComponents.WithClassicFullstackSpec(&oneagent.HostInjectSpec{}), ) // check if oneAgent pods startup and report as ready diff --git a/test/features/classic/switch_modes/switch_modes.go b/test/features/classic/switch_modes/switch_modes.go index af59b2afad..90b2b7c080 100644 --- a/test/features/classic/switch_modes/switch_modes.go +++ b/test/features/classic/switch_modes/switch_modes.go @@ -5,12 +5,12 @@ package switch_modes import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" - "github.com/Dynatrace/dynatrace-operator/test/helpers/components/oneagent" + oneagenthelper "github.com/Dynatrace/dynatrace-operator/test/helpers/components/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers/sample" "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" "sigs.k8s.io/e2e-framework/pkg/features" @@ -32,7 +32,7 @@ func Feature(t *testing.T) features.Feature { } dynakubeClassicFullStack := *dynakubeComponents.New( - append(commonOptions, dynakubeComponents.WithClassicFullstackSpec(&dynakube.HostInjectSpec{}))..., + append(commonOptions, dynakubeComponents.WithClassicFullstackSpec(&oneagent.HostInjectSpec{}))..., ) sampleAppClassic := sample.NewApp(t, &dynakubeClassicFullStack, @@ -48,7 +48,7 @@ func Feature(t *testing.T) features.Feature { ) dynakubeComponents.Delete(builder, helpers.LevelAssess, dynakubeClassicFullStack) - oneagent.RunClassicUninstall(builder, helpers.LevelAssess, dynakubeClassicFullStack) + oneagenthelper.RunClassicUninstall(builder, helpers.LevelAssess, dynakubeClassicFullStack) sampleAppCloudNative := sample.NewApp(t, &dynakubeCloudNative, sample.AsDeployment(), sample.WithName(sampleAppsCloudNativeName), diff --git a/test/features/cloudnative/codemodules/codemodules.go b/test/features/cloudnative/codemodules/codemodules.go index 29524dbed3..f9bfd984ff 100644 --- a/test/features/cloudnative/codemodules/codemodules.go +++ b/test/features/cloudnative/codemodules/codemodules.go @@ -15,6 +15,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" @@ -79,13 +80,13 @@ func InstallFromImage(t *testing.T) features.Feature { appDynakube := *dynakubeComponents.New( dynakubeComponents.WithName("app-codemodules"), - dynakubeComponents.WithApplicationMonitoringSpec(&dynakube.ApplicationMonitoringSpec{AppInjectionSpec: *codeModulesAppInjectSpec(t)}), + dynakubeComponents.WithApplicationMonitoringSpec(&oneagent.ApplicationMonitoringSpec{AppInjectionSpec: *codeModulesAppInjectSpec(t)}), dynakubeComponents.WithNameBasedOneAgentNamespaceSelector(), dynakubeComponents.WithNameBasedMetadataEnrichmentNamespaceSelector(), dynakubeComponents.WithApiUrl(secretConfigs[1].ApiUrl), ) - labels := cloudNativeDynakube.OneAgentNamespaceSelector().MatchLabels + labels := cloudNativeDynakube.OneAgent().GetNamespaceSelector().MatchLabels sampleNamespace := *namespace.New("codemodules-sample", namespace.WithLabels(labels)) sampleApp := sample.NewApp(t, &cloudNativeDynakube, @@ -385,14 +386,14 @@ func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Featur return builder.Feature() } -func codeModulesCloudNativeSpec(t *testing.T) *dynakube.CloudNativeFullStackSpec { - return &dynakube.CloudNativeFullStackSpec{ +func codeModulesCloudNativeSpec(t *testing.T) *oneagent.CloudNativeFullStackSpec { + return &oneagent.CloudNativeFullStackSpec{ AppInjectionSpec: *codeModulesAppInjectSpec(t), } } -func codeModulesAppInjectSpec(t *testing.T) *dynakube.AppInjectionSpec { - return &dynakube.AppInjectionSpec{ +func codeModulesAppInjectSpec(t *testing.T) *oneagent.AppInjectionSpec { + return &oneagent.AppInjectionSpec{ CodeModulesImage: registry.GetLatestCodeModulesImageURI(t), } } @@ -414,7 +415,7 @@ func imageHasBeenDownloaded(dk dynakube.DynaKube) features.Func { require.NoError(t, err) buffer := new(bytes.Buffer) _, err = io.Copy(buffer, logStream) - isNew := strings.Contains(buffer.String(), "Installed agent version: "+dk.CustomCodeModulesImage()) + isNew := strings.Contains(buffer.String(), "Installed agent version: "+dk.OneAgent().GetCustomCodeModulesImage()) isOld := strings.Contains(buffer.String(), "agent already installed") t.Logf("wait for Installed agent version in %s", podItem.Name) @@ -548,13 +549,13 @@ func checkOneAgentEnvVars(dk dynakube.DynaKube) features.Func { return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { resources := envConfig.Client().Resources() err := daemonset.NewQuery(ctx, resources, client.ObjectKey{ - Name: dk.OneAgentDaemonsetName(), + Name: dk.OneAgent().GetDaemonsetName(), Namespace: dk.Namespace, }).ForEachPod(func(podItem corev1.Pod) { require.NotNil(t, podItem) require.NotNil(t, podItem.Spec) - checkEnvVarsInContainer(t, podItem, dk.OneAgentDaemonsetName(), httpsProxy) + checkEnvVarsInContainer(t, podItem, dk.OneAgent().GetDaemonsetName(), httpsProxy) }) require.NoError(t, err) diff --git a/test/features/cloudnative/init_containers.go b/test/features/cloudnative/init_containers.go index d126ba83a5..a835330eb3 100644 --- a/test/features/cloudnative/init_containers.go +++ b/test/features/cloudnative/init_containers.go @@ -6,7 +6,7 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/pod" "github.com/Dynatrace/dynatrace-operator/test/helpers/logs" @@ -81,8 +81,8 @@ func checkInitContainers(sampleApp *sample.App) features.Func { } } -func DefaultCloudNativeSpec() *dynakube.CloudNativeFullStackSpec { - return &dynakube.CloudNativeFullStackSpec{ - HostInjectSpec: dynakube.HostInjectSpec{}, +func DefaultCloudNativeSpec() *oneagent.CloudNativeFullStackSpec { + return &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{}, } } diff --git a/test/features/cloudnative/switch_modes/switch_modes.go b/test/features/cloudnative/switch_modes/switch_modes.go index bb8b071b45..7a894e7b11 100644 --- a/test/features/cloudnative/switch_modes/switch_modes.go +++ b/test/features/cloudnative/switch_modes/switch_modes.go @@ -5,7 +5,7 @@ package switch_modes import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" @@ -27,7 +27,7 @@ func Feature(t *testing.T) features.Feature { commonOptions := []dynakubeComponents.Option{ dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), } - dynakubeCloudNative := *dynakubeComponents.New(append(commonOptions, dynakubeComponents.WithCloudNativeSpec(&dynakube.CloudNativeFullStackSpec{}))...) + dynakubeCloudNative := *dynakubeComponents.New(append(commonOptions, dynakubeComponents.WithCloudNativeSpec(&oneagent.CloudNativeFullStackSpec{}))...) sampleAppCloudNative := sample.NewApp(t, &dynakubeCloudNative, sample.AsDeployment(), sample.WithName(sampleAppsCloudNativeName), @@ -45,7 +45,7 @@ func Feature(t *testing.T) features.Feature { cloudnative.AssessSampleInitContainers(builder, sampleAppCloudNative) // switch to classic full stack - dynakubeClassicFullStack := *dynakubeComponents.New(append(commonOptions, dynakubeComponents.WithClassicFullstackSpec(&dynakube.HostInjectSpec{}))...) + dynakubeClassicFullStack := *dynakubeComponents.New(append(commonOptions, dynakubeComponents.WithClassicFullstackSpec(&oneagent.HostInjectSpec{}))...) sampleAppClassicFullStack := sample.NewApp(t, &dynakubeClassicFullStack, sample.AsDeployment(), sample.WithName(sampleAppsClassicName), diff --git a/test/features/support_archive/support_archive.go b/test/features/support_archive/support_archive.go index ad716ca7d5..558f85d4d3 100644 --- a/test/features/support_archive/support_archive.go +++ b/test/features/support_archive/support_archive.go @@ -14,6 +14,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" agconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/functional" "github.com/Dynatrace/dynatrace-operator/test/features/consts" @@ -66,7 +67,7 @@ func Feature(t *testing.T) features.Feature { MatchLabels: injectLabels, }), dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), - dynakubeComponents.WithCloudNativeSpec(&dynakube.CloudNativeFullStackSpec{}), + dynakubeComponents.WithCloudNativeSpec(&oneagent.CloudNativeFullStackSpec{}), dynakubeComponents.WithActiveGate(), dynakubeComponents.WithActiveGateTLSSecret(consts.AgSecretName), dynakubeComponents.WithCustomPullSecret(consts.DevRegistryPullSecretName), diff --git a/test/helpers/components/codemodules/codemodules.go b/test/helpers/components/codemodules/codemodules.go index a1da4eff62..c593c30720 100644 --- a/test/helpers/components/codemodules/codemodules.go +++ b/test/helpers/components/codemodules/codemodules.go @@ -36,7 +36,7 @@ func CheckRuxitAgentProcFileHasNoConnInfo(testDynakube dynakube.DynaKube) featur Namespace: testDynakube.Namespace, }).ForEachPod(func(podItem corev1.Pod) { // /data/codemodules/1.273.0.20230719-145632/agent/conf/ruxitagentproc.conf - dir := filepath.Join("/data", "codemodules", dk.CodeModulesVersion(), "agent", "conf", RuxitAgentProcFile) + dir := filepath.Join("/data", "codemodules", dk.OneAgent().GetCodeModulesVersion(), "agent", "conf", RuxitAgentProcFile) readFileCommand := shell.ReadFile(dir) result, err := pod.Exec(ctx, resources, podItem, "provisioner", readFileCommand...) require.NoError(t, err) diff --git a/test/helpers/components/dynakube/dynakube.go b/test/helpers/components/dynakube/dynakube.go index 18fbc55c97..d03f878991 100644 --- a/test/helpers/components/dynakube/dynakube.go +++ b/test/helpers/components/dynakube/dynakube.go @@ -73,17 +73,17 @@ func VerifyStartupPreviousVersion(builder *features.FeatureBuilder, level featur func Delete(builder *features.FeatureBuilder, level features.Level, dk dynakube.DynaKube) { builder.WithStep("dynakube deleted", level, remove(dk)) - if dk.NeedsOneAgent() { - builder.WithStep("oneagent pods stopped", level, oneagent.WaitForDaemonSetPodsDeletion(dk.OneAgentDaemonsetName(), dk.Namespace)) + if dk.OneAgent().IsDaemonsetRequired() { + builder.WithStep("oneagent pods stopped", level, oneagent.WaitForDaemonSetPodsDeletion(dk.OneAgent().GetDaemonsetName(), dk.Namespace)) } - if dk.ClassicFullStackMode() { + if dk.OneAgent().IsClassicFullStackMode() { oneagent.RunClassicUninstall(builder, level, dk) } } func VerifyStartup(builder *features.FeatureBuilder, level features.Level, dk dynakube.DynaKube) { - if dk.NeedsOneAgent() { - builder.WithStep("oneagent started", level, oneagent.WaitForDaemonset(dk.OneAgentDaemonsetName(), dk.Namespace)) + if dk.OneAgent().IsDaemonsetRequired() { + builder.WithStep("oneagent started", level, oneagent.WaitForDaemonset(dk.OneAgent().GetDaemonsetName(), dk.Namespace)) } builder.WithStep( fmt.Sprintf("'%s' dynakube phase changes to 'Running'", dk.Name), diff --git a/test/helpers/components/dynakube/options.go b/test/helpers/components/dynakube/options.go index 0a623ee2cf..a0a89f3cb5 100644 --- a/test/helpers/components/dynakube/options.go +++ b/test/helpers/components/dynakube/options.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -95,9 +96,9 @@ func WithNameBasedOneAgentNamespaceSelector() Option { }, } switch { - case dk.CloudNativeFullstackMode(): + case dk.OneAgent().IsCloudNativeFullstackMode(): dk.Spec.OneAgent.CloudNativeFullStack.NamespaceSelector = namespaceSelector - case dk.ApplicationMonitoringMode(): + case dk.OneAgent().IsApplicationMonitoringMode(): dk.Spec.OneAgent.ApplicationMonitoring.NamespaceSelector = namespaceSelector } } @@ -117,9 +118,9 @@ func WithNameBasedMetadataEnrichmentNamespaceSelector() Option { func WithOneAgentNamespaceSelector(selector metav1.LabelSelector) Option { return func(dk *dynakube.DynaKube) { switch { - case dk.CloudNativeFullstackMode(): + case dk.OneAgent().IsCloudNativeFullstackMode(): dk.Spec.OneAgent.CloudNativeFullStack.NamespaceSelector = selector - case dk.ApplicationMonitoringMode(): + case dk.OneAgent().IsApplicationMonitoringMode(): dk.Spec.OneAgent.ApplicationMonitoring.NamespaceSelector = selector } } @@ -137,19 +138,19 @@ func WithIstioIntegration() Option { } } -func WithClassicFullstackSpec(classicFullStackSpec *dynakube.HostInjectSpec) Option { +func WithClassicFullstackSpec(classicFullStackSpec *oneagent.HostInjectSpec) Option { return func(dk *dynakube.DynaKube) { dk.Spec.OneAgent.ClassicFullStack = classicFullStackSpec } } -func WithCloudNativeSpec(cloudNativeFullStackSpec *dynakube.CloudNativeFullStackSpec) Option { +func WithCloudNativeSpec(cloudNativeFullStackSpec *oneagent.CloudNativeFullStackSpec) Option { return func(dk *dynakube.DynaKube) { dk.Spec.OneAgent.CloudNativeFullStack = cloudNativeFullStackSpec } } -func WithApplicationMonitoringSpec(applicationMonitoringSpec *dynakube.ApplicationMonitoringSpec) Option { +func WithApplicationMonitoringSpec(applicationMonitoringSpec *oneagent.ApplicationMonitoringSpec) Option { return func(dk *dynakube.DynaKube) { dk.Spec.OneAgent.ApplicationMonitoring = applicationMonitoringSpec } diff --git a/test/helpers/components/oneagent/daemonset.go b/test/helpers/components/oneagent/daemonset.go index c808bbbe3e..bf0d3cb0f4 100644 --- a/test/helpers/components/oneagent/daemonset.go +++ b/test/helpers/components/oneagent/daemonset.go @@ -25,7 +25,7 @@ func WaitForDaemonSetPodsDeletion(dsName, namespace string) features.Func { func Get(ctx context.Context, resource *resources.Resources, dk dynakubev1beta3.DynaKube) (appsv1.DaemonSet, error) { return daemonset.NewQuery(ctx, resource, client.ObjectKey{ - Name: dk.OneAgentDaemonsetName(), + Name: dk.OneAgent().GetDaemonsetName(), Namespace: dk.Namespace, }).Get() } diff --git a/test/helpers/istio/install.go b/test/helpers/istio/install.go index dd72d2fcc6..faeb9768e9 100644 --- a/test/helpers/istio/install.go +++ b/test/helpers/istio/install.go @@ -104,7 +104,7 @@ func assertIstioInitContainer(t *testing.T, pods corev1.PodList, testDynakube dy require.NotNil(t, podItem) require.NotNil(t, podItem.Spec) - if strings.HasPrefix(podItem.Name, testDynakube.OneAgentDaemonsetName()) { + if strings.HasPrefix(podItem.Name, testDynakube.OneAgent().GetDaemonsetName()) { continue } From 6e172ed87512f4dc097a9f6066a00e8565b795e0 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 19 Dec 2024 13:52:24 +0100 Subject: [PATCH 075/426] Remove yet unused csi-volume-attribute `retryTimeout` (#4233) (#4235) --- .../csi/driver/volumes/volume_config.go | 14 ------ .../csi/driver/volumes/volume_config_test.go | 44 ------------------- .../dynakube/oneagent/daemonset/volumes.go | 1 - 3 files changed, 59 deletions(-) diff --git a/pkg/controllers/csi/driver/volumes/volume_config.go b/pkg/controllers/csi/driver/volumes/volume_config.go index 3426ec4b98..0b7cf6ee34 100644 --- a/pkg/controllers/csi/driver/volumes/volume_config.go +++ b/pkg/controllers/csi/driver/volumes/volume_config.go @@ -1,8 +1,6 @@ package csivolumes import ( - "time" - "github.com/container-storage-interface/spec/lib/go/csi" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -29,7 +27,6 @@ type VolumeConfig struct { PodName string Mode string DynakubeName string - RetryTimeout time.Duration } // Transforms the NodePublishVolumeRequest into a VolumeConfig @@ -76,16 +73,6 @@ func ParseNodePublishVolumeRequest(req *csi.NodePublishVolumeRequest) (*VolumeCo return nil, status.Error(codes.InvalidArgument, "No dynakube attribute included with request") } - retryTimeoutValue := volCtx[CSIVolumeAttributeRetryTimeout] - if retryTimeoutValue == "" { - return nil, status.Error(codes.InvalidArgument, "No retryTimeout attribute included with request") - } - - retryTimeout, err := time.ParseDuration(retryTimeoutValue) - if err != nil { - return nil, status.Error(codes.InvalidArgument, "The retryTimeout attribute has incorrect format") - } - return &VolumeConfig{ VolumeInfo: VolumeInfo{ VolumeID: volID, @@ -94,7 +81,6 @@ func ParseNodePublishVolumeRequest(req *csi.NodePublishVolumeRequest) (*VolumeCo PodName: podName, Mode: mode, DynakubeName: dynakubeName, - RetryTimeout: retryTimeout, }, nil } diff --git a/pkg/controllers/csi/driver/volumes/volume_config_test.go b/pkg/controllers/csi/driver/volumes/volume_config_test.go index 6c248d48d9..1b4dd6f60c 100644 --- a/pkg/controllers/csi/driver/volumes/volume_config_test.go +++ b/pkg/controllers/csi/driver/volumes/volume_config_test.go @@ -2,7 +2,6 @@ package csivolumes import ( "testing" - "time" "github.com/container-storage-interface/spec/lib/go/csi" "github.com/stretchr/testify/assert" @@ -142,47 +141,6 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { require.Error(t, err) assert.Nil(t, volumeCfg) }) - t.Run(`retryTimeout missing from requests volume context`, func(t *testing.T) { - request := &csi.NodePublishVolumeRequest{ - VolumeCapability: &csi.VolumeCapability{ - AccessType: &csi.VolumeCapability_Mount{ - Mount: &csi.VolumeCapability_MountVolume{}, - }, - }, - VolumeId: testVolumeId, - TargetPath: testTargetPath, - VolumeContext: map[string]string{ - PodNameContextKey: testPodUID, - CSIVolumeAttributeDynakubeField: testDynakubeName, - CSIVolumeAttributeModeField: "test", - }, - } - volumeCfg, err := ParseNodePublishVolumeRequest(request) - - require.Error(t, err) - assert.Nil(t, volumeCfg) - }) - t.Run(`retryTimeout has incorrect format`, func(t *testing.T) { - request := &csi.NodePublishVolumeRequest{ - VolumeCapability: &csi.VolumeCapability{ - AccessType: &csi.VolumeCapability_Mount{ - Mount: &csi.VolumeCapability_MountVolume{}, - }, - }, - VolumeId: testVolumeId, - TargetPath: testTargetPath, - VolumeContext: map[string]string{ - PodNameContextKey: testPodUID, - CSIVolumeAttributeDynakubeField: testDynakubeName, - CSIVolumeAttributeModeField: "test", - CSIVolumeAttributeRetryTimeout: "5", - }, - } - volumeCfg, err := ParseNodePublishVolumeRequest(request) - - require.Error(t, err) - assert.Nil(t, volumeCfg) - }) t.Run(`request is parsed correctly`, func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeCapability: &csi.VolumeCapability{ @@ -196,7 +154,6 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { PodNameContextKey: testPodUID, CSIVolumeAttributeDynakubeField: testDynakubeName, CSIVolumeAttributeModeField: "test", - CSIVolumeAttributeRetryTimeout: "5m", }, } volumeCfg, err := ParseNodePublishVolumeRequest(request) @@ -208,6 +165,5 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { assert.Equal(t, testPodUID, volumeCfg.PodName) assert.Equal(t, "test", volumeCfg.Mode) assert.Equal(t, testDynakubeName, volumeCfg.DynakubeName) - assert.Equal(t, time.Minute*5, volumeCfg.RetryTimeout) }) } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go index e94697e308..e0d82674a2 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go @@ -141,7 +141,6 @@ func getCSIStorageVolume(dk *dynakube.DynaKube) corev1.Volume { VolumeAttributes: map[string]string{ csivolumes.CSIVolumeAttributeModeField: hostvolumes.Mode, csivolumes.CSIVolumeAttributeDynakubeField: dk.Name, - csivolumes.CSIVolumeAttributeRetryTimeout: dk.FeatureMaxCSIRetryTimeout().String(), }, }, }, From c765083ec5b8398a375f21219d7d1183bddf4bf7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:03:01 +0000 Subject: [PATCH 076/426] chore(deps): update github/codeql-action action to v3.28.0 (main) (#4238) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index bb3f1015a6..a342bb7d94 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/init@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/autobuild@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/analyze@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 3ed9a10c5a..f1c86b2f50 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 with: sarif_file: results.sarif From 65e51a0733337eb1a71ec936f41101ca7146d9b1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:41:28 +0000 Subject: [PATCH 077/426] chore(deps): update module github.com/vektra/mockery to v2.50.1 (main) (#4239) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 3365f5040c..882627c8ca 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.28.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.50.0 +mockery_version=v2.50.1 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest From bbbae0dfdb11d1d52b5ac01fe606ead793673035 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 27 Dec 2024 16:03:21 +0000 Subject: [PATCH 078/426] chore(deps): update peter-evans/create-pull-request action to v7.0.6 (main) (#4240) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0e27d09180..3ba4a74e1d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -407,7 +407,7 @@ jobs: hack/build/ci/generate-new-helm-index-yaml.sh "helm-pkg" ${{ needs.prepare.outputs.version_without_prefix }} - name: Create pull request for adding helm index to main branch if: ${{ !contains(github.ref, '-rc.') }} - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 with: base: main delete-branch: true From c849da42aeab31edc7fd309d69e0cd223dbf297b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 21:07:19 +0000 Subject: [PATCH 079/426] chore(deps): update dependency ruamel.yaml to v0.18.7 (main) (#4242) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/requirements.txt b/hack/requirements.txt index 5612512238..76bc014c74 100644 --- a/hack/requirements.txt +++ b/hack/requirements.txt @@ -1,4 +1,4 @@ argparse==1.4.0 pyyaml==6.0.2 json5==0.10.0 -ruamel.yaml==0.18.6 +ruamel.yaml==0.18.7 From 4bbeec390d337e03801bc8475a81b7ae49d90de2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2024 04:43:04 +0000 Subject: [PATCH 080/426] chore(deps): update module github.com/vektra/mockery to v2.50.2 (main) (#4244) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 882627c8ca..18b4142d7b 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.28.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.50.1 +mockery_version=v2.50.2 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest From 015c5d58b043833d99f32996d038e7e6e56c0a4b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2024 22:10:00 +0000 Subject: [PATCH 081/426] chore(deps): update module github.com/helm-unittest/helm-unittest to v0.7.1 (main) (#4246) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 18b4142d7b..d0183a3460 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -13,7 +13,7 @@ mockery_version=v2.50.2 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest -helmunittest_version=v0.7.0 +helmunittest_version=v0.7.1 # renovate depName=github.com/princjef/gomarkdoc gomarkdoc_version=v1.1.0 From 8435c4e71307a2176030c913fd86c32111b7721a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 09:16:05 +0000 Subject: [PATCH 082/426] chore(deps): update dependency ruamel.yaml to v0.18.8 (main) (#4248) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/requirements.txt b/hack/requirements.txt index 76bc014c74..be72386b68 100644 --- a/hack/requirements.txt +++ b/hack/requirements.txt @@ -1,4 +1,4 @@ argparse==1.4.0 pyyaml==6.0.2 json5==0.10.0 -ruamel.yaml==0.18.7 +ruamel.yaml==0.18.8 From 6f723dfbd2c0a8b011d56fe07d1b68eac8ba3a9a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 09:28:18 +0000 Subject: [PATCH 083/426] chore(deps): update module github.com/vektra/mockery to v2.50.3 (main) (#4249) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index d0183a3460..32e712f479 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.28.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.50.2 +mockery_version=v2.50.3 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest From 041309c0dfd9bc5ba1f111901a5b828e558d7ae7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 09:33:25 +0000 Subject: [PATCH 084/426] chore(deps): update module sigs.k8s.io/controller-tools/cmd to v0.17.0 (main) (#4245) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Marcell Sevcsik Co-authored-by: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> --- config/crd/bases/dynatrace.com_dynakubes.yaml | 2 +- config/crd/bases/dynatrace.com_edgeconnects.yaml | 2 +- .../default/templates/Common/crd/dynatrace-operator-crd.yaml | 4 ++-- hack/make/prerequisites.mk | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index 0568dc3943..d7937febd0 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.17.0 name: dynakubes.dynatrace.com spec: group: dynatrace.com diff --git a/config/crd/bases/dynatrace.com_edgeconnects.yaml b/config/crd/bases/dynatrace.com_edgeconnects.yaml index d56e1ccc41..14e4f7d8b8 100644 --- a/config/crd/bases/dynatrace.com_edgeconnects.yaml +++ b/config/crd/bases/dynatrace.com_edgeconnects.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.17.0 name: edgeconnects.dynatrace.com spec: group: dynatrace.com diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index ef09d4063c..5cd3dffb09 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.17.0 name: dynakubes.dynatrace.com spec: conversion: @@ -7531,7 +7531,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.17.0 name: edgeconnects.dynatrace.com spec: conversion: diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 32e712f479..60bb41b455 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -1,7 +1,7 @@ #renovate depName=sigs.k8s.io/kustomize/kustomize/v5 kustomize_version=v5.5.0 #renovate depName=sigs.k8s.io/controller-tools/cmd -controller_gen_version=v0.16.5 +controller_gen_version=v0.17.0 # renovate depName=github.com/golangci/golangci-lint golang_ci_cmd_version=v1.62.2 # renovate depName=github.com/daixiang0/gci From 5898cdd7a154a26022cfd28cce835bfd3b66a8d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:48:51 +0000 Subject: [PATCH 085/426] chore(deps): update module github.com/golangci/golangci-lint to v1.63.3 (main) (#4251) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- hack/make/prerequisites.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index aad785160b..2f61dbc399 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -97,7 +97,7 @@ jobs: uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 with: # renovate depName=github.com/golangci/golangci-lint - version: v1.62.2 + version: v1.63.3 args: --build-tags e2e --timeout 300s --out-${NO_FUTURE}format colored-line-number - name: Run deadcode id: deadcode diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 60bb41b455..a0f4745c4a 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -3,7 +3,7 @@ kustomize_version=v5.5.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.0 # renovate depName=github.com/golangci/golangci-lint -golang_ci_cmd_version=v1.62.2 +golang_ci_cmd_version=v1.63.3 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools From ec418f72eab6c4988c63242d0c081b896a744b17 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 4 Jan 2025 00:44:53 +0000 Subject: [PATCH 086/426] chore(deps): update module github.com/golangci/golangci-lint to v1.63.4 (main) (#4255) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- hack/make/prerequisites.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2f61dbc399..e2b2f7145c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -97,7 +97,7 @@ jobs: uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 with: # renovate depName=github.com/golangci/golangci-lint - version: v1.63.3 + version: v1.63.4 args: --build-tags e2e --timeout 300s --out-${NO_FUTURE}format colored-line-number - name: Run deadcode id: deadcode diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index a0f4745c4a..08385f86ad 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -3,7 +3,7 @@ kustomize_version=v5.5.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.0 # renovate depName=github.com/golangci/golangci-lint -golang_ci_cmd_version=v1.63.3 +golang_ci_cmd_version=v1.63.4 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools From 31403713496e3705e501c8bf537b8aa8923890f1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 4 Jan 2025 19:35:05 +0000 Subject: [PATCH 087/426] fix(deps): update module golang.org/x/oauth2 to v0.25.0 (main) (#4256) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2e1a4fd6a6..6c49547d8c 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.22.0 golang.org/x/net v0.33.0 - golang.org/x/oauth2 v0.24.0 + golang.org/x/oauth2 v0.25.0 golang.org/x/sys v0.28.0 google.golang.org/grpc v1.69.2 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index a97d968faf..d0d65900e1 100644 --- a/go.sum +++ b/go.sum @@ -187,8 +187,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= +golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 5851abcf00164b3f74f36aa5a3c749d278699ee2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:59:10 +0000 Subject: [PATCH 088/426] fix(deps): update module golang.org/x/sys to v0.29.0 (main) (#4257) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6c49547d8c..981fd467ca 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( golang.org/x/mod v0.22.0 golang.org/x/net v0.33.0 golang.org/x/oauth2 v0.25.0 - golang.org/x/sys v0.28.0 + golang.org/x/sys v0.29.0 google.golang.org/grpc v1.69.2 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.2 diff --git a/go.sum b/go.sum index d0d65900e1..44f7fabbc5 100644 --- a/go.sum +++ b/go.sum @@ -198,8 +198,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 73b36b8f58a71371d0c3945fad410b3fcd254838 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 5 Jan 2025 13:58:14 +0000 Subject: [PATCH 089/426] chore(deps): update dependency ruamel.yaml to v0.18.9 (main) (#4258) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/requirements.txt b/hack/requirements.txt index be72386b68..41aef7c1d1 100644 --- a/hack/requirements.txt +++ b/hack/requirements.txt @@ -1,4 +1,4 @@ argparse==1.4.0 pyyaml==6.0.2 json5==0.10.0 -ruamel.yaml==0.18.8 +ruamel.yaml==0.18.9 From f0aa6912d05a4dd6c93c6e8eec93372a0eec7e6c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 20:57:09 +0000 Subject: [PATCH 090/426] chore(deps): update dependency ruamel.yaml to v0.18.10 (main) (#4260) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/requirements.txt b/hack/requirements.txt index 41aef7c1d1..d6fa32b5ee 100644 --- a/hack/requirements.txt +++ b/hack/requirements.txt @@ -1,4 +1,4 @@ argparse==1.4.0 pyyaml==6.0.2 json5==0.10.0 -ruamel.yaml==0.18.9 +ruamel.yaml==0.18.10 From 0127885ea1c948418180c5b3f3d793f00fe1b5fc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 00:37:58 +0000 Subject: [PATCH 091/426] chore(deps): update module golang.org/x/tools to v0.29.0 (main) (#4262) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 08385f86ad..6622522a12 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -7,7 +7,7 @@ golang_ci_cmd_version=v1.63.4 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools -golang_tools_version=v0.28.0 +golang_tools_version=v0.29.0 # renovate depName=github.com/vektra/mockery mockery_version=v2.50.3 # renovate depName=github.com/igorshubovych/markdownlint-cli From ecb2558fbaee6de58b61cd3630bede48238041b3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 04:18:35 +0000 Subject: [PATCH 092/426] fix(deps): update module golang.org/x/net to v0.34.0 (main) (#4261) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 981fd467ca..ddca579dd7 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.22.0 - golang.org/x/net v0.33.0 + golang.org/x/net v0.34.0 golang.org/x/oauth2 v0.25.0 golang.org/x/sys v0.29.0 google.golang.org/grpc v1.69.2 @@ -84,7 +84,7 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sync v0.10.0 // indirect - golang.org/x/term v0.27.0 // indirect + golang.org/x/term v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.7.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 44f7fabbc5..9518501cf2 100644 --- a/go.sum +++ b/go.sum @@ -185,8 +185,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -200,8 +200,8 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= From 838baadaed873c9e51d4d26ad345fb812eb366d5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 11:16:19 +0100 Subject: [PATCH 093/426] chore(deps): update module github.com/vektra/mockery to v2.50.4 (main) (#4263) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Andrii Soldatenko --- hack/make/prerequisites.mk | 2 +- .../csi/provisioner/controller_test.go | 20 ++++++------- .../pkg/reconcile/reconciler.go | 28 +++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 6622522a12..330dcd8547 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.29.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.50.3 +mockery_version=v2.50.4 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest diff --git a/pkg/controllers/csi/provisioner/controller_test.go b/pkg/controllers/csi/provisioner/controller_test.go index 5ef4034869..0e03aa74f7 100644 --- a/pkg/controllers/csi/provisioner/controller_test.go +++ b/pkg/controllers/csi/provisioner/controller_test.go @@ -61,7 +61,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { dynakubeName := "test-dk" t.Run("no dynakube instance", func(t *testing.T) { - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) provisioner := &OneAgentProvisioner{ apiReader: fake.NewClient(), db: metadata.FakeMemoryDB(), @@ -74,7 +74,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { require.Equal(t, reconcile.Result{}, result) }) t.Run("dynakube deleted", func(t *testing.T) { - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) db := metadata.FakeMemoryDB() metadataDk := metadata.Dynakube{TenantUUID: tenantUUID, LatestVersion: agentVersion, Name: dkName} _ = db.InsertDynakube(ctx, &metadataDk) @@ -94,7 +94,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { require.Nil(t, ten) }) t.Run("csi driver not used (classicFullstack)", func(t *testing.T) { - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) provisioner := &OneAgentProvisioner{ apiReader: fake.NewClient( &dynakube.DynaKube{ @@ -143,7 +143,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { ) mockDtcBuilder := dtbuildermock.NewBuilder(t) - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) db := metadata.FakeMemoryDB() provisioner := &OneAgentProvisioner{ @@ -166,7 +166,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { require.Len(t, dynakubeMetadatas, 1) }) t.Run("no tokens", func(t *testing.T) { - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) provisioner := &OneAgentProvisioner{ apiReader: fake.NewClient( addFakeTenantUUID( @@ -200,7 +200,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { require.NotNil(t, result) }) t.Run("error when creating dynatrace client", func(t *testing.T) { - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) mockDtcBuilder := dtbuildermock.NewBuilder(t) mockDtcBuilder.On("SetContext", mock.Anything).Return(mockDtcBuilder) mockDtcBuilder.On("SetDynakube", mock.Anything).Return(mockDtcBuilder) @@ -249,7 +249,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { require.NotNil(t, result) }) t.Run("error creating directories", func(t *testing.T) { - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) errorfs := &mkDirAllErrorFs{ Fs: afero.NewMemMapFs(), } @@ -293,7 +293,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { log.Info("") }) t.Run("error getting latest agent version", func(t *testing.T) { - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) memFs := afero.NewMemMapFs() mockDtcBuilder := dtbuildermock.NewBuilder(t) dynakube := addFakeTenantUUID( @@ -354,7 +354,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { require.True(t, exists) }) t.Run("error getting dynakube from db", func(t *testing.T) { - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) memFs := afero.NewMemMapFs() mockDtcBuilder := dtbuildermock.NewBuilder(t) @@ -396,7 +396,7 @@ func TestOneAgentProvisioner_Reconcile(t *testing.T) { require.Empty(t, result) }) t.Run("correct directories are created", func(t *testing.T) { - gc := reconcilermock.NewReconciler(t) + gc := reconcilermock.NewReconciler[reconcile.Request](t) memFs := afero.NewMemMapFs() memDB := metadata.FakeMemoryDB() dynakube := addFakeTenantUUID( diff --git a/test/mocks/sigs.k8s.io/controller-runtime/pkg/reconcile/reconciler.go b/test/mocks/sigs.k8s.io/controller-runtime/pkg/reconcile/reconciler.go index 35e031341c..1d39ff638d 100644 --- a/test/mocks/sigs.k8s.io/controller-runtime/pkg/reconcile/reconciler.go +++ b/test/mocks/sigs.k8s.io/controller-runtime/pkg/reconcile/reconciler.go @@ -10,20 +10,20 @@ import ( ) // Reconciler is an autogenerated mock type for the Reconciler type -type Reconciler struct { +type Reconciler[request comparable] struct { mock.Mock } -type Reconciler_Expecter struct { +type Reconciler_Expecter[request comparable] struct { mock *mock.Mock } -func (_m *Reconciler) EXPECT() *Reconciler_Expecter { - return &Reconciler_Expecter{mock: &_m.Mock} +func (_m *Reconciler[request]) EXPECT() *Reconciler_Expecter[request] { + return &Reconciler_Expecter[request]{mock: &_m.Mock} } // Reconcile provides a mock function with given fields: _a0, _a1 -func (_m *Reconciler) Reconcile(_a0 context.Context, _a1 reconcile.Request) (reconcile.Result, error) { +func (_m *Reconciler[request]) Reconcile(_a0 context.Context, _a1 reconcile.Request) (reconcile.Result, error) { ret := _m.Called(_a0, _a1) if len(ret) == 0 { @@ -51,41 +51,41 @@ func (_m *Reconciler) Reconcile(_a0 context.Context, _a1 reconcile.Request) (rec } // Reconciler_Reconcile_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Reconcile' -type Reconciler_Reconcile_Call struct { +type Reconciler_Reconcile_Call[request comparable] struct { *mock.Call } // Reconcile is a helper method to define mock.On call // - _a0 context.Context // - _a1 reconcile.Request -func (_e *Reconciler_Expecter) Reconcile(_a0 interface{}, _a1 interface{}) *Reconciler_Reconcile_Call { - return &Reconciler_Reconcile_Call{Call: _e.mock.On("Reconcile", _a0, _a1)} +func (_e *Reconciler_Expecter[request]) Reconcile(_a0 interface{}, _a1 interface{}) *Reconciler_Reconcile_Call[request] { + return &Reconciler_Reconcile_Call[request]{Call: _e.mock.On("Reconcile", _a0, _a1)} } -func (_c *Reconciler_Reconcile_Call) Run(run func(_a0 context.Context, _a1 reconcile.Request)) *Reconciler_Reconcile_Call { +func (_c *Reconciler_Reconcile_Call[request]) Run(run func(_a0 context.Context, _a1 reconcile.Request)) *Reconciler_Reconcile_Call[request] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(reconcile.Request)) }) return _c } -func (_c *Reconciler_Reconcile_Call) Return(_a0 reconcile.Result, _a1 error) *Reconciler_Reconcile_Call { +func (_c *Reconciler_Reconcile_Call[request]) Return(_a0 reconcile.Result, _a1 error) *Reconciler_Reconcile_Call[request] { _c.Call.Return(_a0, _a1) return _c } -func (_c *Reconciler_Reconcile_Call) RunAndReturn(run func(context.Context, reconcile.Request) (reconcile.Result, error)) *Reconciler_Reconcile_Call { +func (_c *Reconciler_Reconcile_Call[request]) RunAndReturn(run func(context.Context, reconcile.Request) (reconcile.Result, error)) *Reconciler_Reconcile_Call[request] { _c.Call.Return(run) return _c } // NewReconciler creates a new instance of Reconciler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. -func NewReconciler(t interface { +func NewReconciler[request comparable](t interface { mock.TestingT Cleanup(func()) -}) *Reconciler { - mock := &Reconciler{} +}) *Reconciler[request] { + mock := &Reconciler[request]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) From 5ff9a5894a43714179e03b50f14fa76303b8f0e1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Jan 2025 18:53:07 +0000 Subject: [PATCH 094/426] chore(deps): update softprops/action-gh-release action to v2.2.1 (main) (#4264) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3ba4a74e1d..1fbcff097b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -361,7 +361,7 @@ jobs: mkdir -p tmp echo ${COSIGN_PUBLIC_KEY} | base64 -d > tmp/cosign.pub - name: Create pre-release - uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.0 + uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 if: ${{ contains(github.ref, '-rc.') }} with: body_path: ./CHANGELOG.md @@ -377,7 +377,7 @@ jobs: draft: true fail_on_unmatched_files: true - name: Create release - uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.0 + uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 if: ${{ !contains(github.ref, '-rc.') }} with: body_path: ./CHANGELOG.md From 38f1ccc75e6fed571f5d48969c15a20f676969d5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Jan 2025 22:18:34 +0000 Subject: [PATCH 095/426] fix(deps): update module sigs.k8s.io/controller-runtime to v0.19.4 (main) (#4265) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 3 ++- go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ddca579dd7..c27c93ed1f 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( k8s.io/client-go v0.32.0 k8s.io/mount-utils v0.32.0 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - sigs.k8s.io/controller-runtime v0.19.3 + sigs.k8s.io/controller-runtime v0.19.4 sigs.k8s.io/e2e-framework v0.3.0 sigs.k8s.io/yaml v1.4.0 ) @@ -48,6 +48,7 @@ require ( github.com/docker/docker-credential-helpers v0.8.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect diff --git a/go.sum b/go.sum index 9518501cf2..4633b7b9b8 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lSh github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= @@ -260,8 +262,8 @@ k8s.io/mount-utils v0.32.0 h1:KOQAhPzJICATXnc6XCkWoexKbkOexRnMCUW8APFfwg4= k8s.io/mount-utils v0.32.0/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw= -sigs.k8s.io/controller-runtime v0.19.3/go.mod h1:j4j87DqtsThvwTv5/Tc5NFRyyF/RF0ip4+62tbTSIUM= +sigs.k8s.io/controller-runtime v0.19.4 h1:SUmheabttt0nx8uJtoII4oIP27BVVvAKFvdvGFwV/Qo= +sigs.k8s.io/controller-runtime v0.19.4/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= From c6769fa4857512b43cb03271172f4aa73f3eb7f4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 06:12:07 +0000 Subject: [PATCH 096/426] chore(deps): update docker/build-push-action action to v6.11.0 (main) (#4267) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 7966231b3f..453af012ff 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -31,7 +31,7 @@ runs: run: | hack/build/ci/third-party-licenses.sh - name: Build target - uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 + uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 with: builder: ${{ steps.buildx.outputs.name }} build-args: | From 4c7e970726a0ceeab068e9e63a30e0ea4d8f7890 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 08:14:01 +0000 Subject: [PATCH 097/426] chore(deps): update docker/setup-qemu-action action to v3.3.0 (main) (#4268) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 453af012ff..bc2e351786 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -14,7 +14,7 @@ runs: using: "composite" steps: - name: Set up QEMU - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 + uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3.3.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 - name: Set up Golang From d53e4abbef621b3adc36c8dfe602bad657dc9e7a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 09:38:49 +0000 Subject: [PATCH 098/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1736404036 (main) (#4273) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 177b60d294..06492e53a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS=" -o ./build/_output/bin/dynatrace-operator ./cmd/ FROM registry.access.redhat.com/ubi9-micro:9.5-1734513256@sha256:becdf7fff4509ee81df982000d0adef858a7ae7995dfb7d774b9ded6a461ebad AS base -FROM registry.access.redhat.com/ubi9:9.5-1734495538@sha256:38791b293262ac2169eca2717e68e626a047d2b89fbd1da544db24ed0204efeb AS dependency +FROM registry.access.redhat.com/ubi9:9.5-1736404036@sha256:53d6c19d664f4f418ce5c823d3a33dbb562a2550ea249cf07ef10aa063ace38f AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 4c3ae7c3550039789755c1060d6f918757007913 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 10:26:42 +0000 Subject: [PATCH 099/426] chore(deps): update registry.k8s.io/sig-storage/csi-node-driver-registrar docker tag to v2.13.0 (main) (#4269) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 06492e53a0..8f290dc9b5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,7 @@ COPY --from=dependency /tmp/rootfs-dependency / COPY --from=operator-build /app/build/_output/bin /usr/local/bin # csi binaries -COPY --from=registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.12.0@sha256:0d23a6fd60c421054deec5e6d0405dc3498095a5a597e175236c0692f4adee0f /csi-node-driver-registrar /usr/local/bin +COPY --from=registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0@sha256:d7138bcc3aa5f267403d45ad4292c95397e421ea17a0035888850f424c7de25d /csi-node-driver-registrar /usr/local/bin COPY --from=registry.k8s.io/sig-storage/livenessprobe:v2.14.0@sha256:33692aed26aaf105b4d6e66280cceca9e0463f500c81b5d8c955428a75438f32 /livenessprobe /usr/local/bin COPY ./third_party_licenses /usr/share/dynatrace-operator/third_party_licenses From e0bea01f29ee1d119dbcf89ffbeaa2a0fefa1c32 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:35:41 +0000 Subject: [PATCH 100/426] chore(deps): update registry.k8s.io/sig-storage/livenessprobe docker tag to v2.15.0 (main) (#4270) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8f290dc9b5..4b63d134d0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ COPY --from=operator-build /app/build/_output/bin /usr/local/bin # csi binaries COPY --from=registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0@sha256:d7138bcc3aa5f267403d45ad4292c95397e421ea17a0035888850f424c7de25d /csi-node-driver-registrar /usr/local/bin -COPY --from=registry.k8s.io/sig-storage/livenessprobe:v2.14.0@sha256:33692aed26aaf105b4d6e66280cceca9e0463f500c81b5d8c955428a75438f32 /livenessprobe /usr/local/bin +COPY --from=registry.k8s.io/sig-storage/livenessprobe:v2.15.0@sha256:2c5f9dc4ea5ac5509d93c664ae7982d4ecdec40ca7b0638c24e5b16243b8360f /livenessprobe /usr/local/bin COPY ./third_party_licenses /usr/share/dynatrace-operator/third_party_licenses COPY LICENSE /licenses/ From e78611fcc22a32209e42438e1a47e744537d5c4a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:44:48 +0000 Subject: [PATCH 101/426] fix(deps): update module github.com/spf13/afero to v1.12.0 (main) (#4276) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index c27c93ed1f..e177cb3b89 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 - github.com/spf13/afero v1.11.0 + github.com/spf13/afero v1.12.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 go.uber.org/zap v1.27.0 @@ -87,11 +87,11 @@ require ( golang.org/x/sync v0.10.0 // indirect golang.org/x/term v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.7.0 // indirect + golang.org/x/time v0.8.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/protobuf v1.35.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect + google.golang.org/protobuf v1.36.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 4633b7b9b8..f75b78ffe3 100644 --- a/go.sum +++ b/go.sum @@ -132,8 +132,8 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= -github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -208,8 +208,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -222,14 +222,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 h1:fVoAXEKA4+yufmbdVYv+SE73+cPZbbbe8paLsHfkK+U= -google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= +google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 7ea8ba00d837650cc89d90b7242cea66cb7a44c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:23:54 +0000 Subject: [PATCH 102/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1736426761 (main) (#4278) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4b63d134d0..474f4c3e17 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS=" go build -tags "${GO_BUILD_TAGS}" -trimpath -ldflags="${GO_LINKER_ARGS}" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ -FROM registry.access.redhat.com/ubi9-micro:9.5-1734513256@sha256:becdf7fff4509ee81df982000d0adef858a7ae7995dfb7d774b9ded6a461ebad AS base +FROM registry.access.redhat.com/ubi9-micro:9.5-1736426761@sha256:f6e0a71b7e0875b54ea559c2e0a6478703268a8d4b8bdcf5d911d0dae76aef51 AS base FROM registry.access.redhat.com/ubi9:9.5-1736404036@sha256:53d6c19d664f4f418ce5c823d3a33dbb562a2550ea249cf07ef10aa063ace38f AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From 2fcfb850cab9768e1eb66dc4ee340ee7ef1b9dea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 10 Jan 2025 23:14:26 +0000 Subject: [PATCH 103/426] chore(deps): update actions/upload-artifact action to v4.6.0 (main) (#4282) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- .github/actions/preflight/action.yaml | 2 +- .github/workflows/openssf-scorecards.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index bc2e351786..fd77f13646 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -45,7 +45,7 @@ runs: labels: ${{ inputs.labels }} outputs: type=docker,dest=/tmp/operator-${{ inputs.platform }}.tar - name: Upload artifact - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: operator-${{ inputs.platform }} path: /tmp/operator-${{ inputs.platform }}.tar diff --git a/.github/actions/preflight/action.yaml b/.github/actions/preflight/action.yaml index 09dc8722ae..d8cbf1d2d9 100644 --- a/.github/actions/preflight/action.yaml +++ b/.github/actions/preflight/action.yaml @@ -34,7 +34,7 @@ runs: run: | hack/build/ci/preflight.sh "${{ env.PREFLIGHT_VERSION }}" "${{ env.IMAGE_URI}}" "${{ inputs.report-name }}" - name: Upload report - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: preflight-report path: ${{ inputs.report-name }} diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index f1c86b2f50..e0383c66f6 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -48,7 +48,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: SARIF file path: results.sarif From a89659fc26699a09875d1c897a9450d150e90227 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 11 Jan 2025 01:39:46 +0000 Subject: [PATCH 104/426] chore(deps): update github/codeql-action action to v3.28.1 (main) (#4283) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index a342bb7d94..cd1cdcf466 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 + uses: github/codeql-action/init@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 + uses: github/codeql-action/autobuild@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 + uses: github/codeql-action/analyze@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index e0383c66f6..06b169da80 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 + uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 with: sarif_file: results.sarif From 7a7d85ef2f55abfeb00132fae5911e889dbd7f60 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 13:40:29 +0000 Subject: [PATCH 105/426] fix(deps): update module google.golang.org/grpc to v1.69.4 (main) (#4284) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e177cb3b89..4bba09aa55 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( golang.org/x/net v0.34.0 golang.org/x/oauth2 v0.25.0 golang.org/x/sys v0.29.0 - google.golang.org/grpc v1.69.2 + google.golang.org/grpc v1.69.4 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.2 istio.io/client-go v1.24.2 diff --git a/go.sum b/go.sum index f75b78ffe3..c601d454d9 100644 --- a/go.sum +++ b/go.sum @@ -226,8 +226,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1: google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= -google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= -google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 0f2fd562c82d6eea8af979654795b95efc3c330e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 00:52:56 +0000 Subject: [PATCH 106/426] fix(deps): update module github.com/docker/cli to v27.5.0+incompatible (main) (#4286) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4bba09aa55..d17f88c0ee 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.3 require ( github.com/container-storage-interface/spec v1.11.0 - github.com/docker/cli v27.4.1+incompatible + github.com/docker/cli v27.5.0+incompatible github.com/evanphx/json-patch v5.9.0+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.2 diff --git a/go.sum b/go.sum index c601d454d9..8856567977 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v27.4.1+incompatible h1:VzPiUlRJ/xh+otB75gva3r05isHMo5wXDfPRi5/b4hI= -github.com/docker/cli v27.4.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM= +github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= From ef1cf622916eea0875725c83d18a70b4829160c5 Mon Sep 17 00:00:00 2001 From: Martin Bentancour Date: Tue, 14 Jan 2025 13:12:00 +0100 Subject: [PATCH 107/426] Adds serverPort for webhook in helm chart, and adds the same option for metricsPort and healthProbePort (#4212) Co-authored-by: Martin Bentancour Co-authored-by: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> --- cmd/webhook/manager.go | 28 ++++++++++++++----- cmd/webhook/manager_test.go | 9 ++++-- .../Common/webhook/deployment-webhook.yaml | 12 ++++++-- .../webhook/deployment-webhook_test.yaml | 24 ++++++++++++++-- config/helm/chart/default/values.yaml | 4 +++ 5 files changed, 61 insertions(+), 16 deletions(-) diff --git a/cmd/webhook/manager.go b/cmd/webhook/manager.go index 0041660144..65c719bf9d 100644 --- a/cmd/webhook/manager.go +++ b/cmd/webhook/manager.go @@ -17,13 +17,13 @@ import ( ) const ( - metricsBindAddress = ":8383" - healthProbeBindAddress = ":10080" - defaultPort = 8443 - livezEndpointName = "livez" - livenessEndpointName = "/" + livezEndpointName - readyzEndpointName = "readyz" - readinessEndpointName = "/" + readyzEndpointName + defaultMetricsBindAddress = ":8383" + defaultHealthProbeBindAddress = ":10080" + defaultPort = 8443 + livezEndpointName = "livez" + livenessEndpointName = "/" + livezEndpointName + readyzEndpointName = "readyz" + readinessEndpointName = "/" + readyzEndpointName ) type Provider struct { @@ -67,6 +67,20 @@ func (provider Provider) createOptions(namespace string) ctrl.Options { port = parsedWebhookPort } + metricsBindAddress := defaultMetricsBindAddress + + metricsBindAddressEnv := os.Getenv("METRICS_BIND_ADDRESS") + if metricsBindAddressEnv != "" { + metricsBindAddress = metricsBindAddressEnv + } + + healthProbeBindAddress := defaultHealthProbeBindAddress + + healthProbeBindAddressEnv := os.Getenv("HEALTH_PROBE_BIND_ADDRESS") + if healthProbeBindAddressEnv != "" { + healthProbeBindAddress = healthProbeBindAddressEnv + } + return ctrl.Options{ Scheme: scheme.Scheme, ReadinessEndpointName: readinessEndpointName, diff --git a/cmd/webhook/manager_test.go b/cmd/webhook/manager_test.go index 6c316c27dc..bd4f8ac511 100644 --- a/cmd/webhook/manager_test.go +++ b/cmd/webhook/manager_test.go @@ -29,15 +29,17 @@ func TestCreateOptions(t *testing.T) { assert.NotNil(t, options) assert.Contains(t, options.Cache.DefaultNamespaces, "test-namespace") assert.Equal(t, scheme.Scheme, options.Scheme) - assert.Equal(t, metricsBindAddress, options.Metrics.BindAddress) + assert.Equal(t, defaultMetricsBindAddress, options.Metrics.BindAddress) webhookServer, ok := options.WebhookServer.(*webhook.DefaultServer) require.True(t, ok) assert.Equal(t, defaultPort, webhookServer.Options.Port) }) - t.Run("creates options with configured webhook port", func(t *testing.T) { + t.Run("creates options with custom ports", func(t *testing.T) { t.Setenv("WEBHOOK_PORT", "6443") + t.Setenv("METRICS_BIND_ADDRESS", ":8081") + t.Setenv("HEALTH_PROBE_BIND_ADDRESS", ":10081") provider := Provider{} options := provider.createOptions("test-namespace") @@ -45,11 +47,12 @@ func TestCreateOptions(t *testing.T) { assert.NotNil(t, options) assert.Contains(t, options.Cache.DefaultNamespaces, "test-namespace") assert.Equal(t, scheme.Scheme, options.Scheme) - assert.Equal(t, metricsBindAddress, options.Metrics.BindAddress) webhookServer, ok := options.WebhookServer.(*webhook.DefaultServer) require.True(t, ok) assert.Equal(t, 6443, webhookServer.Options.Port) + assert.Equal(t, ":10081", options.HealthProbeBindAddress) + assert.Equal(t, ":8081", options.Metrics.BindAddress) }) t.Run("configures webhooks server", func(t *testing.T) { provider := NewProvider("certs-dir", "key-file", "cert-file") diff --git a/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml b/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml index e75d3ccc48..d118cf1bfc 100644 --- a/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml +++ b/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml @@ -87,6 +87,12 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name + - name: WEBHOOK_PORT + value: "{{ .Values.webhook.ports.server | default "8443" }}" + - name: HEALTH_PROBE_BIND_ADDRESS + value: ":{{ .Values.webhook.ports.healthProbe | default "10080" }}" + - name: METRICS_BIND_ADDRESS + value: ":{{ .Values.webhook.ports.metrics | default "8383" }}" {{ include "dynatrace-operator.modules-json-env" . | nindent 12 }} readinessProbe: httpGet: @@ -104,11 +110,11 @@ spec: periodSeconds: 10 ports: - name: server-port - containerPort: 8443 + containerPort: {{ .Values.webhook.ports.server | default 8443 }} - name: livez - containerPort: 10080 + containerPort: {{ .Values.webhook.ports.healthProbe | default 10080 }} - name: metrics - containerPort: 8080 + containerPort: {{ .Values.webhook.ports.metrics | default 8383 }} resources: requests: {{- toYaml (.Values.webhook).requests | nindent 14 }} diff --git a/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml b/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml index 2f0b1d24f1..c3c2cbaea5 100644 --- a/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml +++ b/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml @@ -116,6 +116,12 @@ tests: valueFrom: fieldRef: fieldPath: metadata.name + - name: WEBHOOK_PORT + value: "8443" + - name: HEALTH_PROBE_BIND_ADDRESS + value: :10080 + - name: METRICS_BIND_ADDRESS + value: :8383 - name: modules.json value: | { @@ -140,7 +146,7 @@ tests: name: server-port - containerPort: 10080 name: livez - - containerPort: 8080 + - containerPort: 8383 name: metrics readinessProbe: httpGet: @@ -306,6 +312,12 @@ tests: valueFrom: fieldRef: fieldPath: metadata.name + - name: WEBHOOK_PORT + value: "8443" + - name: HEALTH_PROBE_BIND_ADDRESS + value: :10080 + - name: METRICS_BIND_ADDRESS + value: :8383 - name: modules.json value: | { @@ -330,7 +342,7 @@ tests: name: server-port - containerPort: 10080 name: livez - - containerPort: 8080 + - containerPort: 8383 name: metrics readinessProbe: httpGet: @@ -461,6 +473,12 @@ tests: valueFrom: fieldRef: fieldPath: metadata.name + - name: WEBHOOK_PORT + value: "8443" + - name: HEALTH_PROBE_BIND_ADDRESS + value: :10080 + - name: METRICS_BIND_ADDRESS + value: :8383 - name: modules.json value: | { @@ -485,7 +503,7 @@ tests: name: server-port - containerPort: 10080 name: livez - - containerPort: 8080 + - containerPort: 8383 name: metrics readinessProbe: httpGet: diff --git a/config/helm/chart/default/values.yaml b/config/helm/chart/default/values.yaml index c85f309905..fb554f8240 100644 --- a/config/helm/chart/default/values.yaml +++ b/config/helm/chart/default/values.yaml @@ -57,6 +57,10 @@ operator: webhook: hostNetwork: false + ports: + server: 8443 + metrics: 8383 + healthProbe: 10080 nodeSelector: {} tolerations: [] labels: {} From 9f1814ac0747c3914a05dbc670e5a073fbbe99f3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 13:32:27 +0000 Subject: [PATCH 108/426] chore(deps): update module github.com/vektra/mockery to v2.51.0 (main) (#4287) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 330dcd8547..bb21ed913f 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.29.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.50.4 +mockery_version=v2.51.0 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest From 67c2fadfd2b1a9d93fa14399f6b399e038cd9ba3 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Tue, 14 Jan 2025 14:48:09 +0100 Subject: [PATCH 109/426] Always enable the ActiveGate http port (#4281) --- .../activegate/internal/statefulset/statefulset.go | 5 +---- .../activegate/internal/statefulset/statefulset_test.go | 7 +++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index 472460a291..ea99b3caf5 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -204,6 +204,7 @@ func (statefulSetBuilder Builder) buildCommonEnvs() []corev1.EnvVar { Optional: ptr.To(false), }, }}, + {Name: consts.EnvDtHttpPort, Value: strconv.Itoa(consts.HttpContainerPort)}, }) if statefulSetBuilder.capability.Properties().Group != "" { @@ -214,10 +215,6 @@ func (statefulSetBuilder Builder) buildCommonEnvs() []corev1.EnvVar { prioritymap.Append(statefulSetBuilder.envMap, corev1.EnvVar{Name: consts.EnvDtNetworkZone, Value: statefulSetBuilder.dynakube.Spec.NetworkZone}) } - if statefulSetBuilder.dynakube.ActiveGate().IsMetricsIngestEnabled() { - prioritymap.Append(statefulSetBuilder.envMap, corev1.EnvVar{Name: consts.EnvDtHttpPort, Value: strconv.Itoa(consts.HttpContainerPort)}) - } - prioritymap.Append(statefulSetBuilder.envMap, statefulSetBuilder.capability.Properties().Env, prioritymap.WithPriority(customEnvPriority)) return statefulSetBuilder.envMap.AsEnvVars() diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index 63bd7a3c52..fb3720e2f7 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -371,15 +371,14 @@ func TestBuildCommonEnvs(t *testing.T) { require.NotNil(t, idEnv) assert.Equal(t, testKubeUID, idEnv.Value) + dtHttpPortEnv := env.FindEnvVar(envs, consts.EnvDtHttpPort) + require.NotNil(t, dtHttpPortEnv) + metadataEnv := env.FindEnvVar(envs, deploymentmetadata.EnvDtDeploymentMetadata) require.NotNil(t, metadataEnv) assert.NotEmpty(t, metadataEnv.ValueFrom.ConfigMapKeyRef) assert.Equal(t, deploymentmetadata.ActiveGateMetadataKey, metadataEnv.ValueFrom.ConfigMapKeyRef.Key) assert.Equal(t, deploymentmetadata.GetDeploymentMetadataConfigMapName(dk.Name), metadataEnv.ValueFrom.ConfigMapKeyRef.Name) - - // metrics-ingest disabled -> HTTP port disabled - dtHttpPortEnv := env.FindEnvVar(envs, consts.EnvDtHttpPort) - require.Nil(t, dtHttpPortEnv) }) t.Run("adds extra envs with overrides", func(t *testing.T) { From 3b6085b86920fd2a945746e014418235b15dc1c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 02:25:50 +0000 Subject: [PATCH 110/426] chore(deps): update module sigs.k8s.io/kustomize/kustomize/v5 to v5.6.0 (main) (#4291) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index bb21ed913f..ed39f54d16 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -1,5 +1,5 @@ #renovate depName=sigs.k8s.io/kustomize/kustomize/v5 -kustomize_version=v5.5.0 +kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.0 # renovate depName=github.com/golangci/golangci-lint From 47b781e252ecc4d1aa464d1aefa74d336848ba02 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 16:42:37 +0000 Subject: [PATCH 111/426] chore(deps): update docker/build-push-action action to v6.12.0 (main) (#4294) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index fd77f13646..b3ca2d55d6 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -31,7 +31,7 @@ runs: run: | hack/build/ci/third-party-licenses.sh - name: Build target - uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 + uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 with: builder: ${{ steps.buildx.outputs.name }} build-args: | From 5f6b4f8c7a1fed74cfafdaef3fcd2880bc7eb2c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Jan 2025 01:49:06 +0000 Subject: [PATCH 112/426] fix(deps): update module github.com/google/go-containerregistry to v0.20.3 (main) (#4295) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 14 +++++++------- go.sum | 50 ++++++++++++++++++++++++++------------------------ 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index d17f88c0ee..4c2d3330bf 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/docker/cli v27.5.0+incompatible github.com/evanphx/json-patch v5.9.0+incompatible github.com/go-logr/logr v1.4.2 - github.com/google/go-containerregistry v0.20.2 + github.com/google/go-containerregistry v0.20.3 github.com/google/uuid v1.6.0 github.com/klauspost/compress v1.17.11 github.com/mattn/go-sqlite3 v1.14.24 @@ -42,10 +42,10 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker-credential-helpers v0.8.0 // indirect + github.com/docker/distribution v2.8.3+incompatible // indirect + github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -73,14 +73,14 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/opencontainers/image-spec v1.1.0-rc4 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/vbatts/tar-split v0.11.5 // indirect + github.com/vbatts/tar-split v0.11.6 // indirect github.com/vladimirvivien/gexe v0.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -91,7 +91,7 @@ require ( gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect - google.golang.org/protobuf v1.36.1 // indirect + google.golang.org/protobuf v1.36.3 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 8856567977..171568baa2 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/container-storage-interface/spec v1.11.0 h1:H/YKTOeUZwHtyPOr9raR+HgFmGluGCklulxDYxSdVNM= github.com/container-storage-interface/spec v1.11.0/go.mod h1:DtUvaQszPml1YJfIK7c00mlv6/g4wNMLanLgiUbKFRI= -github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= -github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= +github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8= +github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -16,10 +16,10 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM= github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= -github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= +github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= +github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= +github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= @@ -55,8 +55,8 @@ github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYu github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= -github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= +github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= +github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -112,8 +112,8 @@ github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -150,24 +150,26 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= -github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= +github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= +github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= github.com/vladimirvivien/gexe v0.2.0 h1:nbdAQ6vbZ+ZNsolCgSVb9Fno60kzSuvtzVh6Ytqi/xY= github.com/vladimirvivien/gexe v0.2.0/go.mod h1:LHQL00w/7gDUKIak24n801ABp8C+ni6eBht9vGVst8w= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= +go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= +go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= +go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= +go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= +go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= +go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -214,8 +216,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -228,8 +230,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= -google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From f25687d08414200763c6ca6241f4ead5e4213208 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Jan 2025 10:54:40 +0100 Subject: [PATCH 113/426] chore(deps): update module sigs.k8s.io/controller-tools/cmd to v0.17.1 (main) (#4285) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Marcell Sevcsik Co-authored-by: Andrii Soldatenko --- config/crd/bases/dynatrace.com_dynakubes.yaml | 2 +- config/crd/bases/dynatrace.com_edgeconnects.yaml | 2 +- .../default/templates/Common/crd/dynatrace-operator-crd.yaml | 4 ++-- hack/make/prerequisites.mk | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index d7937febd0..18800eeba0 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.0 + controller-gen.kubebuilder.io/version: v0.17.1 name: dynakubes.dynatrace.com spec: group: dynatrace.com diff --git a/config/crd/bases/dynatrace.com_edgeconnects.yaml b/config/crd/bases/dynatrace.com_edgeconnects.yaml index 14e4f7d8b8..b531a0abb3 100644 --- a/config/crd/bases/dynatrace.com_edgeconnects.yaml +++ b/config/crd/bases/dynatrace.com_edgeconnects.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.0 + controller-gen.kubebuilder.io/version: v0.17.1 name: edgeconnects.dynatrace.com spec: group: dynatrace.com diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 5cd3dffb09..11250e0ea1 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.0 + controller-gen.kubebuilder.io/version: v0.17.1 name: dynakubes.dynatrace.com spec: conversion: @@ -7531,7 +7531,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.0 + controller-gen.kubebuilder.io/version: v0.17.1 name: edgeconnects.dynatrace.com spec: conversion: diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index ed39f54d16..c26c3f260b 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -1,7 +1,7 @@ #renovate depName=sigs.k8s.io/kustomize/kustomize/v5 kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd -controller_gen_version=v0.17.0 +controller_gen_version=v0.17.1 # renovate depName=github.com/golangci/golangci-lint golang_ci_cmd_version=v1.63.4 # renovate depName=github.com/daixiang0/gci From b74e6e4bd4bf601f4a79e22d81a8de7bdfd3255c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:15:39 +0000 Subject: [PATCH 114/426] fix(deps): update kubernetes packages to v0.32.1 (main) (#4298) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 4c2d3330bf..4012013422 100644 --- a/go.mod +++ b/go.mod @@ -28,11 +28,11 @@ require ( gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.2 istio.io/client-go v1.24.2 - k8s.io/api v0.32.0 - k8s.io/apiextensions-apiserver v0.32.0 - k8s.io/apimachinery v0.32.0 - k8s.io/client-go v0.32.0 - k8s.io/mount-utils v0.32.0 + k8s.io/api v0.32.1 + k8s.io/apiextensions-apiserver v0.32.1 + k8s.io/apimachinery v0.32.1 + k8s.io/client-go v0.32.1 + k8s.io/mount-utils v0.32.1 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.19.4 sigs.k8s.io/e2e-framework v0.3.0 diff --git a/go.sum b/go.sum index 171568baa2..8d54342d1a 100644 --- a/go.sum +++ b/go.sum @@ -248,20 +248,20 @@ istio.io/api v1.24.2 h1:jYjcN6Iq0RPtQj/3KMFsybxmfqmjGN/dxhL7FGJEdIM= istio.io/api v1.24.2/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= istio.io/client-go v1.24.2 h1:JTTfBV6dv+AAW+AfccyrdX4T1f9CpsXd1Yzo1s/IYAI= istio.io/client-go v1.24.2/go.mod h1:dgZ9EmJzh1EECzf6nQhwNL4R6RvlyeH/RXeNeNp/MRg= -k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= -k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= -k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0= -k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw= -k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg= -k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= -k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= +k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc= +k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k= +k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw= +k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto= +k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs= +k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU= +k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/mount-utils v0.32.0 h1:KOQAhPzJICATXnc6XCkWoexKbkOexRnMCUW8APFfwg4= -k8s.io/mount-utils v0.32.0/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= +k8s.io/mount-utils v0.32.1 h1:RJOD6xXzEJT/OOJoG1KstfVa8ZXJJPlHb+t2MoulPHM= +k8s.io/mount-utils v0.32.1/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.19.4 h1:SUmheabttt0nx8uJtoII4oIP27BVVvAKFvdvGFwV/Qo= From 8057a867079f6bc3128a0d419c9ccfc453839246 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Jan 2025 17:49:46 +0000 Subject: [PATCH 115/426] fix(deps): update module sigs.k8s.io/controller-runtime to v0.20.0 (main) (#4301) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 3 ++- go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4012013422..747ca8a909 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( k8s.io/client-go v0.32.1 k8s.io/mount-utils v0.32.1 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - sigs.k8s.io/controller-runtime v0.19.4 + sigs.k8s.io/controller-runtime v0.20.0 sigs.k8s.io/e2e-framework v0.3.0 sigs.k8s.io/yaml v1.4.0 ) @@ -56,6 +56,7 @@ require ( github.com/go-openapi/swag v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect diff --git a/go.sum b/go.sum index 8d54342d1a..a5871682eb 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -264,8 +266,8 @@ k8s.io/mount-utils v0.32.1 h1:RJOD6xXzEJT/OOJoG1KstfVa8ZXJJPlHb+t2MoulPHM= k8s.io/mount-utils v0.32.1/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.19.4 h1:SUmheabttt0nx8uJtoII4oIP27BVVvAKFvdvGFwV/Qo= -sigs.k8s.io/controller-runtime v0.19.4/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= +sigs.k8s.io/controller-runtime v0.20.0 h1:jjkMo29xEXH+02Md9qaVXfEIaMESSpy3TBWPrsfQkQs= +sigs.k8s.io/controller-runtime v0.20.0/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= From c68866fbbcf45a838a61e30908e0847249c720fd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 01:35:47 +0000 Subject: [PATCH 116/426] chore(deps): update golangci/golangci-lint-action action to v6.2.0 (main) (#4302) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e2b2f7145c..fcd1f31902 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -94,7 +94,7 @@ jobs: run: | hack/build/ci/install-cgo-dependencies.sh - name: Run golangci-lint - uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 + uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6.2.0 with: # renovate depName=github.com/golangci/golangci-lint version: v1.63.4 From 3c782cdfb3eed27cfadb98a9a4ffae48ae33ba30 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 05:15:34 +0000 Subject: [PATCH 117/426] chore(deps): update golang docker tag to v1.23.5 (main) (#4303) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 474f4c3e17..11d061358d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # setup build image -FROM golang:1.23.4@sha256:c25964d301e6c50174d29deadbbaa5ea6443e94b61087b6d89e8f41ef4ebca35 AS operator-build +FROM golang:1.23.5@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 AS operator-build RUN --mount=type=cache,target=/var/cache/apt \ apt-get update && apt-get install -y libbtrfs-dev libdevmapper-dev From e69ee36d4d33f8222949adf0c7e024bb86506f7a Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:29:11 +0100 Subject: [PATCH 118/426] Migrate CSI to fs from db (#4292) Co-authored-by: Albian Krasniqi <62391739+waodim@users.noreply.github.com> --- .github/workflows/ci.yaml | 10 +- .github/workflows/release.yaml | 4 - Dockerfile | 16 +- cmd/csi/init/builder.go | 101 --- cmd/csi/init/cmd.go | 84 ++ cmd/csi/init/config.go | 7 - cmd/csi/init/manager.go | 30 - cmd/csi/provisioner/builder.go | 146 ---- cmd/csi/provisioner/builder_test.go | 82 -- cmd/csi/provisioner/cmd.go | 121 +++ cmd/csi/provisioner/command_test.go | 49 -- cmd/csi/provisioner/manager.go | 69 -- cmd/csi/provisioner/manager_test.go | 55 -- cmd/csi/server/builder.go | 149 ---- cmd/csi/server/builder_test.go | 84 -- cmd/csi/server/cmd.go | 113 +++ cmd/csi/server/command_test.go | 49 -- cmd/csi/server/manager.go | 46 - cmd/csi/server/manager_test.go | 27 - cmd/main.go | 24 +- .../templates/Common/csi/daemonset.yaml | 9 +- .../tests/Common/csi/daemonset_test.yaml | 11 +- config/helm/chart/default/values.yaml | 2 +- go.mod | 4 +- go.sum | 2 - hack/build/ci/install-cgo-dependencies.sh | 4 - hack/build/create_go_build_tags.sh | 9 +- pkg/api/v1beta3/dynakube/dynakube_props.go | 33 +- .../v1beta3/dynakube/dynakube_props_test.go | 69 -- pkg/controllers/csi/config.go | 1 + pkg/controllers/csi/driver/server.go | 127 ++- .../csi/driver/volumes/app/config.go | 2 +- .../csi/driver/volumes/app/publisher.go | 302 +++---- .../csi/driver/volumes/app/publisher_test.go | 459 +++------- .../csi/driver/volumes/bind_config.go | 50 -- .../csi/driver/volumes/bind_config_test.go | 94 -- .../csi/driver/volumes/host/config.go | 2 +- .../csi/driver/volumes/host/publisher.go | 113 +-- .../csi/driver/volumes/host/publisher_test.go | 177 +--- .../csi/driver/volumes/publisher.go | 2 - .../csi/driver/volumes/volume_config.go | 60 +- .../csi/driver/volumes/volume_config_test.go | 32 +- pkg/controllers/csi/gc/binaries.go | 165 ---- pkg/controllers/csi/gc/binaries_test.go | 171 ---- pkg/controllers/csi/gc/config.go | 38 - pkg/controllers/csi/gc/reconciler.go | 107 --- pkg/controllers/csi/gc/reconciler_test.go | 43 - pkg/controllers/csi/gc/unmounted.go | 97 -- pkg/controllers/csi/gc/unmounted_test.go | 184 ---- pkg/controllers/csi/metadata/correctness.go | 248 +++--- .../csi/metadata/correctness_test.go | 217 ++--- .../csi/metadata/deprecared_test.go | 76 ++ pkg/controllers/csi/metadata/deprecated.go | 35 + pkg/controllers/csi/metadata/fakes.go | 117 --- pkg/controllers/csi/metadata/metadata.go | 143 --- pkg/controllers/csi/metadata/metadata_test.go | 79 -- pkg/controllers/csi/metadata/path_resolver.go | 106 ++- .../csi/metadata/path_resolver_test.go | 27 - pkg/controllers/csi/metadata/sqlite.go | 814 ----------------- pkg/controllers/csi/metadata/sqlite_test.go | 645 -------------- .../csi/provisioner/cleanup/appmounts.go | 57 ++ .../csi/provisioner/cleanup/appmounts_test.go | 83 ++ .../csi/provisioner/cleanup/binaries.go | 117 +++ .../csi/provisioner/cleanup/binaries_test.go | 286 ++++++ .../csi/provisioner/cleanup/config.go | 9 + .../csi/provisioner/cleanup/hostmounts.go | 77 ++ .../provisioner/cleanup/hostmounts_test.go | 189 ++++ .../csi/provisioner/cleanup/run.go | 166 ++++ .../csi/provisioner/cleanup/run_test.go | 170 ++++ .../csi/provisioner/cleanup/ticker.go | 75 ++ .../csi/provisioner/cleanup/ticker_test.go | 49 ++ pkg/controllers/csi/provisioner/config.go | 5 - pkg/controllers/csi/provisioner/controller.go | 237 +---- .../csi/provisioner/controller_test.go | 825 +++++------------- pkg/controllers/csi/provisioner/events.go | 26 - pkg/controllers/csi/provisioner/install.go | 151 ++-- .../csi/provisioner/install_test.go | 350 +------- .../dynakube/dtpullsecret/generate.go | 2 +- .../dynakube/kspm/daemonset/reconciler.go | 2 +- .../logmonitoring/configsecret/reconciler.go | 2 +- .../configsecret/reconciler_test.go | 2 +- .../logmonitoring/daemonset/reconciler.go | 2 +- .../processmoduleconfigsecret/reconciler.go | 4 +- .../codemodule/installer/image/installer.go | 3 +- .../codemodule/installer/symlink/symlink.go | 49 +- .../codemodule/installer/url/installer.go | 2 +- .../codemodule/processmoduleconfig/update.go | 4 +- .../processmoduleconfig/update_test.go | 8 +- .../namespace/ingestendpoint/secret.go | 2 +- pkg/injection/startup/run.go | 2 +- pkg/util/testing/events.go | 38 - pkg/webhook/mutation/pod/oneagent/mutator.go | 2 +- 92 files changed, 2872 insertions(+), 6266 deletions(-) delete mode 100644 cmd/csi/init/builder.go create mode 100644 cmd/csi/init/cmd.go delete mode 100644 cmd/csi/init/config.go delete mode 100644 cmd/csi/init/manager.go delete mode 100644 cmd/csi/provisioner/builder.go delete mode 100644 cmd/csi/provisioner/builder_test.go create mode 100644 cmd/csi/provisioner/cmd.go delete mode 100644 cmd/csi/provisioner/command_test.go delete mode 100644 cmd/csi/provisioner/manager.go delete mode 100644 cmd/csi/provisioner/manager_test.go delete mode 100644 cmd/csi/server/builder.go delete mode 100644 cmd/csi/server/builder_test.go create mode 100644 cmd/csi/server/cmd.go delete mode 100644 cmd/csi/server/command_test.go delete mode 100644 cmd/csi/server/manager.go delete mode 100644 cmd/csi/server/manager_test.go delete mode 100755 hack/build/ci/install-cgo-dependencies.sh delete mode 100644 pkg/controllers/csi/driver/volumes/bind_config.go delete mode 100644 pkg/controllers/csi/driver/volumes/bind_config_test.go delete mode 100644 pkg/controllers/csi/gc/binaries.go delete mode 100644 pkg/controllers/csi/gc/binaries_test.go delete mode 100644 pkg/controllers/csi/gc/config.go delete mode 100644 pkg/controllers/csi/gc/reconciler.go delete mode 100644 pkg/controllers/csi/gc/reconciler_test.go delete mode 100644 pkg/controllers/csi/gc/unmounted.go delete mode 100644 pkg/controllers/csi/gc/unmounted_test.go create mode 100644 pkg/controllers/csi/metadata/deprecared_test.go create mode 100644 pkg/controllers/csi/metadata/deprecated.go delete mode 100644 pkg/controllers/csi/metadata/fakes.go delete mode 100644 pkg/controllers/csi/metadata/metadata.go delete mode 100644 pkg/controllers/csi/metadata/metadata_test.go delete mode 100644 pkg/controllers/csi/metadata/path_resolver_test.go delete mode 100644 pkg/controllers/csi/metadata/sqlite.go delete mode 100644 pkg/controllers/csi/metadata/sqlite_test.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/appmounts.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/appmounts_test.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/binaries.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/binaries_test.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/config.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/hostmounts.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/run.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/run_test.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/ticker.go create mode 100644 pkg/controllers/csi/provisioner/cleanup/ticker_test.go delete mode 100644 pkg/controllers/csi/provisioner/events.go delete mode 100644 pkg/util/testing/events.go diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fcd1f31902..55b9a0a603 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -57,11 +57,7 @@ jobs: uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: "${{ github.workspace }}/go.mod" - - name: Download dependencies - id: depdownload - run: | - hack/build/ci/install-cgo-dependencies.sh - - name: Run unit tests and integration tests + - name: Run Unit tests and Integration tests id: unittest run: | make go/test @@ -89,10 +85,6 @@ jobs: - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: "${{ github.workspace }}/go.mod" - - name: Download dependencies - id: depdownload - run: | - hack/build/ci/install-cgo-dependencies.sh - name: Run golangci-lint uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6.2.0 with: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1fbcff097b..8e9f9d058a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -288,10 +288,6 @@ jobs: uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: "${{ github.workspace }}/go.mod" - - name: Download dependencies - id: depdownload - run: | - hack/build/ci/install-cgo-dependencies.sh - name: Generate release notes shell: bash env: diff --git a/Dockerfile b/Dockerfile index 11d061358d..a3451127fa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,5 @@ # setup build image -FROM golang:1.23.5@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 AS operator-build - -RUN --mount=type=cache,target=/var/cache/apt \ - apt-get update && apt-get install -y libbtrfs-dev libdevmapper-dev +FROM --platform=$BUILDPLATFORM golang:1.23.5@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 AS operator-build WORKDIR /app @@ -14,12 +11,17 @@ RUN if [ "$DEBUG_TOOLS" = "true" ]; then \ COPY go.mod go.sum ./ RUN go mod download -x +COPY pkg ./pkg +COPY cmd ./cmd + ARG GO_LINKER_ARGS ARG GO_BUILD_TAGS +ARG TARGETARCH +ARG TARGETOS -COPY pkg ./pkg -COPY cmd ./cmd -RUN --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 CGO_CFLAGS="-O2 -Wno-return-local-addr" \ +RUN --mount=type=cache,target="/root/.cache/go-build" \ + --mount=type=cache,target="/go/pkg" \ + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ go build -tags "${GO_BUILD_TAGS}" -trimpath -ldflags="${GO_LINKER_ARGS}" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ diff --git a/cmd/csi/init/builder.go b/cmd/csi/init/builder.go deleted file mode 100644 index 934921a257..0000000000 --- a/cmd/csi/init/builder.go +++ /dev/null @@ -1,101 +0,0 @@ -package init - -import ( - "github.com/Dynatrace/dynatrace-operator/cmd/config" - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/Dynatrace/dynatrace-operator/pkg/logd" - "github.com/Dynatrace/dynatrace-operator/pkg/version" - "github.com/pkg/errors" - "github.com/spf13/afero" - "github.com/spf13/cobra" - "golang.org/x/sys/unix" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -const use = "csi-init" - -var nodeId, endpoint string - -type CommandBuilder struct { - configProvider config.Provider - namespace string -} - -func NewCsiInitCommandBuilder() CommandBuilder { - return CommandBuilder{} -} - -func (builder CommandBuilder) SetConfigProvider(provider config.Provider) CommandBuilder { - builder.configProvider = provider - - return builder -} - -func (builder CommandBuilder) SetNamespace(namespace string) CommandBuilder { - builder.namespace = namespace - - return builder -} - -func (builder CommandBuilder) Build() *cobra.Command { - cmd := &cobra.Command{ - Use: use, - RunE: builder.buildRun(), - } - - return cmd -} - -func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { - return func(cmd *cobra.Command, args []string) error { - unix.Umask(dtcsi.UnixUmask) - version.LogVersion() - logd.LogBaseLoggerSettings() - - kubeConfig, err := builder.configProvider.GetConfig() - if err != nil { - return err - } - - csiManager, err := createManager(builder.namespace, kubeConfig) - if err != nil { - log.Info("failed to create/configure kubernetes client, will only run non-network related corrections and checks", "err", err.Error()) - } - - err = createCsiDataPath(afero.NewOsFs()) - if err != nil { - return err - } - - signalHandler := ctrl.SetupSignalHandler() - - access, err := metadata.NewAccess(signalHandler, dtcsi.MetadataAccessPath) - if err != nil { - return err - } - - csiOptions := dtcsi.CSIOptions{ - NodeId: nodeId, - Endpoint: endpoint, - RootDir: dtcsi.DataPath, - } - - var apiReader client.Reader - if csiManager != nil { - apiReader = csiManager.GetAPIReader() - } - - err = metadata.NewCorrectnessChecker(apiReader, access, csiOptions).CorrectCSI(signalHandler) - if err != nil { - return err - } - - return nil - } -} - -func createCsiDataPath(fs afero.Fs) error { - return errors.WithStack(fs.MkdirAll(dtcsi.DataPath, 0770)) -} diff --git a/cmd/csi/init/cmd.go b/cmd/csi/init/cmd.go new file mode 100644 index 0000000000..04f8436b67 --- /dev/null +++ b/cmd/csi/init/cmd.go @@ -0,0 +1,84 @@ +package init + +import ( + "os" + + "github.com/Dynatrace/dynatrace-operator/cmd/config" + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" + dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + "github.com/Dynatrace/dynatrace-operator/pkg/version" + "github.com/pkg/errors" + "github.com/spf13/afero" + "github.com/spf13/cobra" + "golang.org/x/sys/unix" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +const use = "csi-init" + +var nodeId, endpoint string + +func New() *cobra.Command { + cmd := &cobra.Command{ + Use: use, + RunE: run(), + } + + return cmd +} + +func run() func(*cobra.Command, []string) error { + return func(cmd *cobra.Command, args []string) error { + unix.Umask(dtcsi.UnixUmask) + version.LogVersion() + logd.LogBaseLoggerSettings() + + err := createCSIDataPath(afero.NewOsFs()) + if err != nil { + return err + } + + signalHandler := ctrl.SetupSignalHandler() + + csiOptions := dtcsi.CSIOptions{ + NodeId: nodeId, + Endpoint: endpoint, + RootDir: dtcsi.DataPath, + } + + managerOptions := ctrl.Options{ + Cache: cache.Options{ + DefaultNamespaces: map[string]cache.Config{ + env.DefaultNamespace(): {}, + }, + }, + Scheme: scheme.Scheme, + } + + kubeconfig, err := config.NewKubeConfigProvider().GetConfig() + if err != nil { + return errors.WithStack(err) + } + + mgr, err := manager.New(kubeconfig, managerOptions) + if err != nil { + return errors.WithStack(err) + } + + err = metadata.NewCorrectnessChecker(mgr.GetAPIReader(), csiOptions).CorrectCSI(signalHandler) + if err != nil { + return err + } + + return nil + } +} + +func createCSIDataPath(fs afero.Fs) error { + return errors.WithStack(fs.MkdirAll(dtcsi.DataPath, os.ModePerm)) +} diff --git a/cmd/csi/init/config.go b/cmd/csi/init/config.go deleted file mode 100644 index 3ef0e4f665..0000000000 --- a/cmd/csi/init/config.go +++ /dev/null @@ -1,7 +0,0 @@ -package init - -import ( - "github.com/Dynatrace/dynatrace-operator/pkg/logd" -) - -var log = logd.Get().WithName("csi-init") diff --git a/cmd/csi/init/manager.go b/cmd/csi/init/manager.go deleted file mode 100644 index f70d8bca2f..0000000000 --- a/cmd/csi/init/manager.go +++ /dev/null @@ -1,30 +0,0 @@ -package init - -import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/pkg/errors" - "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/cache" - "sigs.k8s.io/controller-runtime/pkg/manager" -) - -func createManager(namespace string, config *rest.Config) (manager.Manager, error) { - mgr, err := manager.New(config, createManagerOptions(namespace)) - if err != nil { - return nil, errors.WithStack(err) - } - - return mgr, nil -} - -func createManagerOptions(namespace string) ctrl.Options { - return ctrl.Options{ - Cache: cache.Options{ - DefaultNamespaces: map[string]cache.Config{ - namespace: {}, - }, - }, - Scheme: scheme.Scheme, - } -} diff --git a/cmd/csi/provisioner/builder.go b/cmd/csi/provisioner/builder.go deleted file mode 100644 index 9be1f83bfe..0000000000 --- a/cmd/csi/provisioner/builder.go +++ /dev/null @@ -1,146 +0,0 @@ -package provisioner - -import ( - "github.com/Dynatrace/dynatrace-operator/cmd/config" - cmdManager "github.com/Dynatrace/dynatrace-operator/cmd/manager" - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - csiprovisioner "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/provisioner" - "github.com/Dynatrace/dynatrace-operator/pkg/logd" - "github.com/Dynatrace/dynatrace-operator/pkg/version" - "github.com/pkg/errors" - "github.com/spf13/afero" - "github.com/spf13/cobra" - "golang.org/x/sys/unix" - ctrl "sigs.k8s.io/controller-runtime" -) - -const use = "csi-provisioner" - -var probeAddress string - -type CommandBuilder struct { - configProvider config.Provider - managerProvider cmdManager.Provider - filesystem afero.Fs - csiOptions *dtcsi.CSIOptions - namespace string -} - -func NewCsiProvisionerCommandBuilder() CommandBuilder { - return CommandBuilder{} -} - -func (builder CommandBuilder) SetConfigProvider(provider config.Provider) CommandBuilder { - builder.configProvider = provider - - return builder -} - -func (builder CommandBuilder) setManagerProvider(provider cmdManager.Provider) CommandBuilder { - builder.managerProvider = provider - - return builder -} - -func (builder CommandBuilder) SetNamespace(namespace string) CommandBuilder { - builder.namespace = namespace - - return builder -} - -func (builder CommandBuilder) setCsiOptions(csiOptions dtcsi.CSIOptions) CommandBuilder { - builder.csiOptions = &csiOptions - - return builder -} - -func (builder CommandBuilder) setFilesystem(filesystem afero.Fs) CommandBuilder { - builder.filesystem = filesystem - - return builder -} - -func (builder CommandBuilder) getCsiOptions() dtcsi.CSIOptions { - if builder.csiOptions == nil { - builder.csiOptions = &dtcsi.CSIOptions{ - RootDir: dtcsi.DataPath, - } - } - - return *builder.csiOptions -} - -func (builder CommandBuilder) getManagerProvider() cmdManager.Provider { - if builder.managerProvider == nil { - builder.managerProvider = newCsiDriverManagerProvider(probeAddress) - } - - return builder.managerProvider -} - -func (builder CommandBuilder) getFilesystem() afero.Fs { - if builder.filesystem == nil { - builder.filesystem = afero.NewOsFs() - } - - return builder.filesystem -} - -func (builder CommandBuilder) Build() *cobra.Command { - cmd := &cobra.Command{ - Use: use, - RunE: builder.buildRun(), - } - - addFlags(cmd) - - return cmd -} - -func addFlags(cmd *cobra.Command) { - cmd.PersistentFlags().StringVar(&probeAddress, "health-probe-bind-address", ":10090", "The address the probe endpoint binds to.") -} - -func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { - return func(cmd *cobra.Command, args []string) error { - unix.Umask(dtcsi.UnixUmask) - version.LogVersion() - logd.LogBaseLoggerSettings() - - kubeConfig, err := builder.configProvider.GetConfig() - if err != nil { - return err - } - - csiManager, err := builder.getManagerProvider().CreateManager(builder.namespace, kubeConfig) - if err != nil { - return err - } - - signalHandler := ctrl.SetupSignalHandler() - - err = createCsiDataPath(builder.getFilesystem()) - if err != nil { - return err - } - - access, err := metadata.NewAccess(signalHandler, dtcsi.MetadataAccessPath) - if err != nil { - return err - } - - err = csiprovisioner.NewOneAgentProvisioner(csiManager, builder.getCsiOptions(), access).SetupWithManager(csiManager) - if err != nil { - return err - } - - err = csiManager.Start(signalHandler) - - return errors.WithStack(err) - } -} - -func createCsiDataPath(fs afero.Fs) error { - return errors.WithStack(fs.MkdirAll(dtcsi.DataPath, 0770)) -} diff --git a/cmd/csi/provisioner/builder_test.go b/cmd/csi/provisioner/builder_test.go deleted file mode 100644 index 33be4c7374..0000000000 --- a/cmd/csi/provisioner/builder_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package provisioner - -import ( - "io/fs" - "testing" - - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - configmock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/config" - managermock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/manager" - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestCsiCommandBuilder(t *testing.T) { - t.Run("build command", func(t *testing.T) { - builder := NewCsiProvisionerCommandBuilder() - csiCommand := builder.Build() - - assert.NotNil(t, csiCommand) - assert.Equal(t, use, csiCommand.Use) - assert.NotNil(t, csiCommand.RunE) - }) - t.Run("set config provider", func(t *testing.T) { - builder := NewCsiProvisionerCommandBuilder() - - assert.NotNil(t, builder) - - expectedProvider := &configmock.Provider{} - builder = builder.SetConfigProvider(expectedProvider) - - assert.Equal(t, expectedProvider, builder.configProvider) - }) - t.Run("set manager provider", func(t *testing.T) { - expectedProvider := managermock.NewProvider(t) - builder := NewCsiProvisionerCommandBuilder().setManagerProvider(expectedProvider) - - assert.Equal(t, expectedProvider, builder.managerProvider) - }) - t.Run("set namespace", func(t *testing.T) { - builder := NewCsiProvisionerCommandBuilder().SetNamespace("namespace") - - assert.Equal(t, "namespace", builder.namespace) - }) - t.Run("set filesystem", func(t *testing.T) { - expectedFs := afero.NewMemMapFs() - builder := NewCsiProvisionerCommandBuilder() - - assert.Equal(t, afero.NewOsFs(), builder.getFilesystem()) - - builder = builder.setFilesystem(expectedFs) - - assert.Equal(t, expectedFs, builder.getFilesystem()) - }) - t.Run("set csi options", func(t *testing.T) { - expectedOptions := dtcsi.CSIOptions{ - RootDir: dtcsi.DataPath, - } - builder := NewCsiProvisionerCommandBuilder(). - setCsiOptions(expectedOptions) - - assert.Equal(t, expectedOptions, builder.getCsiOptions()) - }) -} - -func TestCreateCsiRootPath(t *testing.T) { - memFs := afero.NewMemMapFs() - err := createCsiDataPath(memFs) - - require.NoError(t, err) - - exists, err := afero.Exists(memFs, dtcsi.DataPath) - - assert.True(t, exists) - require.NoError(t, err) - - stat, err := memFs.Stat(dtcsi.DataPath) - - require.NoError(t, err) - assert.Equal(t, fs.FileMode(0770), stat.Mode()&fs.FileMode(0770)) - assert.True(t, stat.IsDir()) -} diff --git a/cmd/csi/provisioner/cmd.go b/cmd/csi/provisioner/cmd.go new file mode 100644 index 0000000000..ab9cad5602 --- /dev/null +++ b/cmd/csi/provisioner/cmd.go @@ -0,0 +1,121 @@ +package provisioner + +import ( + "os" + + "github.com/Dynatrace/dynatrace-operator/cmd/config" + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" + dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" + csiprovisioner "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/provisioner" + "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + "github.com/Dynatrace/dynatrace-operator/pkg/version" + "github.com/pkg/errors" + "github.com/spf13/afero" + "github.com/spf13/cobra" + "golang.org/x/sys/unix" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" +) + +const ( + use = "csi-provisioner" + + metricsBindAddress = ":8090" + defaultProbeAddress = ":8091" + livenessEndpointName = "/livez" + livezEndpointName = "livez" +) + +var probeAddress string + +func New() *cobra.Command { + cmd := &cobra.Command{ + Use: use, + RunE: run(), + } + + addFlags(cmd) + + return cmd +} + +func addFlags(cmd *cobra.Command) { + cmd.PersistentFlags().StringVar(&probeAddress, "health-probe-bind-address", ":10090", "The address the probe endpoint binds to.") +} + +func run() func(*cobra.Command, []string) error { + return func(cmd *cobra.Command, args []string) error { + unix.Umask(dtcsi.UnixUmask) + version.LogVersion() + logd.LogBaseLoggerSettings() + + kubeConfig, err := config.NewKubeConfigProvider().GetConfig() + if err != nil { + return err + } + + csiManager, err := createManager(kubeConfig, env.DefaultNamespace()) + if err != nil { + return err + } + + signalHandler := ctrl.SetupSignalHandler() + + err = createCSIDataPath(afero.NewOsFs()) + if err != nil { + return err + } + + err = csiprovisioner.NewOneAgentProvisioner(csiManager, createCsiOptions()).SetupWithManager(csiManager) + if err != nil { + return err + } + + err = csiManager.Start(signalHandler) + + return errors.WithStack(err) + } +} + +func createCSIDataPath(fs afero.Fs) error { + return errors.WithStack(fs.MkdirAll(dtcsi.DataPath, os.ModePerm)) +} + +func createManager(config *rest.Config, namespace string) (manager.Manager, error) { + options := ctrl.Options{ + Cache: cache.Options{ + DefaultNamespaces: map[string]cache.Config{ + namespace: {}, + }, + }, + Scheme: scheme.Scheme, + Metrics: server.Options{ + BindAddress: metricsBindAddress, + }, + HealthProbeBindAddress: probeAddress, + LivenessEndpointName: livenessEndpointName, + } + + mgr, err := manager.New(config, options) + if err != nil { + return nil, errors.WithStack(err) + } + + err = mgr.AddHealthzCheck(livezEndpointName, healthz.Ping) + if err != nil { + return nil, errors.WithStack(err) + } + + return mgr, nil +} + +func createCsiOptions() dtcsi.CSIOptions { + return dtcsi.CSIOptions{ + RootDir: dtcsi.DataPath, + } +} diff --git a/cmd/csi/provisioner/command_test.go b/cmd/csi/provisioner/command_test.go deleted file mode 100644 index d91b9e2d2d..0000000000 --- a/cmd/csi/provisioner/command_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package provisioner - -import ( - "testing" - - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - "github.com/Dynatrace/dynatrace-operator/pkg/logd" - configmock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/config" - providermock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/manager" - managermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "k8s.io/client-go/rest" -) - -func TestCsiCommand(t *testing.T) { - configProvider := configmock.NewProvider(t) - configProvider.On("GetConfig").Return(&rest.Config{}, nil) - - cmdMgr := managermock.NewManager(t) - - managerProvider := providermock.NewProvider(t) - managerProvider.On("CreateManager", mock.Anything, mock.Anything).Return(cmdMgr, nil) - - memFs := afero.NewMemMapFs() - builder := NewCsiProvisionerCommandBuilder(). - SetConfigProvider(configProvider). - setManagerProvider(managerProvider). - SetNamespace("test-namespace"). - setFilesystem(memFs) - command := builder.Build() - commandFn := builder.buildRun() - - err := commandFn(command, make([]string, 0)) - - // sqlite library does not use afero fs, so it throws an error because path does not exist - require.Error(t, err) - configProvider.AssertCalled(t, "GetConfig") - managerProvider.AssertCalled(t, "CreateManager", "test-namespace", &rest.Config{}) - - exists, err := afero.Exists(memFs, dtcsi.DataPath) - assert.True(t, exists) - require.NoError(t, err) - - // Logging a newline because otherwise `go test` doesn't recognize the result - logd.Get().WithName("csi command").Info("") -} diff --git a/cmd/csi/provisioner/manager.go b/cmd/csi/provisioner/manager.go deleted file mode 100644 index 4017b932ed..0000000000 --- a/cmd/csi/provisioner/manager.go +++ /dev/null @@ -1,69 +0,0 @@ -package provisioner - -import ( - cmdManager "github.com/Dynatrace/dynatrace-operator/cmd/manager" - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/pkg/errors" - "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/cache" - "sigs.k8s.io/controller-runtime/pkg/healthz" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/metrics/server" -) - -const ( - metricsBindAddress = ":8090" - defaultProbeAddress = ":8091" - livenessEndpointName = "/livez" - livezEndpointName = "livez" -) - -type csiDriverManagerProvider struct { - probeAddress string -} - -func newCsiDriverManagerProvider(probeAddress string) cmdManager.Provider { - return csiDriverManagerProvider{ - probeAddress: probeAddress, - } -} - -func (provider csiDriverManagerProvider) CreateManager(namespace string, config *rest.Config) (manager.Manager, error) { - mgr, err := manager.New(config, provider.createOptions(namespace)) - if err != nil { - return nil, errors.WithStack(err) - } - - err = provider.addHealthzCheck(mgr) - if err != nil { - return nil, err - } - - return mgr, nil -} - -func (provider csiDriverManagerProvider) addHealthzCheck(mgr manager.Manager) error { - err := mgr.AddHealthzCheck(livezEndpointName, healthz.Ping) - if err != nil { - return errors.WithStack(err) - } - - return nil -} - -func (provider csiDriverManagerProvider) createOptions(namespace string) ctrl.Options { - return ctrl.Options{ - Cache: cache.Options{ - DefaultNamespaces: map[string]cache.Config{ - namespace: {}, - }, - }, - Scheme: scheme.Scheme, - Metrics: server.Options{ - BindAddress: metricsBindAddress, - }, - HealthProbeBindAddress: provider.probeAddress, - LivenessEndpointName: livenessEndpointName, - } -} diff --git a/cmd/csi/provisioner/manager_test.go b/cmd/csi/provisioner/manager_test.go deleted file mode 100644 index 38152cfb04..0000000000 --- a/cmd/csi/provisioner/manager_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package provisioner - -import ( - "testing" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - managermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" -) - -func TestCsiDriverManagerProvider(t *testing.T) { - t.Run("is instantiable", func(t *testing.T) { - csiManagerProvider := newCsiDriverManagerProvider(defaultProbeAddress) - assert.NotNil(t, csiManagerProvider) - - csiManagerProviderImpl := csiManagerProvider.(csiDriverManagerProvider) - assert.Equal(t, defaultProbeAddress, csiManagerProviderImpl.probeAddress) - }) - t.Run("creates options", func(t *testing.T) { - csiManagerProvider := csiDriverManagerProvider{} - - options := csiManagerProvider.createOptions("namespace") - - assert.NotNil(t, options) - assert.Contains(t, options.Cache.DefaultNamespaces, "namespace") - assert.Equal(t, scheme.Scheme, options.Scheme) - assert.Equal(t, metricsBindAddress, options.Metrics.BindAddress) - assert.Equal(t, "", options.HealthProbeBindAddress) - assert.Equal(t, livenessEndpointName, options.LivenessEndpointName) - }) - t.Run("adds healthz check endpoint", func(t *testing.T) { - const addHealthzCheck = "AddHealthzCheck" - - operatorMgrProvider := csiDriverManagerProvider{} - mockMgr := managermock.NewManager(t) - mockMgr.On(addHealthzCheck, livezEndpointName, mock.AnythingOfType("healthz.Checker")).Return(nil) - - err := operatorMgrProvider.addHealthzCheck(mockMgr) - - require.NoError(t, err) - mockMgr.AssertCalled(t, addHealthzCheck, livezEndpointName, mock.AnythingOfType("healthz.Checker")) - - expectedError := errors.New("healthz error") - mockMgr = managermock.NewManager(t) - mockMgr.On(addHealthzCheck, mock.Anything, mock.Anything).Return(expectedError) - - err = operatorMgrProvider.addHealthzCheck(mockMgr) - - require.EqualError(t, err, expectedError.Error()) - mockMgr.AssertCalled(t, addHealthzCheck, mock.Anything, mock.Anything) - }) -} diff --git a/cmd/csi/server/builder.go b/cmd/csi/server/builder.go deleted file mode 100644 index 524bb5436a..0000000000 --- a/cmd/csi/server/builder.go +++ /dev/null @@ -1,149 +0,0 @@ -package server - -import ( - "github.com/Dynatrace/dynatrace-operator/cmd/config" - cmdManager "github.com/Dynatrace/dynatrace-operator/cmd/manager" - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - csidriver "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/Dynatrace/dynatrace-operator/pkg/logd" - "github.com/Dynatrace/dynatrace-operator/pkg/version" - "github.com/pkg/errors" - "github.com/spf13/afero" - "github.com/spf13/cobra" - "golang.org/x/sys/unix" - ctrl "sigs.k8s.io/controller-runtime" -) - -const use = "csi-server" - -var nodeId, endpoint string - -type CommandBuilder struct { - configProvider config.Provider - managerProvider cmdManager.Provider - filesystem afero.Fs - csiOptions *dtcsi.CSIOptions - namespace string -} - -func NewCsiServerCommandBuilder() CommandBuilder { - return CommandBuilder{} -} - -func (builder CommandBuilder) SetConfigProvider(provider config.Provider) CommandBuilder { - builder.configProvider = provider - - return builder -} - -func (builder CommandBuilder) setManagerProvider(provider cmdManager.Provider) CommandBuilder { - builder.managerProvider = provider - - return builder -} - -func (builder CommandBuilder) SetNamespace(namespace string) CommandBuilder { - builder.namespace = namespace - - return builder -} - -func (builder CommandBuilder) setCsiOptions(csiOptions dtcsi.CSIOptions) CommandBuilder { - builder.csiOptions = &csiOptions - - return builder -} - -func (builder CommandBuilder) setFilesystem(filesystem afero.Fs) CommandBuilder { - builder.filesystem = filesystem - - return builder -} - -func (builder CommandBuilder) getCsiOptions() dtcsi.CSIOptions { - if builder.csiOptions == nil { - builder.csiOptions = &dtcsi.CSIOptions{ - NodeId: nodeId, - Endpoint: endpoint, - RootDir: dtcsi.DataPath, - } - } - - return *builder.csiOptions -} - -func (builder CommandBuilder) getManagerProvider() cmdManager.Provider { - if builder.managerProvider == nil { - builder.managerProvider = newCsiDriverManagerProvider() - } - - return builder.managerProvider -} - -func (builder CommandBuilder) getFilesystem() afero.Fs { - if builder.filesystem == nil { - builder.filesystem = afero.NewOsFs() - } - - return builder.filesystem -} - -func (builder CommandBuilder) Build() *cobra.Command { - cmd := &cobra.Command{ - Use: use, - RunE: builder.buildRun(), - } - - addFlags(cmd) - - return cmd -} - -func addFlags(cmd *cobra.Command) { - cmd.PersistentFlags().StringVar(&nodeId, "node-id", "", "node id") - cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "unix:/tmp/csi.sock", "CSI endpoint") -} - -func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { - return func(cmd *cobra.Command, args []string) error { - unix.Umask(dtcsi.UnixUmask) - version.LogVersion() - logd.LogBaseLoggerSettings() - - kubeConfig, err := builder.configProvider.GetConfig() - if err != nil { - return err - } - - csiManager, err := builder.getManagerProvider().CreateManager(builder.namespace, kubeConfig) - if err != nil { - return err - } - - signalHandler := ctrl.SetupSignalHandler() - - err = createCsiDataPath(builder.getFilesystem()) - if err != nil { - return err - } - - access, err := metadata.NewAccess(signalHandler, dtcsi.MetadataAccessPath) - if err != nil { - return err - } - - err = csidriver.NewServer(builder.getCsiOptions(), access).SetupWithManager(csiManager) - if err != nil { - return err - } - - err = csiManager.Start(signalHandler) - - return errors.WithStack(err) - } -} - -func createCsiDataPath(fs afero.Fs) error { - return errors.WithStack(fs.MkdirAll(dtcsi.DataPath, 0770)) -} diff --git a/cmd/csi/server/builder_test.go b/cmd/csi/server/builder_test.go deleted file mode 100644 index e2a263d4ce..0000000000 --- a/cmd/csi/server/builder_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package server - -import ( - "io/fs" - "testing" - - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - configmock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/config" - providermock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/manager" - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestCsiCommandBuilder(t *testing.T) { - t.Run("build command", func(t *testing.T) { - builder := NewCsiServerCommandBuilder() - csiCommand := builder.Build() - - assert.NotNil(t, csiCommand) - assert.Equal(t, use, csiCommand.Use) - assert.NotNil(t, csiCommand.RunE) - }) - t.Run("set config provider", func(t *testing.T) { - builder := NewCsiServerCommandBuilder() - - assert.NotNil(t, builder) - - expectedProvider := &configmock.Provider{} - builder = builder.SetConfigProvider(expectedProvider) - - assert.Equal(t, expectedProvider, builder.configProvider) - }) - t.Run("set manager provider", func(t *testing.T) { - expectedProvider := providermock.NewProvider(t) - builder := NewCsiServerCommandBuilder().setManagerProvider(expectedProvider) - - assert.Equal(t, expectedProvider, builder.managerProvider) - }) - t.Run("set namespace", func(t *testing.T) { - builder := NewCsiServerCommandBuilder().SetNamespace("namespace") - - assert.Equal(t, "namespace", builder.namespace) - }) - t.Run("set filesystem", func(t *testing.T) { - expectedFs := afero.NewMemMapFs() - builder := NewCsiServerCommandBuilder() - - assert.Equal(t, afero.NewOsFs(), builder.getFilesystem()) - - builder = builder.setFilesystem(expectedFs) - - assert.Equal(t, expectedFs, builder.getFilesystem()) - }) - t.Run("set csi options", func(t *testing.T) { - expectedOptions := dtcsi.CSIOptions{ - NodeId: "test-node-id", - Endpoint: "test-endpoint", - RootDir: dtcsi.DataPath, - } - builder := NewCsiServerCommandBuilder(). - setCsiOptions(expectedOptions) - - assert.Equal(t, expectedOptions, builder.getCsiOptions()) - }) -} - -func TestCreateCsiRootPath(t *testing.T) { - memFs := afero.NewMemMapFs() - err := createCsiDataPath(memFs) - - require.NoError(t, err) - - exists, err := afero.Exists(memFs, dtcsi.DataPath) - - assert.True(t, exists) - require.NoError(t, err) - - stat, err := memFs.Stat(dtcsi.DataPath) - - require.NoError(t, err) - assert.Equal(t, fs.FileMode(0770), stat.Mode()&fs.FileMode(0770)) - assert.True(t, stat.IsDir()) -} diff --git a/cmd/csi/server/cmd.go b/cmd/csi/server/cmd.go new file mode 100644 index 0000000000..5ac83bedf5 --- /dev/null +++ b/cmd/csi/server/cmd.go @@ -0,0 +1,113 @@ +package server + +import ( + "os" + + "github.com/Dynatrace/dynatrace-operator/cmd/config" + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" + dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" + csidriver "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver" + "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + "github.com/Dynatrace/dynatrace-operator/pkg/version" + "github.com/pkg/errors" + "github.com/spf13/afero" + "github.com/spf13/cobra" + "golang.org/x/sys/unix" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" +) + +const ( + use = "csi-server" + + metricsBindAddress = ":8080" +) + +var nodeId, endpoint string + +func New() *cobra.Command { + cmd := &cobra.Command{ + Use: use, + RunE: run(), + } + + addFlags(cmd) + + return cmd +} + +func addFlags(cmd *cobra.Command) { + cmd.PersistentFlags().StringVar(&nodeId, "node-id", "", "node id") + cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "unix:///tmp/csi.sock", "CSI endpoint") +} + +func run() func(*cobra.Command, []string) error { + return func(cmd *cobra.Command, args []string) error { + unix.Umask(dtcsi.UnixUmask) + version.LogVersion() + logd.LogBaseLoggerSettings() + + kubeConfig, err := config.NewKubeConfigProvider().GetConfig() + if err != nil { + return err + } + + csiManager, err := createManager(kubeConfig, env.DefaultNamespace()) + if err != nil { + return err + } + + signalHandler := ctrl.SetupSignalHandler() + + err = createCSIDataPath(afero.NewOsFs()) + if err != nil { + return err + } + + err = csidriver.NewServer(createCsiOptions()).SetupWithManager(csiManager) + if err != nil { + return err + } + + err = csiManager.Start(signalHandler) + + return errors.WithStack(err) + } +} + +func createCSIDataPath(fs afero.Fs) error { + return errors.WithStack(fs.MkdirAll(dtcsi.DataPath, os.ModePerm)) +} + +func createManager(config *rest.Config, namespace string) (manager.Manager, error) { + options := ctrl.Options{ + Cache: cache.Options{ + DefaultNamespaces: map[string]cache.Config{ + namespace: {}, + }, + }, + Metrics: server.Options{ + BindAddress: metricsBindAddress, + }, + Scheme: scheme.Scheme, + } + + mgr, err := manager.New(config, options) + if err != nil { + return nil, errors.WithStack(err) + } + + return mgr, nil +} + +func createCsiOptions() dtcsi.CSIOptions { + return dtcsi.CSIOptions{ + NodeId: nodeId, + Endpoint: endpoint, + RootDir: dtcsi.DataPath, + } +} diff --git a/cmd/csi/server/command_test.go b/cmd/csi/server/command_test.go deleted file mode 100644 index 6f932b45a3..0000000000 --- a/cmd/csi/server/command_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package server - -import ( - "testing" - - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - "github.com/Dynatrace/dynatrace-operator/pkg/logd" - configmock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/config" - providermock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/manager" - managermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "k8s.io/client-go/rest" -) - -func TestCsiCommand(t *testing.T) { - configProvider := &configmock.Provider{} - configProvider.On("GetConfig").Return(&rest.Config{}, nil) - - cmdMgr := managermock.NewManager(t) - - managerProvider := providermock.NewProvider(t) - managerProvider.On("CreateManager", mock.Anything, mock.Anything).Return(cmdMgr, nil) - - memFs := afero.NewMemMapFs() - builder := NewCsiServerCommandBuilder(). - SetConfigProvider(configProvider). - setManagerProvider(managerProvider). - SetNamespace("test-namespace"). - setFilesystem(memFs) - command := builder.Build() - commandFn := builder.buildRun() - - err := commandFn(command, make([]string, 0)) - - // sqlite library does not use afero fs, so it throws an error because path does not exist - require.Error(t, err) - configProvider.AssertCalled(t, "GetConfig") - managerProvider.AssertCalled(t, "CreateManager", "test-namespace", &rest.Config{}) - - exists, err := afero.Exists(memFs, dtcsi.DataPath) - assert.True(t, exists) - require.NoError(t, err) - - // Logging a newline because otherwise `go test` doesn't recognize the result - logd.Get().WithName("csi command").Info("") -} diff --git a/cmd/csi/server/manager.go b/cmd/csi/server/manager.go deleted file mode 100644 index 751db85d9f..0000000000 --- a/cmd/csi/server/manager.go +++ /dev/null @@ -1,46 +0,0 @@ -package server - -import ( - cmdManager "github.com/Dynatrace/dynatrace-operator/cmd/manager" - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/pkg/errors" - "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/cache" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/metrics/server" -) - -const ( - metricsBindAddress = ":8080" -) - -type csiDriverManagerProvider struct{} - -func newCsiDriverManagerProvider() cmdManager.Provider { - return csiDriverManagerProvider{} -} - -func (provider csiDriverManagerProvider) CreateManager(namespace string, config *rest.Config) (manager.Manager, error) { - mgr, err := manager.New(config, provider.createOptions(namespace)) - if err != nil { - return nil, errors.WithStack(err) - } - - return mgr, nil -} -func (provider csiDriverManagerProvider) createOptions(namespace string) ctrl.Options { - options := ctrl.Options{ - Cache: cache.Options{ - DefaultNamespaces: map[string]cache.Config{ - namespace: {}, - }, - }, - Metrics: server.Options{ - BindAddress: metricsBindAddress, - }, - Scheme: scheme.Scheme, - } - - return options -} diff --git a/cmd/csi/server/manager_test.go b/cmd/csi/server/manager_test.go deleted file mode 100644 index 0f20757c67..0000000000 --- a/cmd/csi/server/manager_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package server - -import ( - "testing" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/stretchr/testify/assert" -) - -func TestCsiDriverManagerProvider(t *testing.T) { - t.Run("is instantiable", func(t *testing.T) { - csiManagerProvider := newCsiDriverManagerProvider() - assert.NotNil(t, csiManagerProvider) - }) - t.Run("creates options", func(t *testing.T) { - csiManagerProvider := csiDriverManagerProvider{} - - options := csiManagerProvider.createOptions("namespace") - - assert.NotNil(t, options) - assert.Contains(t, options.Cache.DefaultNamespaces, "namespace") - assert.Equal(t, scheme.Scheme, options.Scheme) - assert.Equal(t, metricsBindAddress, options.Metrics.BindAddress) - - assert.Equal(t, "", options.HealthProbeBindAddress) - }) -} diff --git a/cmd/main.go b/cmd/main.go index bc5c6c3fed..08aaaa3010 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -61,24 +61,6 @@ func createOperatorCommandBuilder() operator.CommandBuilder { SetConfigProvider(cmdConfig.NewKubeConfigProvider()) } -func createCsiServerCommandBuilder() csiServer.CommandBuilder { - return csiServer.NewCsiServerCommandBuilder(). - SetNamespace(os.Getenv(env.PodNamespace)). - SetConfigProvider(cmdConfig.NewKubeConfigProvider()) -} - -func createCsiInitCommandBuilder() csiInit.CommandBuilder { - return csiInit.NewCsiInitCommandBuilder(). - SetNamespace(os.Getenv(env.PodNamespace)). - SetConfigProvider(cmdConfig.NewKubeConfigProvider()) -} - -func createCsiProvisionerCommandBuilder() csiProvisioner.CommandBuilder { - return csiProvisioner.NewCsiProvisionerCommandBuilder(). - SetNamespace(os.Getenv(env.PodNamespace)). - SetConfigProvider(cmdConfig.NewKubeConfigProvider()) -} - func createTroubleshootCommandBuilder() troubleshoot.CommandBuilder { return troubleshoot.NewTroubleshootCommandBuilder(). SetConfigProvider(cmdConfig.NewKubeConfigProvider()) @@ -105,13 +87,13 @@ func main() { cmd.AddCommand( createWebhookCommandBuilder().Build(), createOperatorCommandBuilder().Build(), - createCsiServerCommandBuilder().Build(), - createCsiProvisionerCommandBuilder().Build(), standalone.NewStandaloneCommand(), createTroubleshootCommandBuilder().Build(), createSupportArchiveCommandBuilder().Build(), createStartupProbe().Build(), - createCsiInitCommandBuilder().Build(), + csiInit.New(), + csiProvisioner.New(), + csiServer.New(), ) err := cmd.Execute() diff --git a/config/helm/chart/default/templates/Common/csi/daemonset.yaml b/config/helm/chart/default/templates/Common/csi/daemonset.yaml index c1e0cf69b7..7ec83f1f02 100644 --- a/config/helm/chart/default/templates/Common/csi/daemonset.yaml +++ b/config/helm/chart/default/templates/Common/csi/daemonset.yaml @@ -166,9 +166,9 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - {{- if .Values.csidriver.maxUnmountedVolumeAge }} - - name: MAX_UNMOUNTED_VOLUME_AGE - value: "{{ .Values.csidriver.maxUnmountedVolumeAge}}" + {{- if .Values.csidriver.cleanupPeriod }} + - name: CLEANUP_PERIOD + value: "{{ .Values.csidriver.cleanupPeriod}}" {{- end }} {{ include "dynatrace-operator.modules-json-env" . | nindent 10 }} {{- include "dynatrace-operator.startupProbe" . | nindent 8 }} @@ -201,6 +201,9 @@ spec: mountPropagation: Bidirectional - mountPath: /tmp name: tmp-dir + - mountPath: {{ include "dynatrace-operator.CSIMountPointDir" . }} + name: mountpoint-dir # needed for garbage-collection + readOnly: true # Used to make a gRPC request (GetPluginInfo()) to the driver to get driver name and driver contain # - Needs access to the csi socket, needs to read/write to it, needs root permissions to do so. diff --git a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml index 742c692b4f..35c0205547 100644 --- a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml @@ -42,17 +42,17 @@ tests: key: ToBeDeletedByClusterAutoscaler operator: Exists - - it: should set the env maxUnmountedVolumeAge + - it: should set the env cleanupPeriod set: platform: kubernetes csidriver.enabled: true - csidriver.maxUnmountedVolumeAge: "6" + csidriver.cleanupPeriod: "5m" asserts: - equal: path: spec.template.spec.containers[1].env[1] #provisioner value: - name: MAX_UNMOUNTED_VOLUME_AGE - value: "6" + name: CLEANUP_PERIOD + value: "5m" - it: should have nodeSelectors if set set: @@ -296,6 +296,9 @@ tests: name: data-dir - mountPath: "/tmp" name: tmp-dir + - mountPath: "/var/lib/kubelet/pods/" + name: mountpoint-dir + readOnly: true - args: - "--csi-address=/csi/csi.sock" - "--kubelet-registration-path=$(DRIVER_REG_SOCK_PATH)" diff --git a/config/helm/chart/default/values.yaml b/config/helm/chart/default/values.yaml index fb554f8240..b68a97a06b 100644 --- a/config/helm/chart/default/values.yaml +++ b/config/helm/chart/default/values.yaml @@ -100,7 +100,7 @@ csidriver: kubeletPath: "/var/lib/kubelet" existingPriorityClassName: "" # if defined, use this priorityclass instead of creating a new one priorityClassValue: "1000000" - maxUnmountedVolumeAge: "" # defined in days, must be a plain number + cleanupPeriod: "" # defined in the Golang time.Duration format, like "30m" == 30 minutes tolerations: - effect: NoSchedule key: node-role.kubernetes.io/master diff --git a/go.mod b/go.mod index 747ca8a909..37a531b599 100644 --- a/go.mod +++ b/go.mod @@ -10,11 +10,9 @@ require ( github.com/google/go-containerregistry v0.20.3 github.com/google/uuid v1.6.0 github.com/klauspost/compress v1.17.11 - github.com/mattn/go-sqlite3 v1.14.24 github.com/opencontainers/go-digest v1.0.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.5 - github.com/prometheus/client_model v0.6.1 github.com/spf13/afero v1.12.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 @@ -64,7 +62,6 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kylelemons/godebug v1.1.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/spdystream v0.5.0 // indirect @@ -76,6 +73,7 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect diff --git a/go.sum b/go.sum index a5871682eb..4a30d7d365 100644 --- a/go.sum +++ b/go.sum @@ -89,8 +89,6 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= -github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= diff --git a/hack/build/ci/install-cgo-dependencies.sh b/hack/build/ci/install-cgo-dependencies.sh deleted file mode 100755 index 37640cf7ba..0000000000 --- a/hack/build/ci/install-cgo-dependencies.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -sudo apt-get update -sudo apt-get install -y libdevmapper-dev libbtrfs-dev libgpgme-dev diff --git a/hack/build/create_go_build_tags.sh b/hack/build/create_go_build_tags.sh index caf4cfaebe..f89805a2b9 100755 --- a/hack/build/create_go_build_tags.sh +++ b/hack/build/create_go_build_tags.sh @@ -7,14 +7,7 @@ fi needs_e2e_tag=$1 -go_build_tags=( - # If CGO is enabled, certain standard libraries will also use CGO, these explicitly disallow that - "osusergo" - "netgo" - - # Disables the ability to add load extensions for sqlite3, needed to statically build when using the sqlite library. We never use extensions so its good to disable it. - "sqlite_omit_load_extension" -) +go_build_tags=() if "${needs_e2e_tag}"; then # Used for enabling e2e testing code diff --git a/pkg/api/v1beta3/dynakube/dynakube_props.go b/pkg/api/v1beta3/dynakube/dynakube_props.go index 26b9aca5ca..66b73ad319 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_props.go +++ b/pkg/api/v1beta3/dynakube/dynakube_props.go @@ -2,7 +2,6 @@ package dynakube import ( "net/url" - "strings" "time" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" @@ -80,37 +79,7 @@ func (dk *DynaKube) Tokens() string { return dk.Name } -func (dk *DynaKube) TenantUUIDFromApiUrl() (string, error) { - return tenantUUID(dk.ApiUrl()) -} - -func runeIs(wanted rune) func(rune) bool { - return func(actual rune) bool { - return actual == wanted - } -} - -func tenantUUID(apiUrl string) (string, error) { - parsedUrl, err := url.Parse(apiUrl) - if err != nil { - return "", errors.WithMessagef(err, "problem parsing tenant id from url %s", apiUrl) - } - - // Path = "/e//api" -> ["e", "", "api"] - subPaths := strings.FieldsFunc(parsedUrl.Path, runeIs('/')) - if len(subPaths) >= 3 && subPaths[0] == "e" && subPaths[2] == "api" { - return subPaths[1], nil - } - - hostnameWithDomains := strings.FieldsFunc(parsedUrl.Hostname(), runeIs('.')) - if len(hostnameWithDomains) >= 1 { - return hostnameWithDomains[0], nil - } - - return "", errors.Errorf("problem getting tenant id from API URL '%s'", apiUrl) -} - -func (dk *DynaKube) TenantUUIDFromConnectionInfoStatus() (string, error) { +func (dk *DynaKube) TenantUUID() (string, error) { if dk.Status.OneAgent.ConnectionInfoStatus.TenantUUID != "" { return dk.Status.OneAgent.ConnectionInfoStatus.TenantUUID, nil } else if dk.Status.ActiveGate.ConnectionInfo.TenantUUID != "" { diff --git a/pkg/api/v1beta3/dynakube/dynakube_props_test.go b/pkg/api/v1beta3/dynakube/dynakube_props_test.go index 4ccea22b72..bb470f80c9 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_props_test.go +++ b/pkg/api/v1beta3/dynakube/dynakube_props_test.go @@ -22,7 +22,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" ) @@ -44,74 +43,6 @@ func TestTokens(t *testing.T) { }) } -func TestTenantUUID(t *testing.T) { - t.Run("happy path", func(t *testing.T) { - apiUrl := "https://demo.dev.dynatracelabs.com/api" - expectedTenantId := "demo" - - actualTenantId, err := tenantUUID(apiUrl) - - require.NoErrorf(t, err, "Expected that getting tenant id from '%s' will be successful", apiUrl) - assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", - apiUrl, expectedTenantId, actualTenantId, - ) - }) - - t.Run("happy path (alternative)", func(t *testing.T) { - apiUrl := "https://dynakube-activegate.dynatrace/e/tenant/api/v2/metrics/ingest" - expectedTenantId := "tenant" - - actualTenantId, err := tenantUUID(apiUrl) - - require.NoErrorf(t, err, "Expected that getting tenant id from '%s' will be successful", apiUrl) - assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", - apiUrl, expectedTenantId, actualTenantId, - ) - }) - - t.Run("happy path (alternative, no domain)", func(t *testing.T) { - apiUrl := "https://dynakube-activegate/e/tenant/api/v2/metrics/ingest" - expectedTenantId := "tenant" - - actualTenantId, err := tenantUUID(apiUrl) - - require.NoErrorf(t, err, "Expected that getting tenant id from '%s' will be successful", apiUrl) - assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", - apiUrl, expectedTenantId, actualTenantId, - ) - }) - - t.Run("missing API URL protocol", func(t *testing.T) { - apiUrl := "demo.dev.dynatracelabs.com/api" - expectedTenantId := "" - expectedError := "problem getting tenant id from API URL 'demo.dev.dynatracelabs.com/api'" - - actualTenantId, err := tenantUUID(apiUrl) - - require.EqualErrorf(t, err, expectedError, "Expected that getting tenant id from '%s' will result in: '%v'", - apiUrl, expectedError, - ) - assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", - apiUrl, expectedTenantId, actualTenantId, - ) - }) - - t.Run("suffix-only, relative API URL", func(t *testing.T) { - apiUrl := "/api" - expectedTenantId := "" - expectedError := "problem getting tenant id from API URL '/api'" - - actualTenantId, err := tenantUUID(apiUrl) - - require.EqualErrorf(t, err, expectedError, "Expected that getting tenant id from '%s' will result in: '%v'", - apiUrl, expectedError, - ) - assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", - apiUrl, expectedTenantId, actualTenantId, - ) - }) -} - func TestIsTokenScopeVerificationAllowed(t *testing.T) { dk := DynaKube{ Status: DynaKubeStatus{ diff --git a/pkg/controllers/csi/config.go b/pkg/controllers/csi/config.go index 5f787bbead..a62e57aaf0 100644 --- a/pkg/controllers/csi/config.go +++ b/pkg/controllers/csi/config.go @@ -30,6 +30,7 @@ const ( OverlayVarDirPath = "var" OverlayWorkDirPath = "work" SharedAgentBinDir = "codemodules" + SharedAppMountsDir = "appmounts" SharedAgentConfigDir = "config" DaemonSetName = "dynatrace-oneagent-csi-driver" diff --git a/pkg/controllers/csi/driver/server.go b/pkg/controllers/csi/driver/server.go index e3ee8fd931..38e0833d05 100644 --- a/pkg/controllers/csi/driver/server.go +++ b/pkg/controllers/csi/driver/server.go @@ -52,7 +52,6 @@ type Server struct { fs afero.Afero mounter mount.Interface - db metadata.Access publishers map[string]csivolumes.Publisher opts dtcsi.CSIOptions @@ -62,39 +61,37 @@ type Server struct { var _ csi.IdentityServer = &Server{} var _ csi.NodeServer = &Server{} -func NewServer(opts dtcsi.CSIOptions, db metadata.Access) *Server { +func NewServer(opts dtcsi.CSIOptions) *Server { return &Server{ opts: opts, fs: afero.Afero{Fs: afero.NewOsFs()}, mounter: mount.New(""), - db: db, path: metadata.PathResolver{RootDir: opts.RootDir}, } } -func (svr *Server) SetupWithManager(mgr ctrl.Manager) error { - return mgr.Add(svr) +func (srv *Server) SetupWithManager(mgr ctrl.Manager) error { + return mgr.Add(srv) } -func (svr *Server) Start(ctx context.Context) error { - defer metadata.LogAccessOverview(svr.db) - - endpoint, err := url.Parse(svr.opts.Endpoint) - addr := endpoint.Host + endpoint.Path +func (srv *Server) Start(ctx context.Context) error { + endpoint, err := url.Parse(srv.opts.Endpoint) if err != nil { - return fmt.Errorf("failed to parse endpoint '%s': %w", svr.opts.Endpoint, err) + return fmt.Errorf("failed to parse endpoint '%s': %w", srv.opts.Endpoint, err) } + addr := endpoint.Host + endpoint.Path + if endpoint.Scheme == "unix" { - if err := svr.fs.Remove(addr); err != nil && !os.IsNotExist(err) { + if err := srv.fs.Remove(addr); err != nil && !os.IsNotExist(err) { return fmt.Errorf("failed to remove old endpoint on '%s': %w", addr, err) } } - svr.publishers = map[string]csivolumes.Publisher{ - appvolumes.Mode: appvolumes.NewAppVolumePublisher(svr.fs, svr.mounter, svr.db, svr.path), - hostvolumes.Mode: hostvolumes.NewHostVolumePublisher(svr.fs, svr.mounter, svr.db, svr.path), + srv.publishers = map[string]csivolumes.Publisher{ + appvolumes.Mode: appvolumes.NewPublisher(srv.fs, srv.mounter, srv.path), + hostvolumes.Mode: hostvolumes.NewPublisher(srv.fs, srv.mounter, srv.path), } log.Info("starting listener", "scheme", endpoint.Scheme, "address", addr) @@ -132,8 +129,8 @@ func (svr *Server) Start(ctx context.Context) error { } }() - csi.RegisterIdentityServer(server, svr) - csi.RegisterNodeServer(server, svr) + csi.RegisterIdentityServer(server, srv) + csi.RegisterNodeServer(server, srv) log.Info("listening for connections on address", "address", listener.Addr()) @@ -143,31 +140,31 @@ func (svr *Server) Start(ctx context.Context) error { return err } -func (svr *Server) GetPluginInfo(context.Context, *csi.GetPluginInfoRequest) (*csi.GetPluginInfoResponse, error) { +func (srv *Server) GetPluginInfo(context.Context, *csi.GetPluginInfoRequest) (*csi.GetPluginInfoResponse, error) { return &csi.GetPluginInfoResponse{Name: dtcsi.DriverName, VendorVersion: version.Version}, nil } -func (svr *Server) Probe(context.Context, *csi.ProbeRequest) (*csi.ProbeResponse, error) { +func (srv *Server) Probe(context.Context, *csi.ProbeRequest) (*csi.ProbeResponse, error) { return &csi.ProbeResponse{}, nil } -func (svr *Server) GetPluginCapabilities(context.Context, *csi.GetPluginCapabilitiesRequest) (*csi.GetPluginCapabilitiesResponse, error) { +func (srv *Server) GetPluginCapabilities(context.Context, *csi.GetPluginCapabilitiesRequest) (*csi.GetPluginCapabilitiesResponse, error) { return &csi.GetPluginCapabilitiesResponse{}, nil } -func (svr *Server) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) { +func (srv *Server) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) { volumeCfg, err := csivolumes.ParseNodePublishVolumeRequest(req) if err != nil { return nil, err } - if isMounted, err := svr.mounter.IsMountPoint(volumeCfg.TargetPath); err != nil && !os.IsNotExist(err) { + if isMounted, err := srv.mounter.IsMountPoint(volumeCfg.TargetPath); err != nil && !os.IsNotExist(err) { return nil, err } else if isMounted { return &csi.NodePublishVolumeResponse{}, nil } - publisher, ok := svr.publishers[volumeCfg.Mode] + publisher, ok := srv.publishers[volumeCfg.Mode] if !ok { return nil, status.Error(codes.Internal, "unknown csi mode provided, mode="+volumeCfg.Mode) } @@ -185,62 +182,98 @@ func (svr *Server) NodePublishVolume(ctx context.Context, req *csi.NodePublishVo return publisher.PublishVolume(ctx, volumeCfg) } -func (svr *Server) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) { +func (srv *Server) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) { volumeInfo, err := csivolumes.ParseNodeUnpublishVolumeRequest(req) if err != nil { return nil, err } - for _, publisher := range svr.publishers { - canUnpublish, err := publisher.CanUnpublishVolume(ctx, volumeInfo) - if err != nil { - log.Error(err, "couldn't determine if volume can be unpublished", "publisher", publisher) + srv.unmount(*volumeInfo) + + return &csi.NodeUnpublishVolumeResponse{}, nil +} + +func (srv *Server) unmount(volumeInfo csivolumes.VolumeInfo) { + // targetPath always needs to be unmounted + if err := srv.mounter.Unmount(volumeInfo.TargetPath); err != nil { + log.Error(err, "Unmount failed", "path", volumeInfo.TargetPath) + } + + appMountDir := srv.path.AppMountForID(volumeInfo.VolumeID) + + mappedDir := srv.path.AppMountMappedDir(volumeInfo.VolumeID) // Unmount follows symlinks, so no need to check for them here + + _, err := srv.fs.Stat(mappedDir) + if os.IsNotExist(err) { // case for timed out mounts + _ = srv.fs.RemoveAll(appMountDir) + + return + } else if err != nil { + log.Error(err, "unexpected error when checking for app mount folder, trying to unmount just to be sure") + } + + if err := srv.mounter.Unmount(mappedDir); err != nil { + // Just try to unmount, nothing really can go wrong, just have to handle errors + log.Error(err, "Unmount failed", "path", mappedDir) + } else { + // special handling is needed, because after upgrade/restart the mappedDir will be still busy + needsCleanUp := []string{ + srv.path.AppMountVarDir(volumeInfo.VolumeID), + srv.path.AppMountWorkDir(volumeInfo.VolumeID), } - if canUnpublish { - response, err := publisher.UnpublishVolume(ctx, volumeInfo) + for _, path := range needsCleanUp { + err := srv.fs.RemoveAll(path) // you see correctly, we don't keep the logs of the app mounts, will keep them when they will have a use if err != nil { - return nil, err + log.Error(err, "failed to clean up unmounted volume dir", "path", path) } - - return response, nil } - } - svr.unmountUnknownVolume(*volumeInfo) + _ = srv.fs.RemoveAll(appMountDir) // try to cleanup fully, but lets not spam the logs with errors + } - return &csi.NodeUnpublishVolumeResponse{}, nil + podInfoSymlinkPath := srv.findPodInfoSymlink(volumeInfo) // cleaning up the pod-info symlink here is far more efficient instead of having to walk the whole fs during cleanup + if podInfoSymlinkPath != "" { + _ = srv.fs.Remove(podInfoSymlinkPath) + } } -func (svr *Server) unmountUnknownVolume(volumeInfo csivolumes.VolumeInfo) { - log.Info("VolumeID not present in the database", "volumeID", volumeInfo.VolumeID, "targetPath", volumeInfo.TargetPath) +func (srv *Server) findPodInfoSymlink(volumeInfo csivolumes.VolumeInfo) string { + podInfoPath := srv.path.OverlayVarPodInfo(volumeInfo.VolumeID) + + podInfoBytes, err := srv.fs.ReadFile(srv.path.OverlayVarPodInfo(volumeInfo.VolumeID)) + if err != nil { + if os.IsNotExist(err) { + return "" + } - if err := svr.mounter.Unmount(volumeInfo.TargetPath); err != nil { - log.Error(err, "Tried to unmount unknown volume", "volumeID", volumeInfo.VolumeID) + log.Error(err, "failed to read pod-info file", "path", podInfoPath) } + + return string(podInfoBytes) } -func (svr *Server) NodeStageVolume(context.Context, *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) { +func (srv *Server) NodeStageVolume(context.Context, *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) { return nil, status.Error(codes.Unimplemented, "") } -func (svr *Server) NodeUnstageVolume(context.Context, *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) { +func (srv *Server) NodeUnstageVolume(context.Context, *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) { return nil, status.Error(codes.Unimplemented, "") } -func (svr *Server) NodeGetInfo(context.Context, *csi.NodeGetInfoRequest) (*csi.NodeGetInfoResponse, error) { - return &csi.NodeGetInfoResponse{NodeId: svr.opts.NodeId}, nil +func (srv *Server) NodeGetInfo(context.Context, *csi.NodeGetInfoRequest) (*csi.NodeGetInfoResponse, error) { + return &csi.NodeGetInfoResponse{NodeId: srv.opts.NodeId}, nil } -func (svr *Server) NodeGetCapabilities(context.Context, *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) { +func (srv *Server) NodeGetCapabilities(context.Context, *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) { return &csi.NodeGetCapabilitiesResponse{Capabilities: []*csi.NodeServiceCapability{}}, nil } -func (svr *Server) NodeGetVolumeStats(context.Context, *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) { +func (srv *Server) NodeGetVolumeStats(context.Context, *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) { return nil, status.Error(codes.Unimplemented, "") } -func (svr *Server) NodeExpandVolume(context.Context, *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) { +func (srv *Server) NodeExpandVolume(context.Context, *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) { return nil, status.Error(codes.Unimplemented, "") } diff --git a/pkg/controllers/csi/driver/volumes/app/config.go b/pkg/controllers/csi/driver/volumes/app/config.go index 3cc6bce1aa..27ed6c84b2 100644 --- a/pkg/controllers/csi/driver/volumes/app/config.go +++ b/pkg/controllers/csi/driver/volumes/app/config.go @@ -1,4 +1,4 @@ -package appvolumes +package app import ( "github.com/Dynatrace/dynatrace-operator/pkg/logd" diff --git a/pkg/controllers/csi/driver/volumes/app/publisher.go b/pkg/controllers/csi/driver/volumes/app/publisher.go index a26b872728..17285f4712 100644 --- a/pkg/controllers/csi/driver/volumes/app/publisher.go +++ b/pkg/controllers/csi/driver/volumes/app/publisher.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package appvolumes +package app import ( "context" @@ -22,293 +22,249 @@ import ( "io" "os" "path/filepath" - "strings" + "time" - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csivolumes "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver/volumes" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/symlink" + "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "github.com/container-storage-interface/spec/lib/go/csi" "github.com/pkg/errors" - dto "github.com/prometheus/client_model/go" "github.com/spf13/afero" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" mount "k8s.io/mount-utils" ) -func NewAppVolumePublisher(fs afero.Afero, mounter mount.Interface, db metadata.Access, path metadata.PathResolver) csivolumes.Publisher { - return &AppVolumePublisher{ +func NewPublisher(fs afero.Afero, mounter mount.Interface, path metadata.PathResolver) csivolumes.Publisher { + return &Publisher{ fs: fs, mounter: mounter, - db: db, path: path, + time: timeprovider.New(), } } -type AppVolumePublisher struct { +type Publisher struct { fs afero.Afero mounter mount.Interface - db metadata.Access + time *timeprovider.Provider path metadata.PathResolver } -func (publisher *AppVolumePublisher) PublishVolume(ctx context.Context, volumeCfg *csivolumes.VolumeConfig) (*csi.NodePublishVolumeResponse, error) { - bindCfg, err := csivolumes.NewBindConfig(ctx, publisher.db, volumeCfg) - if err != nil { - return nil, err - } - - hasTooManyAttempts, err := publisher.hasTooManyMountAttempts(ctx, bindCfg, volumeCfg) - if err != nil { - return nil, err - } - - if hasTooManyAttempts { +func (pub *Publisher) PublishVolume(ctx context.Context, volumeCfg *csivolumes.VolumeConfig) (*csi.NodePublishVolumeResponse, error) { + if pub.hasRetryLimitReached(volumeCfg) { log.Info("reached max mount attempts for pod, attaching dummy volume, monitoring disabled", "pod", volumeCfg.PodName) return &csi.NodePublishVolumeResponse{}, nil } - if !bindCfg.IsArchiveAvailable() { + if !pub.isCodeModuleAvailable(volumeCfg) { return nil, status.Error( codes.Unavailable, - "version or digest is not yet set, csi-provisioner hasn't finished setup yet for tenant: "+bindCfg.TenantUUID, + "version or digest is not yet set, csi-provisioner hasn't finished setup yet for DynaKube: "+volumeCfg.DynakubeName, ) } - if err := publisher.ensureMountSteps(ctx, bindCfg, volumeCfg); err != nil { - return nil, err + if err := pub.mountCodeModule(volumeCfg); err != nil { + return nil, status.Error(codes.Internal, fmt.Sprintf("failed to mount oneagent volume: %s", err)) } - agentsVersionsMetric.WithLabelValues(bindCfg.MetricVersionLabel()).Inc() - return &csi.NodePublishVolumeResponse{}, nil } -func (publisher *AppVolumePublisher) UnpublishVolume(ctx context.Context, volumeInfo *csivolumes.VolumeInfo) (*csi.NodeUnpublishVolumeResponse, error) { - volume, err := publisher.loadVolume(ctx, volumeInfo.VolumeID) - if err != nil { - log.Info("failed to load volume info", "error", err.Error()) - } - - if volume == nil { - return &csi.NodeUnpublishVolumeResponse{}, nil - } - - log.Info("loaded volume info", "id", volume.VolumeID, "pod name", volume.PodName, "version", volume.Version, "dynakube", volume.TenantUUID) - - if volume.Version == "" { - log.Info("requester has a dummy volume, no node-level unmount is needed") - - return &csi.NodeUnpublishVolumeResponse{}, publisher.db.DeleteVolume(ctx, volume.VolumeID) - } +// hasRetryLimitReached creates the base dir for a given app mount if it doesn't exist yet, checks the creation timestamp against the threshold +// if any of the FS calls fail in an unexpected way, then it is considered that the limit was reached. +func (pub *Publisher) hasRetryLimitReached(volumeCfg *csivolumes.VolumeConfig) bool { + appDir := pub.path.AppMountForID(volumeCfg.VolumeID) - overlayFSPath := publisher.path.AgentRunDirForVolume(volume.TenantUUID, volumeInfo.VolumeID) - publisher.unmountOneAgent(volumeInfo.TargetPath, overlayFSPath) + stat, err := pub.fs.Stat(appDir) + if errors.Is(err, os.ErrNotExist) { + // First run, create folder, to keep track of time + err := pub.fs.MkdirAll(appDir, os.ModePerm) + if err != nil { + log.Error(err, "failed to create base dir for app mount, skipping injection", "dir", appDir) - if err = publisher.db.DeleteVolume(ctx, volume.VolumeID); err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } + return true + } - log.Info("deleted volume info", "ID", volume.VolumeID, "PodUID", volume.PodName, "Version", volume.Version, "TenantUUID", volume.TenantUUID) + return false + } else if err != nil { + log.Error(err, "unexpected failure in checking filesystem state, skipping injection", "dir", appDir) - if err = publisher.fs.RemoveAll(volumeInfo.TargetPath); err != nil { - return nil, status.Error(codes.Internal, err.Error()) + return true } - log.Info("volume has been unpublished", "targetPath", volumeInfo.TargetPath) - - publisher.fireVolumeUnpublishedMetric(*volume) - - return &csi.NodeUnpublishVolumeResponse{}, nil -} - -func (publisher *AppVolumePublisher) CanUnpublishVolume(ctx context.Context, volumeInfo *csivolumes.VolumeInfo) (bool, error) { - volume, err := publisher.loadVolume(ctx, volumeInfo.VolumeID) - if err != nil { - return false, status.Error(codes.Internal, "failed to get volume info from database: "+err.Error()) - } + limit := stat.ModTime().Add(volumeCfg.RetryTimeout) + log.Info("not first attempt, time remaining before skipping injection", "remaining time", time.Until(limit).String()) - return volume != nil, nil + return pub.time.Now().After(limit) } -func (publisher *AppVolumePublisher) fireVolumeUnpublishedMetric(volume metadata.Volume) { - if len(volume.Version) > 0 { - agentsVersionsMetric.WithLabelValues(volume.Version).Dec() +// isCodeModuleAvailable checks if the LatestAgentBinaryForDynaKube folder exists or not +func (pub *Publisher) isCodeModuleAvailable(volumeCfg *csivolumes.VolumeConfig) bool { + binDir := pub.path.LatestAgentBinaryForDynaKube(volumeCfg.DynakubeName) - var m = &dto.Metric{} - if err := agentsVersionsMetric.WithLabelValues(volume.Version).Write(m); err != nil { - log.Error(err, "failed to get the value of agent version metric") - } + stat, err := pub.fs.Stat(binDir) + if errors.Is(err, os.ErrNotExist) { + log.Info("no CodeModule is available to mount yet, will retry later", "dynakube", volumeCfg.DynakubeName) - if m.GetGauge().GetValue() <= float64(0) { - agentsVersionsMetric.DeleteLabelValues(volume.Version) - } - } -} + return false + } else if err != nil { + log.Error(err, "unexpected failure while checking for the latest available CodeModule", "dynakube", volumeCfg.DynakubeName) -func (publisher *AppVolumePublisher) buildLowerDir(bindCfg *csivolumes.BindConfig) string { - var binFolderName string - if bindCfg.ImageDigest == "" { - binFolderName = bindCfg.Version - } else { - binFolderName = bindCfg.ImageDigest + return false } - directories := []string{ - publisher.path.AgentSharedBinaryDirForAgent(binFolderName), - } - - return strings.Join(directories, ":") + return stat.IsDir() } -func (publisher *AppVolumePublisher) prepareUpperDir(bindCfg *csivolumes.BindConfig, volumeCfg *csivolumes.VolumeConfig) (string, error) { - upperDir := publisher.path.OverlayVarDir(bindCfg.TenantUUID, volumeCfg.VolumeID) - err := publisher.fs.MkdirAll(upperDir, os.ModePerm) +func (pub *Publisher) mountCodeModule(volumeCfg *csivolumes.VolumeConfig) error { + mappedDir := pub.path.AppMountMappedDir(volumeCfg.VolumeID) + err := pub.fs.MkdirAll(mappedDir, os.ModePerm) if err != nil { - return "", errors.WithMessagef(err, "failed create overlay upper directory structure, path: %s", upperDir) + return err } - destAgentConfPath := publisher.path.OverlayVarRuxitAgentProcConf(bindCfg.TenantUUID, volumeCfg.VolumeID) - - err = publisher.fs.MkdirAll(filepath.Dir(destAgentConfPath), os.ModePerm) + upperDir, err := pub.prepareUpperDir(volumeCfg) if err != nil { - return "", errors.WithMessagef(err, "failed create overlay upper directory agent config directory structure, path: %s", upperDir) + return err } - srcAgentConfPath := publisher.path.AgentSharedRuxitAgentProcConf(bindCfg.TenantUUID, volumeCfg.DynakubeName) - srcFile, err := publisher.fs.Open(srcAgentConfPath) + workDir := pub.path.AppMountWorkDir(volumeCfg.VolumeID) + err = pub.fs.MkdirAll(workDir, os.ModePerm) if err != nil { - return "", errors.WithMessagef(err, "failed to open ruxitagentproc.conf file, path: %s", srcAgentConfPath) + return err } - defer func() { _ = srcFile.Close() }() + lowerDir := pub.path.LatestAgentBinaryForDynaKube(volumeCfg.DynakubeName) - srcStat, err := srcFile.Stat() - if err != nil { - return "", errors.WithMessage(err, "failed to get source ruxitagentproc.conf file info") + linker, ok := pub.fs.Fs.(afero.LinkReader) + if ok { // will only be !ok during unit testing + lowerDir, err = linker.ReadlinkIfPossible(lowerDir) + if err != nil { + log.Info("failed to read symlink for latest CodeModule", "symlink", lowerDir) + + return err + } } - destFile, err := publisher.fs.OpenFile(destAgentConfPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, srcStat.Mode()) - if err != nil { - return "", errors.WithMessagef(err, "failed to open destination ruxitagentproc.conf file, path: %s", destAgentConfPath) + overlayOptions := []string{ + "lowerdir=" + lowerDir, + "upperdir=" + upperDir, + "workdir=" + workDir, } - defer func() { _ = destFile.Close() }() + if err := pub.fs.MkdirAll(volumeCfg.TargetPath, os.ModePerm); err != nil { + return err + } - _, err = io.Copy(destFile, srcFile) - if err != nil { - return "", errors.WithMessagef(err, "failed to copy ruxitagentproc.conf file to overlay, from->to: %s -> %s", srcAgentConfPath, destAgentConfPath) + if err := pub.mounter.Mount("overlay", mappedDir, "overlay", overlayOptions); err != nil { + return err } - return upperDir, nil -} + if err := pub.mounter.Mount(mappedDir, volumeCfg.TargetPath, "", []string{"bind"}); err != nil { + _ = pub.mounter.Unmount(mappedDir) -func (publisher *AppVolumePublisher) mountOneAgent(bindCfg *csivolumes.BindConfig, volumeCfg *csivolumes.VolumeConfig) error { - mappedDir := publisher.path.OverlayMappedDir(bindCfg.TenantUUID, volumeCfg.VolumeID) - _ = publisher.fs.MkdirAll(mappedDir, os.ModePerm) + return err + } - upperDir, err := publisher.prepareUpperDir(bindCfg, volumeCfg) + err = pub.addPodInfoSymlink(volumeCfg) if err != nil { return err } - workDir := publisher.path.OverlayWorkDir(bindCfg.TenantUUID, volumeCfg.VolumeID) - _ = publisher.fs.MkdirAll(workDir, os.ModePerm) - - overlayOptions := []string{ - "lowerdir=" + publisher.buildLowerDir(bindCfg), - "upperdir=" + upperDir, - "workdir=" + workDir, - } + return nil +} - if err := publisher.fs.MkdirAll(volumeCfg.TargetPath, os.ModePerm); err != nil { +func (pub *Publisher) addPodInfoSymlink(volumeCfg *csivolumes.VolumeConfig) error { + appMountPodInfoDir := pub.path.AppMountPodInfoDir(volumeCfg.DynakubeName, volumeCfg.PodNamespace, volumeCfg.PodName) + if err := pub.fs.MkdirAll(appMountPodInfoDir, os.ModePerm); err != nil { return err } - if err := publisher.mounter.Mount("overlay", mappedDir, "overlay", overlayOptions); err != nil { + targetDir := pub.path.AppMountForID(volumeCfg.VolumeID) + + if err := symlink.Remove(pub.fs.Fs, appMountPodInfoDir); err != nil { return err } - if err := publisher.mounter.Mount(mappedDir, volumeCfg.TargetPath, "", []string{"bind"}); err != nil { - _ = publisher.mounter.Unmount(mappedDir) - + err := symlink.Create(pub.fs.Fs, targetDir, appMountPodInfoDir) + if err != nil { return err } return nil } -func (publisher *AppVolumePublisher) unmountOneAgent(targetPath string, overlayFSPath string) { - if err := publisher.mounter.Unmount(targetPath); err != nil { - log.Error(err, "Unmount failed", "path", targetPath) +func (pub *Publisher) prepareUpperDir(volumeCfg *csivolumes.VolumeConfig) (string, error) { + upperDir := pub.path.AppMountVarDir(volumeCfg.VolumeID) + + err := pub.prepareAgentConfigInUpperDir(volumeCfg) + if err != nil { + return "", err } - if filepath.IsAbs(overlayFSPath) { - agentDirectoryForPod := filepath.Join(overlayFSPath, dtcsi.OverlayMappedDirPath) - if err := publisher.mounter.Unmount(agentDirectoryForPod); err != nil { - log.Error(err, "Unmount failed", "path", agentDirectoryForPod) - } + err = pub.preparePodInfoUpperDir(volumeCfg) + if err != nil { + return "", err } + + return upperDir, nil } -func (publisher *AppVolumePublisher) ensureMountSteps(ctx context.Context, bindCfg *csivolumes.BindConfig, volumeCfg *csivolumes.VolumeConfig) error { - if err := publisher.mountOneAgent(bindCfg, volumeCfg); err != nil { - return status.Error(codes.Internal, fmt.Sprintf("failed to mount oneagent volume: %s", err)) +func (pub *Publisher) prepareAgentConfigInUpperDir(volumeCfg *csivolumes.VolumeConfig) error { + destAgentConfPath := pub.path.OverlayVarRuxitAgentProcConf(volumeCfg.VolumeID) + + err := pub.fs.MkdirAll(filepath.Dir(destAgentConfPath), os.ModePerm) + if err != nil { + return errors.WithMessagef(err, "failed to create overlay upper directory agent config directory structure, path: %s", destAgentConfPath) } - if err := publisher.storeVolume(ctx, bindCfg, volumeCfg); err != nil { - overlayFSPath := publisher.path.AgentRunDirForVolume(bindCfg.TenantUUID, volumeCfg.VolumeID) - publisher.unmountOneAgent(volumeCfg.TargetPath, overlayFSPath) + srcAgentConfPath := pub.path.AgentSharedRuxitAgentProcConf(volumeCfg.DynakubeName) + srcFile, err := pub.fs.Open(srcAgentConfPath) - return status.Error(codes.Internal, fmt.Sprintf("Failed to store volume info: %s", err)) + if err != nil { + return errors.WithMessagef(err, "failed to open ruxitagentproc.conf file, path: %s", srcAgentConfPath) } - return nil -} + defer func() { _ = srcFile.Close() }() -func (publisher *AppVolumePublisher) hasTooManyMountAttempts(ctx context.Context, bindCfg *csivolumes.BindConfig, volumeCfg *csivolumes.VolumeConfig) (bool, error) { - volume, err := publisher.loadVolume(ctx, volumeCfg.VolumeID) + srcStat, err := srcFile.Stat() if err != nil { - return false, err + return errors.WithMessage(err, "failed to get source ruxitagentproc.conf file info") } - if volume == nil { - volume = createNewVolume(bindCfg, volumeCfg) + destFile, err := pub.fs.OpenFile(destAgentConfPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, srcStat.Mode()) + if err != nil { + return errors.WithMessagef(err, "failed to open destination ruxitagentproc.conf file, path: %s", destAgentConfPath) } - if volume.MountAttempts > bindCfg.MaxMountAttempts { - return true, nil - } + defer func() { _ = destFile.Close() }() - volume.MountAttempts += 1 + _, err = io.Copy(destFile, srcFile) + if err != nil { + return errors.WithMessagef(err, "failed to copy ruxitagentproc.conf file to overlay, from->to: %s -> %s", srcAgentConfPath, destAgentConfPath) + } - return false, publisher.db.InsertVolume(ctx, volume) + return err } -func (publisher *AppVolumePublisher) storeVolume(ctx context.Context, bindCfg *csivolumes.BindConfig, volumeCfg *csivolumes.VolumeConfig) error { - volume := createNewVolume(bindCfg, volumeCfg) - log.Info("inserting volume info", "ID", volume.VolumeID, "PodUID", volume.PodName, "Version", volume.Version, "TenantUUID", volume.TenantUUID) - - return publisher.db.InsertVolume(ctx, volume) -} +func (pub *Publisher) preparePodInfoUpperDir(volumeCfg *csivolumes.VolumeConfig) error { + content := pub.path.AppMountPodInfoDir(volumeCfg.DynakubeName, volumeCfg.PodNamespace, volumeCfg.PodName) + destPath := pub.path.OverlayVarPodInfo(volumeCfg.VolumeID) -func (publisher *AppVolumePublisher) loadVolume(ctx context.Context, volumeID string) (*metadata.Volume, error) { - volume, err := publisher.db.GetVolume(ctx, volumeID) + destFile, err := pub.fs.OpenFile(destPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm) if err != nil { - return nil, err + return errors.WithMessagef(err, "failed to open destination pod-info file, path: %s", destPath) } - return volume, nil -} - -func createNewVolume(bindCfg *csivolumes.BindConfig, volumeCfg *csivolumes.VolumeConfig) *metadata.Volume { - version := bindCfg.Version - if bindCfg.ImageDigest != "" { - version = bindCfg.ImageDigest + _, err = destFile.WriteString(content) + if err != nil { + return errors.WithMessagef(err, "failed write into pod-info file, path: %s", destPath) } - return metadata.NewVolume(volumeCfg.VolumeID, volumeCfg.PodName, version, bindCfg.TenantUUID, 0) + return nil } diff --git a/pkg/controllers/csi/driver/volumes/app/publisher_test.go b/pkg/controllers/csi/driver/volumes/app/publisher_test.go index 2002e0cd11..6b3c07f393 100644 --- a/pkg/controllers/csi/driver/volumes/app/publisher_test.go +++ b/pkg/controllers/csi/driver/volumes/app/publisher_test.go @@ -1,409 +1,194 @@ -package appvolumes +package app import ( "context" - "fmt" + "os" "testing" + "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csivolumes "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver/volumes" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/prometheus/client_golang/prometheus/testutil" + "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "k8s.io/mount-utils" ) -const ( - testPodUID = "a-pod" - testVolumeId = "a-volume" - testTargetPath = "/path/to/container/filesystem/opt/dynatrace/oneagent-paas" - testTenantUUID = "a-tenant-uuid" - testAgentVersion = "1.2-3" - testDynakubeName = "a-dynakube" - testImageDigest = "sha256:123456789" -) - func TestPublishVolume(t *testing.T) { - t.Run("using url", func(t *testing.T) { - mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - mockUrlDynakubeMetadata(t, &publisher) - mockSharedRuxitAgentProcConf(t, &publisher) - - response, err := publisher.PublishVolume(context.Background(), createTestVolumeConfig()) - require.NoError(t, err) - assert.NotNil(t, response) - - require.NotEmpty(t, mounter.MountPoints) - - assert.Equal(t, "overlay", mounter.MountPoints[0].Device) - assert.Equal(t, "overlay", mounter.MountPoints[0].Type) - assert.Equal(t, []string{ - "lowerdir=/codemodules/1.2-3", - "upperdir=/a-tenant-uuid/run/a-volume/var", - "workdir=/a-tenant-uuid/run/a-volume/work"}, - mounter.MountPoints[0].Opts) - assert.Equal(t, "/a-tenant-uuid/run/a-volume/mapped", mounter.MountPoints[0].Path) - - assert.Equal(t, "overlay", mounter.MountPoints[1].Device) - assert.Equal(t, "", mounter.MountPoints[1].Type) - assert.Equal(t, []string{"bind"}, mounter.MountPoints[1].Opts) - assert.Equal(t, testTargetPath, mounter.MountPoints[1].Path) - - confCopied, err := publisher.fs.Exists(publisher.path.OverlayVarRuxitAgentProcConf(testTenantUUID, testVolumeId)) - require.NoError(t, err) - assert.True(t, confCopied) - - assertReferencesForPublishedVolume(t, &publisher, mounter) - }) + ctx := context.Background() + path := metadata.PathResolver{} - t.Run("using code modules image", func(t *testing.T) { + t.Run("early return - FS problem during timeout check == skip mounting", func(t *testing.T) { + fs := getFailFs(t) mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - mockImageDynakubeMetadata(t, &publisher) - mockSharedRuxitAgentProcConf(t, &publisher) + volumeCfg := getTestVolumeConfig(t) - response, err := publisher.PublishVolume(context.Background(), createTestVolumeConfig()) - require.NoError(t, err) - assert.NotNil(t, response) - - require.NotEmpty(t, mounter.MountPoints) - - assert.Equal(t, "overlay", mounter.MountPoints[0].Device) - assert.Equal(t, "overlay", mounter.MountPoints[0].Type) - assert.Equal(t, []string{ - "lowerdir=/codemodules/" + testImageDigest, - "upperdir=/a-tenant-uuid/run/a-volume/var", - "workdir=/a-tenant-uuid/run/a-volume/work"}, - mounter.MountPoints[0].Opts) - assert.Equal(t, "/a-tenant-uuid/run/a-volume/mapped", mounter.MountPoints[0].Path) + pub := NewPublisher(fs, mounter, path) - assert.Equal(t, "overlay", mounter.MountPoints[1].Device) - assert.Equal(t, "", mounter.MountPoints[1].Type) - assert.Equal(t, []string{"bind"}, mounter.MountPoints[1].Opts) - assert.Equal(t, testTargetPath, mounter.MountPoints[1].Path) - - confCopied, err := publisher.fs.Exists(publisher.path.OverlayVarRuxitAgentProcConf(testTenantUUID, testVolumeId)) + resp, err := pub.PublishVolume(ctx, &volumeCfg) require.NoError(t, err) - assert.True(t, confCopied) - - assertReferencesForPublishedVolumeWithCodeModulesImage(t, &publisher, mounter) + require.NotNil(t, resp) }) - t.Run("too many mount attempts", func(t *testing.T) { + t.Run("early return - retry limit reached", func(t *testing.T) { + fs := getTestFs(t) mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - mockFailedPublishedVolume(t, &publisher) + volumeCfg := getTestVolumeConfig(t) + require.NoError(t, fs.Mkdir(path.AppMountForID(volumeCfg.VolumeID), os.ModePerm)) + + pastTime := timeprovider.New() + pastTime.Set(time.Now().Add(2 * volumeCfg.RetryTimeout)) + pub := Publisher{ + fs: fs, + mounter: mounter, + path: path, + time: pastTime, + } - response, err := publisher.PublishVolume(context.Background(), createTestVolumeConfig()) + resp, err := pub.PublishVolume(ctx, &volumeCfg) require.NoError(t, err) - assert.NotNil(t, response) + require.NotNil(t, resp) - require.Empty(t, mounter.MountPoints) + assert.Empty(t, mounter.MountPoints) }) -} - -func TestPrepareUpperDir(t *testing.T) { - testFileContent := []byte{'t', 'e', 's', 't'} - testBindConfig := &csivolumes.BindConfig{ - TenantUUID: testTenantUUID, - } - t.Run("happy path -> file copied from shared dir to overlay dir", func(t *testing.T) { + t.Run("early return (with error) - no binary present", func(t *testing.T) { + fs := getTestFs(t) mounter := mount.NewFakeMounter([]mount.MountPoint{}) + volumeCfg := getTestVolumeConfig(t) - publisher := newPublisherForTesting(mounter) - mockSharedRuxitAgentProcConf(t, &publisher, testFileContent...) + pub := NewPublisher(fs, mounter, path) - upperDir, err := publisher.prepareUpperDir(testBindConfig, createTestVolumeConfig()) - require.NoError(t, err) - require.NotEmpty(t, upperDir) - assertUpperDirContent(t, &publisher, testFileContent) + resp, err := pub.PublishVolume(ctx, &volumeCfg) + require.Error(t, err) + require.Nil(t, resp) + + assert.Empty(t, mounter.MountPoints) }) - t.Run("sad path -> source file doesn't exist -> error", func(t *testing.T) { + t.Run("early return (with error) - binary is just a file", func(t *testing.T) { + fs := getTestFs(t) mounter := mount.NewFakeMounter([]mount.MountPoint{}) + volumeCfg := getTestVolumeConfig(t) + file, err := fs.Create(path.LatestAgentBinaryForDynaKube(volumeCfg.DynakubeName)) + require.NoError(t, err) + require.NoError(t, file.Close()) - publisher := newPublisherForTesting(mounter) + pub := NewPublisher(fs, mounter, path) - upperDir, err := publisher.prepareUpperDir(testBindConfig, createTestVolumeConfig()) + resp, err := pub.PublishVolume(ctx, &volumeCfg) require.Error(t, err) - require.Empty(t, upperDir) + require.Nil(t, resp) - confCopied, err := publisher.fs.Exists(publisher.path.OverlayVarRuxitAgentProcConf(testTenantUUID, testVolumeId)) - require.NoError(t, err) - assert.False(t, confCopied) + assert.Empty(t, mounter.MountPoints) }) -} -func assertUpperDirContent(t *testing.T, publisher *AppVolumePublisher, expected []byte) { - content, err := publisher.fs.ReadFile(publisher.path.OverlayVarRuxitAgentProcConf(testTenantUUID, testVolumeId)) - require.NoError(t, err) - assert.Equal(t, expected, content) -} + t.Run("early return (with error) - ruxit.conf not present", func(t *testing.T) { + fs := getTestFs(t) + mounter := mount.NewFakeMounter([]mount.MountPoint{}) + volumeCfg := getTestVolumeConfig(t) -func TestHasTooManyMountAttempts(t *testing.T) { - t.Run(`initial try`, func(t *testing.T) { - publisher := newPublisherForTesting(nil) - bindCfg := &csivolumes.BindConfig{ - TenantUUID: testTenantUUID, - MaxMountAttempts: dynakube.DefaultMaxFailedCsiMountAttempts, - } - volumeCfg := createTestVolumeConfig() + binaryDir := path.LatestAgentBinaryForDynaKube(volumeCfg.DynakubeName) + require.NoError(t, fs.MkdirAll(binaryDir, os.ModePerm)) - hasTooManyAttempts, err := publisher.hasTooManyMountAttempts(context.Background(), bindCfg, volumeCfg) + pub := NewPublisher(fs, mounter, path) - require.NoError(t, err) - assert.False(t, hasTooManyAttempts) + resp, err := pub.PublishVolume(ctx, &volumeCfg) + require.Error(t, err) + require.Nil(t, resp) - volume, err := publisher.db.GetVolume(context.Background(), volumeCfg.VolumeID) - require.NoError(t, err) - require.NotNil(t, volume) - assert.Equal(t, 1, volume.MountAttempts) + assert.Empty(t, mounter.MountPoints) }) - t.Run(`too many mount attempts`, func(t *testing.T) { - publisher := newPublisherForTesting(nil) - mockFailedPublishedVolume(t, &publisher) - - bindCfg := &csivolumes.BindConfig{ - MaxMountAttempts: dynakube.DefaultMaxFailedCsiMountAttempts, - } - hasTooManyAttempts, err := publisher.hasTooManyMountAttempts(context.Background(), bindCfg, createTestVolumeConfig()) - - require.NoError(t, err) - assert.True(t, hasTooManyAttempts) - }) -} + t.Run("happy path", func(t *testing.T) { + fs := getTestFs(t) + mounter := mount.NewFakeMounter([]mount.MountPoint{}) + volumeCfg := getTestVolumeConfig(t) -func TestUnpublishVolume(t *testing.T) { - t.Run(`valid metadata`, func(t *testing.T) { - resetMetrics() + // Binary present + binaryDir := path.LatestAgentBinaryForDynaKube(volumeCfg.DynakubeName) + require.NoError(t, fs.MkdirAll(binaryDir, os.ModePerm)) - mounter := mount.NewFakeMounter([]mount.MountPoint{ - {Path: testTargetPath}, - {Path: fmt.Sprintf("/%s/run/%s/mapped", testTenantUUID, testVolumeId)}, - }) - publisher := newPublisherForTesting(mounter) - mockPublishedVolume(t, &publisher) + // Config present + confFile := path.AgentSharedRuxitAgentProcConf(volumeCfg.DynakubeName) + conf := []byte("testing") + require.NoError(t, fs.WriteFile(confFile, conf, os.ModePerm)) - assert.Equal(t, 1, testutil.CollectAndCount(agentsVersionsMetric)) - assert.InEpsilon(t, 1, testutil.ToFloat64(agentsVersionsMetric.WithLabelValues(testAgentVersion)), 0.01) + pub := NewPublisher(fs, mounter, path) - response, err := publisher.UnpublishVolume(context.Background(), createTestVolumeInfo()) + resp, err := pub.PublishVolume(ctx, &volumeCfg) require.NoError(t, err) + require.NotNil(t, resp) - assert.Equal(t, 0, testutil.CollectAndCount(agentsVersionsMetric)) - assert.InDelta(t, 0, testutil.ToFloat64(agentsVersionsMetric.WithLabelValues(testAgentVersion)), 0.01) + // Directories created correctly + targetDirExists, _ := fs.IsDir(volumeCfg.TargetPath) + assert.True(t, targetDirExists) - require.NotNil(t, response) - require.Empty(t, mounter.MountPoints) - assertNoReferencesForUnpublishedVolume(t, &publisher) - }) + varDir := path.AppMountVarDir(volumeCfg.VolumeID) + varDirExits, _ := fs.IsDir(varDir) + assert.True(t, varDirExits) - t.Run(`invalid metadata`, func(t *testing.T) { - resetMetrics() + mappedDir := path.AppMountMappedDir(volumeCfg.VolumeID) + mappedDirExits, _ := fs.IsDir(mappedDir) + assert.True(t, mappedDirExits) - mounter := mount.NewFakeMounter([]mount.MountPoint{ - {Path: testTargetPath}, - {Path: fmt.Sprintf("/%s/run/%s/mapped", testTenantUUID, testVolumeId)}, - }) - publisher := newPublisherForTesting(mounter) - - response, err := publisher.UnpublishVolume(context.Background(), createTestVolumeInfo()) + workDir := path.AppMountWorkDir(volumeCfg.VolumeID) + workDirExits, _ := fs.IsDir(workDir) + assert.True(t, workDirExits) + // Config copied correctly, original untouched + copiedConfFile := path.OverlayVarRuxitAgentProcConf(volumeCfg.VolumeID) + copiedConf, err := fs.ReadFile(copiedConfFile) require.NoError(t, err) - require.NotNil(t, response) - require.NotEmpty(t, mounter.MountPoints) - assertNoReferencesForUnpublishedVolume(t, &publisher) - }) - - t.Run(`remove dummy volume created after too many failed attempts`, func(t *testing.T) { - resetMetrics() - - mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - mockFailedPublishedVolume(t, &publisher) - - response, err := publisher.UnpublishVolume(context.Background(), createTestVolumeInfo()) + assert.Equal(t, conf, copiedConf) + originalConf, err := fs.ReadFile(confFile) require.NoError(t, err) - require.NotNil(t, response) - require.Empty(t, mounter.MountPoints) + assert.Equal(t, conf, originalConf) + + // Mount happened + // mounter.IsMountPoint can't be used as it uses os.Stat + require.Len(t, mounter.MountPoints, 2) + overlayMount := mounter.MountPoints[0] + assert.Equal(t, "overlay", overlayMount.Device) + assert.Equal(t, mappedDir, overlayMount.Path) + require.Len(t, overlayMount.Opts, 3) + assert.Contains(t, overlayMount.Opts[0], binaryDir) // lowerdir + assert.Contains(t, overlayMount.Opts[1], varDir) // upperdir + assert.Contains(t, overlayMount.Opts[2], workDir) // workdir + + bindMount := mounter.MountPoints[1] + assert.Equal(t, "overlay", bindMount.Device) // this is set to "overlay" by the FakeMounter to mimic a linux FS + assert.Equal(t, volumeCfg.TargetPath, bindMount.Path) }) } -func TestNodePublishAndUnpublishVolume(t *testing.T) { - resetMetrics() - - mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - mockUrlDynakubeMetadata(t, &publisher) - mockSharedRuxitAgentProcConf(t, &publisher) - - publishResponse, err := publisher.PublishVolume(context.Background(), createTestVolumeConfig()) - - require.NoError(t, err) - assert.Equal(t, 1, testutil.CollectAndCount(agentsVersionsMetric)) - assert.InEpsilon(t, 1, testutil.ToFloat64(agentsVersionsMetric.WithLabelValues(testAgentVersion)), 0.01) - - require.NoError(t, err) - assert.NotNil(t, publishResponse) - assert.NotEmpty(t, mounter.MountPoints) - assertReferencesForPublishedVolume(t, &publisher, mounter) - - unpublishResponse, err := publisher.UnpublishVolume(context.Background(), createTestVolumeInfo()) - - assert.Equal(t, 0, testutil.CollectAndCount(agentsVersionsMetric)) - assert.InDelta(t, 0, testutil.ToFloat64(agentsVersionsMetric.WithLabelValues(testAgentVersion)), 0.01) - - require.NoError(t, err) - require.NotNil(t, unpublishResponse) - require.Empty(t, mounter.MountPoints) - assertNoReferencesForUnpublishedVolume(t, &publisher) -} - -func TestStoreAndLoadPodInfo(t *testing.T) { - mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - - bindCfg := &csivolumes.BindConfig{ - Version: testAgentVersion, - TenantUUID: testTenantUUID, - } - - volumeCfg := createTestVolumeConfig() - - err := publisher.storeVolume(context.Background(), bindCfg, volumeCfg) - require.NoError(t, err) - volume, err := publisher.loadVolume(context.Background(), volumeCfg.VolumeID) - require.NoError(t, err) - require.NotNil(t, volume) - assert.Equal(t, testVolumeId, volume.VolumeID) - assert.Equal(t, testPodUID, volume.PodName) - assert.Equal(t, testAgentVersion, volume.Version) - assert.Equal(t, testTenantUUID, volume.TenantUUID) -} - -func TestLoadPodInfo_Empty(t *testing.T) { - mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - - volume, err := publisher.loadVolume(context.Background(), testVolumeId) - require.NoError(t, err) - require.Nil(t, volume) -} - -func TestMountIfDBHasError(t *testing.T) { - mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - publisher.db = &metadata.FakeFailDB{} - - bindCfg := &csivolumes.BindConfig{ - TenantUUID: testTenantUUID, - MaxMountAttempts: dynakube.DefaultMaxFailedCsiMountAttempts, - } - - err := publisher.ensureMountSteps(context.Background(), bindCfg, createTestVolumeConfig()) - require.Error(t, err) - require.Empty(t, mounter.MountPoints) -} - -func newPublisherForTesting(mounter *mount.FakeMounter) AppVolumePublisher { - csiOptions := dtcsi.CSIOptions{RootDir: "/"} +func getTestFs(t *testing.T) afero.Afero { + t.Helper() - tmpFs := afero.NewMemMapFs() - - return AppVolumePublisher{ - fs: afero.Afero{Fs: tmpFs}, - mounter: mounter, - db: metadata.FakeMemoryDB(), - path: metadata.PathResolver{RootDir: csiOptions.RootDir}, - } -} - -func mockPublishedVolume(t *testing.T, publisher *AppVolumePublisher) { - mockUrlDynakubeMetadata(t, publisher) - err := publisher.db.InsertVolume(context.Background(), metadata.NewVolume(testVolumeId, testPodUID, testAgentVersion, testTenantUUID, 0)) - require.NoError(t, err) - agentsVersionsMetric.WithLabelValues(testAgentVersion).Inc() -} - -func mockFailedPublishedVolume(t *testing.T, publisher *AppVolumePublisher) { - mockUrlDynakubeMetadata(t, publisher) - err := publisher.db.InsertVolume(context.Background(), metadata.NewVolume(testVolumeId, testPodUID, testAgentVersion, testTenantUUID, dynakube.DefaultMaxFailedCsiMountAttempts+1)) - require.NoError(t, err) + return afero.Afero{Fs: afero.NewMemMapFs()} } -func mockUrlDynakubeMetadata(t *testing.T, publisher *AppVolumePublisher) { - err := publisher.db.InsertDynakube(context.Background(), metadata.NewDynakube(testDynakubeName, testTenantUUID, testAgentVersion, "", 0)) - require.NoError(t, err) -} - -func mockSharedRuxitAgentProcConf(t *testing.T, publisher *AppVolumePublisher, content ...byte) { - file, err := publisher.fs.Create(publisher.path.AgentSharedRuxitAgentProcConf(testTenantUUID, testDynakubeName)) - defer func() { _ = file.Close() }() - require.NoError(t, err) +func getFailFs(t *testing.T) afero.Afero { + t.Helper() - if len(content) > 0 { - _, err = file.Write(content) - require.NoError(t, err) - } -} + afero.NewReadOnlyFs(getTestFs(t)) -func mockImageDynakubeMetadata(t *testing.T, publisher *AppVolumePublisher) { - err := publisher.db.InsertDynakube(context.Background(), metadata.NewDynakube(testDynakubeName, testTenantUUID, "", testImageDigest, dynakube.DefaultMaxFailedCsiMountAttempts)) - require.NoError(t, err) + return afero.Afero{Fs: afero.NewReadOnlyFs(getTestFs(t))} } -func assertReferencesForPublishedVolume(t *testing.T, publisher *AppVolumePublisher, mounter *mount.FakeMounter) { - assert.NotEmpty(t, mounter.MountPoints) +func getTestVolumeConfig(t *testing.T) csivolumes.VolumeConfig { + t.Helper() - volume, err := publisher.loadVolume(context.Background(), testVolumeId) - require.NoError(t, err) - assert.Equal(t, testVolumeId, volume.VolumeID) - assert.Equal(t, testPodUID, volume.PodName) - assert.Equal(t, testAgentVersion, volume.Version) - assert.Equal(t, testTenantUUID, volume.TenantUUID) -} - -func assertReferencesForPublishedVolumeWithCodeModulesImage(t *testing.T, publisher *AppVolumePublisher, mounter *mount.FakeMounter) { - assert.NotEmpty(t, mounter.MountPoints) - - volume, err := publisher.loadVolume(context.Background(), testVolumeId) - require.NoError(t, err) - assert.Equal(t, testVolumeId, volume.VolumeID) - assert.Equal(t, testPodUID, volume.PodName) - assert.Equal(t, testImageDigest, volume.Version) - assert.Equal(t, testTenantUUID, volume.TenantUUID) -} - -func assertNoReferencesForUnpublishedVolume(t *testing.T, publisher *AppVolumePublisher) { - volume, err := publisher.loadVolume(context.Background(), testVolumeId) - require.NoError(t, err) - require.Nil(t, volume) -} - -func resetMetrics() { - agentsVersionsMetric.DeleteLabelValues(testAgentVersion) - agentsVersionsMetric.DeleteLabelValues(testImageDigest) -} - -func createTestVolumeConfig() *csivolumes.VolumeConfig { - return &csivolumes.VolumeConfig{ - VolumeInfo: *createTestVolumeInfo(), - PodName: testPodUID, + return csivolumes.VolumeConfig{ + VolumeInfo: csivolumes.VolumeInfo{ + VolumeID: "test-id", + TargetPath: "test/path", + }, + PodName: "test-pod", Mode: Mode, - DynakubeName: testDynakubeName, - } -} - -func createTestVolumeInfo() *csivolumes.VolumeInfo { - return &csivolumes.VolumeInfo{ - VolumeID: testVolumeId, - TargetPath: testTargetPath, + DynakubeName: "test-dk", + RetryTimeout: time.Minute, } } diff --git a/pkg/controllers/csi/driver/volumes/bind_config.go b/pkg/controllers/csi/driver/volumes/bind_config.go deleted file mode 100644 index 50762eb65c..0000000000 --- a/pkg/controllers/csi/driver/volumes/bind_config.go +++ /dev/null @@ -1,50 +0,0 @@ -package csivolumes - -import ( - "context" - "fmt" - - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -type BindConfig struct { - TenantUUID string - Version string - ImageDigest string - DynakubeName string - MaxMountAttempts int -} - -func NewBindConfig(ctx context.Context, access metadata.Access, volumeCfg *VolumeConfig) (*BindConfig, error) { - dynakube, err := access.GetDynakube(ctx, volumeCfg.DynakubeName) - if err != nil { - return nil, status.Error(codes.Unavailable, fmt.Sprintf("failed to extract tenant for DynaKube %s: %s", volumeCfg.DynakubeName, err.Error())) - } - - if dynakube == nil { - return nil, status.Error(codes.Unavailable, fmt.Sprintf("dynakube (%s) is missing from metadata database", volumeCfg.DynakubeName)) - } - - return &BindConfig{ - TenantUUID: dynakube.TenantUUID, - Version: dynakube.LatestVersion, - ImageDigest: dynakube.ImageDigest, - DynakubeName: dynakube.Name, - MaxMountAttempts: dynakube.MaxFailedMountAttempts, - }, nil -} - -func (cfg BindConfig) IsArchiveAvailable() bool { - return cfg.Version != "" || cfg.ImageDigest != "" -} - -func (cfg BindConfig) MetricVersionLabel() string { - versionLabel := cfg.Version - if versionLabel == "" { - versionLabel = cfg.ImageDigest - } - - return versionLabel -} diff --git a/pkg/controllers/csi/driver/volumes/bind_config_test.go b/pkg/controllers/csi/driver/volumes/bind_config_test.go deleted file mode 100644 index 8debddb242..0000000000 --- a/pkg/controllers/csi/driver/volumes/bind_config_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package csivolumes - -import ( - "context" - "testing" - - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const ( - testDynakubeName = "a-dynakube" - testTenantUUID = "a-tenant-uuid" - testAgentVersion = "1.2-3" -) - -func TestNewBindConfig(t *testing.T) { - t.Run(`no dynakube in storage`, func(t *testing.T) { - volumeCfg := &VolumeConfig{ - DynakubeName: testDynakubeName, - } - - bindCfg, err := NewBindConfig(context.TODO(), metadata.FakeMemoryDB(), volumeCfg) - - require.Error(t, err) - assert.Nil(t, bindCfg) - }) - t.Run(`create correct bind config`, func(t *testing.T) { - volumeCfg := &VolumeConfig{ - DynakubeName: testDynakubeName, - } - - db := metadata.FakeMemoryDB() - - db.InsertDynakube(context.TODO(), metadata.NewDynakube(testDynakubeName, testTenantUUID, testAgentVersion, "", 0)) - - bindCfg, err := NewBindConfig(context.TODO(), db, volumeCfg) - - expected := BindConfig{ - TenantUUID: testTenantUUID, - Version: testAgentVersion, - DynakubeName: testDynakubeName, - } - - require.NoError(t, err) - assert.NotNil(t, bindCfg) - assert.Equal(t, expected, *bindCfg) - }) -} - -func TestIsArchiveAvailable(t *testing.T) { - t.Run(`no version, no digest`, func(t *testing.T) { - bindCfg := BindConfig{} - - assert.False(t, bindCfg.IsArchiveAvailable()) - }) - t.Run(`version set, no digest`, func(t *testing.T) { - bindCfg := BindConfig{ - Version: "1.2.3", - } - - assert.True(t, bindCfg.IsArchiveAvailable()) - }) - t.Run(`no version, digest set`, func(t *testing.T) { - bindCfg := BindConfig{ - ImageDigest: "sha256:123", - } - - assert.True(t, bindCfg.IsArchiveAvailable()) - }) -} - -func TestMetricVersionLabel(t *testing.T) { - t.Run(`no version, no digest`, func(t *testing.T) { - bindCfg := BindConfig{} - - assert.Empty(t, bindCfg.MetricVersionLabel()) - }) - t.Run(`version set, no digest`, func(t *testing.T) { - bindCfg := BindConfig{ - Version: "1.2.3", - } - - assert.Equal(t, bindCfg.Version, bindCfg.MetricVersionLabel()) - }) - t.Run(`no version, digest set`, func(t *testing.T) { - bindCfg := BindConfig{ - ImageDigest: "sha256:123", - } - - assert.Equal(t, bindCfg.ImageDigest, bindCfg.MetricVersionLabel()) - }) -} diff --git a/pkg/controllers/csi/driver/volumes/host/config.go b/pkg/controllers/csi/driver/volumes/host/config.go index 7a2ea252c7..f2d46ffd5f 100644 --- a/pkg/controllers/csi/driver/volumes/host/config.go +++ b/pkg/controllers/csi/driver/volumes/host/config.go @@ -1,4 +1,4 @@ -package hostvolumes +package host import ( "github.com/Dynatrace/dynatrace-operator/pkg/logd" diff --git a/pkg/controllers/csi/driver/volumes/host/publisher.go b/pkg/controllers/csi/driver/volumes/host/publisher.go index 7be4b9245d..d7e48901d8 100644 --- a/pkg/controllers/csi/driver/volumes/host/publisher.go +++ b/pkg/controllers/csi/driver/volumes/host/publisher.go @@ -14,13 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -package hostvolumes +package host import ( "context" - "fmt" "os" - "time" csivolumes "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver/volumes" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" @@ -31,120 +29,49 @@ import ( "k8s.io/mount-utils" ) -const failedToGetOsAgentVolumePrefix = "failed to get osagent volume info from database: " - -func NewHostVolumePublisher(fs afero.Afero, mounter mount.Interface, db metadata.Access, path metadata.PathResolver) csivolumes.Publisher { - return &HostVolumePublisher{ +func NewPublisher(fs afero.Afero, mounter mount.Interface, path metadata.PathResolver) csivolumes.Publisher { + return &Publisher{ fs: fs, mounter: mounter, - db: db, path: path, } } -// necessary for mocking, as the MounterMock will use the os package -type mountChecker func(mounter mount.Interface, file string) (bool, error) - -type HostVolumePublisher struct { - fs afero.Afero - mounter mount.Interface - db metadata.Access - isNotMounted mountChecker - path metadata.PathResolver +type Publisher struct { + fs afero.Afero + mounter mount.Interface + path metadata.PathResolver } -func (publisher *HostVolumePublisher) PublishVolume(ctx context.Context, volumeCfg *csivolumes.VolumeConfig) (*csi.NodePublishVolumeResponse, error) { - bindCfg, err := csivolumes.NewBindConfig(ctx, publisher.db, volumeCfg) - if err != nil { - return nil, err - } - - if err := publisher.mountOneAgent(bindCfg.TenantUUID, volumeCfg); err != nil { +func (pub *Publisher) PublishVolume(ctx context.Context, volumeCfg *csivolumes.VolumeConfig) (*csi.NodePublishVolumeResponse, error) { + if err := pub.mountStorageVolume(volumeCfg); err != nil { return nil, status.Error(codes.Internal, "failed to mount osagent volume: "+err.Error()) } - volume, err := publisher.db.GetOsAgentVolumeViaTenantUUID(ctx, bindCfg.TenantUUID) - if err != nil { - return nil, status.Error(codes.Internal, failedToGetOsAgentVolumePrefix+err.Error()) - } - - timestamp := time.Now() - if volume == nil { - storage := metadata.OsAgentVolume{ - VolumeID: volumeCfg.VolumeID, - TenantUUID: bindCfg.TenantUUID, - Mounted: true, - LastModified: ×tamp, - } - if err := publisher.db.InsertOsAgentVolume(ctx, &storage); err != nil { - return nil, status.Error(codes.Internal, fmt.Sprintf("failed to insert osagent volume info to database. info: %v err: %s", storage, err.Error())) - } - } else { - volume.VolumeID = volumeCfg.VolumeID - volume.Mounted = true - volume.LastModified = ×tamp - - if err := publisher.db.UpdateOsAgentVolume(ctx, volume); err != nil { - return nil, status.Error(codes.Internal, fmt.Sprintf("failed to update osagent volume info to database. info: %v err: %s", volume, err.Error())) - } - } - return &csi.NodePublishVolumeResponse{}, nil } -func (publisher *HostVolumePublisher) UnpublishVolume(ctx context.Context, volumeInfo *csivolumes.VolumeInfo) (*csi.NodeUnpublishVolumeResponse, error) { - volume, err := publisher.db.GetOsAgentVolumeViaVolumeID(ctx, volumeInfo.VolumeID) - if err != nil { - return nil, status.Error(codes.Internal, failedToGetOsAgentVolumePrefix+err.Error()) - } - - if volume == nil { - return &csi.NodeUnpublishVolumeResponse{}, nil - } - - publisher.unmountOneAgent(volumeInfo.TargetPath) - - timestamp := time.Now() - volume.Mounted = false - volume.LastModified = ×tamp +func (pub *Publisher) mountStorageVolume(volumeCfg *csivolumes.VolumeConfig) error { + oaStorageDir := pub.path.OsAgentDir(volumeCfg.DynakubeName) - if err := publisher.db.UpdateOsAgentVolume(ctx, volume); err != nil { - return nil, status.Error(codes.Internal, fmt.Sprintf("failed to update osagent volume info to database. info: %v err: %s", volume, err.Error())) - } - - log.Info("osagent volume has been unpublished", "targetPath", volumeInfo.TargetPath) - - return &csi.NodeUnpublishVolumeResponse{}, nil -} - -func (publisher *HostVolumePublisher) CanUnpublishVolume(ctx context.Context, volumeInfo *csivolumes.VolumeInfo) (bool, error) { - volume, err := publisher.db.GetOsAgentVolumeViaVolumeID(ctx, volumeInfo.VolumeID) - if err != nil { - return false, status.Error(codes.Internal, failedToGetOsAgentVolumePrefix+err.Error()) + err := pub.fs.MkdirAll(oaStorageDir, os.ModePerm) + if err != nil && !os.IsExist(err) { + return err } - return volume != nil, nil -} - -func (publisher *HostVolumePublisher) mountOneAgent(tenantUUID string, volumeCfg *csivolumes.VolumeConfig) error { - hostDir := publisher.path.OsAgentDir(tenantUUID) - _ = publisher.fs.MkdirAll(hostDir, os.ModePerm) + if err := pub.fs.MkdirAll(volumeCfg.TargetPath, os.ModePerm); err != nil { + log.Info("failed to create directory for osagent-storage mount", "directory", oaStorageDir) - if err := publisher.fs.MkdirAll(volumeCfg.TargetPath, os.ModePerm); err != nil { return err } - if err := publisher.mounter.Mount(hostDir, volumeCfg.TargetPath, "", []string{"bind"}); err != nil { - _ = publisher.mounter.Unmount(hostDir) + if err := pub.mounter.Mount(oaStorageDir, volumeCfg.TargetPath, "", []string{"bind"}); err != nil { + _ = pub.mounter.Unmount(oaStorageDir) + + log.Info("failed to mount directory for osagent-storage mount", "directory", oaStorageDir) return err } return nil } - -func (publisher *HostVolumePublisher) unmountOneAgent(targetPath string) { - if err := publisher.mounter.Unmount(targetPath); err != nil { - log.Error(err, "Unmount failed", "path", targetPath) - } -} diff --git a/pkg/controllers/csi/driver/volumes/host/publisher_test.go b/pkg/controllers/csi/driver/volumes/host/publisher_test.go index 042ca4ba22..ec23dc7b75 100644 --- a/pkg/controllers/csi/driver/volumes/host/publisher_test.go +++ b/pkg/controllers/csi/driver/volumes/host/publisher_test.go @@ -1,173 +1,80 @@ -package hostvolumes +package host import ( "context" "testing" "time" - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csivolumes "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver/volumes" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - mount "k8s.io/mount-utils" -) - -const ( - testVolumeId = "a-volume" - testTargetPath = "/path/to/container/filesystem" - testTenantUUID = "a-tenant-uuid" - testDynakubeName = "a-dynakube" + "k8s.io/mount-utils" ) func TestPublishVolume(t *testing.T) { ctx := context.Background() + path := metadata.PathResolver{} - t.Run("ready dynakube", func(t *testing.T) { + t.Run("happy path", func(t *testing.T) { + fs := getTestFs(t) mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - - mockDynakube(t, &publisher) - - response, err := publisher.PublishVolume(ctx, createTestVolumeConfig()) + volumeCfg := getTestVolumeConfig(t) + pub := NewPublisher(fs, mounter, path) + resp, err := pub.PublishVolume(ctx, &volumeCfg) require.NoError(t, err) - assert.NotNil(t, response) - assert.NotEmpty(t, mounter.MountPoints) - assertReferencesForPublishedVolume(t, &publisher, mounter) + require.NotNil(t, resp) + + expectedHostDir := path.OsAgentDir(volumeCfg.DynakubeName) + hostDirExists, _ := fs.IsDir(expectedHostDir) + assert.True(t, hostDirExists) + // mounter.IsMountPoint can't be used as it uses os.Stat + require.Len(t, mounter.MountPoints, 1) + hostMount := mounter.MountPoints[0] + assert.Equal(t, expectedHostDir, hostMount.Device) + assert.Equal(t, volumeCfg.TargetPath, hostMount.Path) }) - t.Run(`not ready dynakube`, func(t *testing.T) { - mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - mockDynakubeWithoutVersion(t, &publisher) + t.Run("sad path", func(t *testing.T) { + fs := getFailFs(t) + mounter := mount.NewFakeMounter([]mount.MountPoint{}) + volumeCfg := getTestVolumeConfig(t) - response, err := publisher.PublishVolume(ctx, createTestVolumeConfig()) + pub := NewPublisher(fs, mounter, path) - require.NoError(t, err) - assert.NotNil(t, response) - assert.NotEmpty(t, mounter.MountPoints) - assertReferencesForPublishedVolume(t, &publisher, mounter) + resp, err := pub.PublishVolume(ctx, &volumeCfg) + require.Error(t, err) + require.Nil(t, resp) }) } -func TestUnpublishVolume(t *testing.T) { - t.Run("valid metadata", func(t *testing.T) { - mounter := mount.NewFakeMounter([]mount.MountPoint{ - {Path: testTargetPath}, - }) - publisher := newPublisherForTesting(mounter) - mockPublishedvolume(t, &publisher) - - response, err := publisher.UnpublishVolume(context.Background(), createTestVolumeInfo()) +func getTestFs(t *testing.T) afero.Afero { + t.Helper() - require.NoError(t, err) - assert.NotNil(t, response) - assert.Empty(t, mounter.MountPoints) - assertReferencesForUnpublishedVolume(t, &publisher) - }) - - t.Run("invalid metadata", func(t *testing.T) { - mounter := mount.NewFakeMounter([]mount.MountPoint{ - {Path: testTargetPath}, - }) - publisher := newPublisherForTesting(mounter) - - response, err := publisher.UnpublishVolume(context.Background(), createTestVolumeInfo()) - - require.NoError(t, err) - assert.NotNil(t, response) - assert.NotEmpty(t, mounter.MountPoints) - - volume, err := publisher.db.GetOsAgentVolumeViaVolumeID(context.Background(), testVolumeId) - require.NoError(t, err) - assert.Nil(t, volume) - }) + return afero.Afero{Fs: afero.NewMemMapFs()} } -func TestNodePublishAndUnpublishVolume(t *testing.T) { - mounter := mount.NewFakeMounter([]mount.MountPoint{}) - publisher := newPublisherForTesting(mounter) - mockDynakube(t, &publisher) - - publishResponse, err := publisher.PublishVolume(context.Background(), createTestVolumeConfig()) - require.NoError(t, err) - - assert.NotNil(t, publishResponse) - assert.NotEmpty(t, mounter.MountPoints) - assertReferencesForPublishedVolume(t, &publisher, mounter) +func getFailFs(t *testing.T) afero.Afero { + t.Helper() - unpublishResponse, err := publisher.UnpublishVolume(context.Background(), createTestVolumeInfo()) + afero.NewReadOnlyFs(getTestFs(t)) - require.NoError(t, err) - assert.NotNil(t, unpublishResponse) - assert.Empty(t, mounter.MountPoints) - assertReferencesForUnpublishedVolume(t, &publisher) + return afero.Afero{Fs: afero.NewReadOnlyFs(getTestFs(t))} } -func newPublisherForTesting(mounter *mount.FakeMounter) HostVolumePublisher { - csiOptions := dtcsi.CSIOptions{RootDir: "/"} +func getTestVolumeConfig(t *testing.T) csivolumes.VolumeConfig { + t.Helper() - tmpFs := afero.NewMemMapFs() - - return HostVolumePublisher{ - fs: afero.Afero{Fs: tmpFs}, - mounter: mounter, - db: metadata.FakeMemoryDB(), - path: metadata.PathResolver{RootDir: csiOptions.RootDir}, - isNotMounted: func(mounter mount.Interface, file string) (bool, error) { - return false, nil + return csivolumes.VolumeConfig{ + VolumeInfo: csivolumes.VolumeInfo{ + VolumeID: "test-id", + TargetPath: "test/path", }, - } -} - -func mockPublishedvolume(t *testing.T, publisher *HostVolumePublisher) { - mockDynakube(t, publisher) - - now := time.Now() - err := publisher.db.InsertOsAgentVolume(context.Background(), metadata.NewOsAgentVolume(testVolumeId, testTenantUUID, true, &now)) - require.NoError(t, err) -} - -func mockDynakube(t *testing.T, publisher *HostVolumePublisher) { - err := publisher.db.InsertDynakube(context.Background(), metadata.NewDynakube(testDynakubeName, testTenantUUID, "some-version", "", 0)) - require.NoError(t, err) -} - -func mockDynakubeWithoutVersion(t *testing.T, publisher *HostVolumePublisher) { - err := publisher.db.InsertDynakube(context.Background(), metadata.NewDynakube(testDynakubeName, testTenantUUID, "", "", 0)) - require.NoError(t, err) -} - -func assertReferencesForPublishedVolume(t *testing.T, publisher *HostVolumePublisher, mounter *mount.FakeMounter) { - assert.NotEmpty(t, mounter.MountPoints) - - volume, err := publisher.db.GetOsAgentVolumeViaVolumeID(context.Background(), testVolumeId) - require.NoError(t, err) - assert.Equal(t, testVolumeId, volume.VolumeID) - assert.Equal(t, testTenantUUID, volume.TenantUUID) - assert.True(t, volume.Mounted) -} - -func assertReferencesForUnpublishedVolume(t *testing.T, publisher *HostVolumePublisher) { - volume, err := publisher.db.GetOsAgentVolumeViaVolumeID(context.Background(), testVolumeId) - require.NoError(t, err) - assert.NotNil(t, volume) - assert.False(t, volume.Mounted) -} - -func createTestVolumeConfig() *csivolumes.VolumeConfig { - return &csivolumes.VolumeConfig{ - VolumeInfo: *createTestVolumeInfo(), + PodName: "test-pod", Mode: Mode, - DynakubeName: testDynakubeName, - } -} - -func createTestVolumeInfo() *csivolumes.VolumeInfo { - return &csivolumes.VolumeInfo{ - VolumeID: testVolumeId, - TargetPath: testTargetPath, + DynakubeName: "test-dk", + RetryTimeout: time.Microsecond, // doesn't matter } } diff --git a/pkg/controllers/csi/driver/volumes/publisher.go b/pkg/controllers/csi/driver/volumes/publisher.go index 4ca9547a09..cf168df3d9 100644 --- a/pkg/controllers/csi/driver/volumes/publisher.go +++ b/pkg/controllers/csi/driver/volumes/publisher.go @@ -8,6 +8,4 @@ import ( type Publisher interface { PublishVolume(ctx context.Context, volumeCfg *VolumeConfig) (*csi.NodePublishVolumeResponse, error) - UnpublishVolume(ctx context.Context, volumeInfo *VolumeInfo) (*csi.NodeUnpublishVolumeResponse, error) - CanUnpublishVolume(ctx context.Context, volumeInfo *VolumeInfo) (bool, error) } diff --git a/pkg/controllers/csi/driver/volumes/volume_config.go b/pkg/controllers/csi/driver/volumes/volume_config.go index 0b7cf6ee34..523b466567 100644 --- a/pkg/controllers/csi/driver/volumes/volume_config.go +++ b/pkg/controllers/csi/driver/volumes/volume_config.go @@ -1,13 +1,17 @@ package csivolumes import ( + "time" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/container-storage-interface/spec/lib/go/csi" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) const ( - PodNameContextKey = "csi.storage.k8s.io/pod.name" + PodNameContextKey = "csi.storage.k8s.io/pod.name" + PodNamespaceContextKey = "csi.storage.k8s.io/pod.namespace" // CSIVolumeAttributeModeField used for identifying the origin of the NodePublishVolume request CSIVolumeAttributeModeField = "mode" @@ -25,24 +29,21 @@ type VolumeInfo struct { type VolumeConfig struct { VolumeInfo PodName string + PodNamespace string Mode string DynakubeName string + RetryTimeout time.Duration } // Transforms the NodePublishVolumeRequest into a VolumeConfig func ParseNodePublishVolumeRequest(req *csi.NodePublishVolumeRequest) (*VolumeConfig, error) { - if req.GetVolumeCapability() == nil { - return nil, status.Error(codes.InvalidArgument, "Volume capability missing in request") - } - - volID := req.GetVolumeId() - if volID == "" { - return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request") + volumeInfo, err := newVolumeInfo(req) + if err != nil { + return nil, err } - targetPath := req.GetTargetPath() - if targetPath == "" { - return nil, status.Error(codes.InvalidArgument, "Target path missing in request") + if req.GetVolumeCapability() == nil { + return nil, status.Error(codes.InvalidArgument, "Volume capability missing in request") } if req.GetVolumeCapability().GetBlock() != nil { @@ -60,32 +61,55 @@ func ParseNodePublishVolumeRequest(req *csi.NodePublishVolumeRequest) (*VolumeCo podName := volCtx[PodNameContextKey] if podName == "" { - return nil, status.Error(codes.InvalidArgument, "No Pod Name included with request") + return nil, status.Error(codes.InvalidArgument, "No Pod Name included in request") + } + + podNamespace := volCtx[PodNamespaceContextKey] + if podNamespace == "" { + return nil, status.Error(codes.InvalidArgument, "No Pod Namespace included in request") } mode := volCtx[CSIVolumeAttributeModeField] if mode == "" { - return nil, status.Error(codes.InvalidArgument, "No mode attribute included with request") + return nil, status.Error(codes.InvalidArgument, "No mode attribute included in request") } dynakubeName := volCtx[CSIVolumeAttributeDynakubeField] if dynakubeName == "" { - return nil, status.Error(codes.InvalidArgument, "No dynakube attribute included with request") + return nil, status.Error(codes.InvalidArgument, "No dynakube attribute included in request") + } + + retryTimeoutValue := volCtx[CSIVolumeAttributeRetryTimeout] + if retryTimeoutValue == "" { + retryTimeoutValue = dynakube.DefaultMaxCsiMountTimeout + } + + retryTimeout, err := time.ParseDuration(retryTimeoutValue) + if err != nil { + return nil, status.Error(codes.InvalidArgument, "The retryTimeout attribute has incorrect format") } return &VolumeConfig{ - VolumeInfo: VolumeInfo{ - VolumeID: volID, - TargetPath: targetPath, - }, + VolumeInfo: *volumeInfo, PodName: podName, + PodNamespace: podNamespace, Mode: mode, DynakubeName: dynakubeName, + RetryTimeout: retryTimeout, }, nil } // Transforms the NodeUnpublishVolumeRequest into a VolumeInfo func ParseNodeUnpublishVolumeRequest(req *csi.NodeUnpublishVolumeRequest) (*VolumeInfo, error) { + return newVolumeInfo(req) +} + +type baseRequest interface { + GetVolumeId() string + GetTargetPath() string +} + +func newVolumeInfo(req baseRequest) (*VolumeInfo, error) { volumeID := req.GetVolumeId() if volumeID == "" { return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request") diff --git a/pkg/controllers/csi/driver/volumes/volume_config_test.go b/pkg/controllers/csi/driver/volumes/volume_config_test.go index 1b4dd6f60c..f546fd9f71 100644 --- a/pkg/controllers/csi/driver/volumes/volume_config_test.go +++ b/pkg/controllers/csi/driver/volumes/volume_config_test.go @@ -9,22 +9,16 @@ import ( ) const ( - testVolumeId = "a-volume-id" - testTargetPath = "a-target-path" - testPodUID = "a-pod-uid" + testVolumeId = "a-volume-id" + testTargetPath = "a-target-path" + testPodUID = "a-pod-uid" + testNs = "a-namespace" + testDynakubeName = "a-dynakube" ) func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { - t.Run(`No volume capability`, func(t *testing.T) { - volumeCfg, err := ParseNodePublishVolumeRequest(&csi.NodePublishVolumeRequest{}) - - require.EqualError(t, err, "rpc error: code = InvalidArgument desc = Volume capability missing in request") - assert.Nil(t, volumeCfg) - }) t.Run(`No volume id`, func(t *testing.T) { - request := &csi.NodePublishVolumeRequest{ - VolumeCapability: &csi.VolumeCapability{}, - } + request := &csi.NodePublishVolumeRequest{} volumeCfg, err := ParseNodePublishVolumeRequest(request) require.EqualError(t, err, "rpc error: code = InvalidArgument desc = Volume ID missing in request") @@ -32,14 +26,22 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { }) t.Run(`No target path`, func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ - VolumeCapability: &csi.VolumeCapability{}, - VolumeId: testVolumeId, + VolumeId: testVolumeId, } volumeCfg, err := ParseNodePublishVolumeRequest(request) require.EqualError(t, err, "rpc error: code = InvalidArgument desc = Target path missing in request") assert.Nil(t, volumeCfg) }) + t.Run(`No volume capability`, func(t *testing.T) { + volumeCfg, err := ParseNodePublishVolumeRequest(&csi.NodePublishVolumeRequest{ + VolumeId: testVolumeId, + TargetPath: testTargetPath, + }) + + require.EqualError(t, err, "rpc error: code = InvalidArgument desc = Volume capability missing in request") + assert.Nil(t, volumeCfg) + }) t.Run(`Access type is of type block access`, func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeCapability: &csi.VolumeCapability{ @@ -152,6 +154,7 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { TargetPath: testTargetPath, VolumeContext: map[string]string{ PodNameContextKey: testPodUID, + PodNamespaceContextKey: testNs, CSIVolumeAttributeDynakubeField: testDynakubeName, CSIVolumeAttributeModeField: "test", }, @@ -163,6 +166,7 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { assert.Equal(t, testVolumeId, volumeCfg.VolumeID) assert.Equal(t, testTargetPath, volumeCfg.TargetPath) assert.Equal(t, testPodUID, volumeCfg.PodName) + assert.Equal(t, testNs, volumeCfg.PodNamespace) assert.Equal(t, "test", volumeCfg.Mode) assert.Equal(t, testDynakubeName, volumeCfg.DynakubeName) }) diff --git a/pkg/controllers/csi/gc/binaries.go b/pkg/controllers/csi/gc/binaries.go deleted file mode 100644 index 76f1d6fbe0..0000000000 --- a/pkg/controllers/csi/gc/binaries.go +++ /dev/null @@ -1,165 +0,0 @@ -package csigc - -import ( - "context" - "os" - "strings" - - "github.com/pkg/errors" - "github.com/spf13/afero" - mount "k8s.io/mount-utils" -) - -func (gc *CSIGarbageCollector) runBinaryGarbageCollection(ctx context.Context, tenantUUID string) error { - binDirs, err := gc.getSharedBinDirs() - if err != nil { - return err - } - - oldBinDirs, err := gc.getTenantBinDirs(tenantUUID) - if err != nil { - return err - } - - binDirs = append(binDirs, oldBinDirs...) - - binsToDelete, err := gc.collectUnusedAgentBins(ctx, binDirs, tenantUUID) - if err != nil { - return err - } - - if len(binsToDelete) == 0 { - log.Info("no shared binary dirs to delete on the node") - - return nil - } - - return gc.deleteBinDirs(binsToDelete) -} - -func (gc *CSIGarbageCollector) collectUnusedAgentBins(ctx context.Context, imageDirs []os.FileInfo, tenantUUID string) ([]string, error) { - var toDelete []string - - usedAgentVersions, err := gc.db.GetLatestVersions(ctx) - if err != nil { - log.Info("failed to get the used image versions") - - return nil, err - } - - usedAgentDigest, err := gc.db.GetUsedImageDigests(ctx) - if err != nil { - log.Info("failed to get the used image digests") - - return nil, err - } - - mountedAgentBins, err := getRelevantOverlayMounts(gc.mounter, []string{gc.path.AgentBinaryDir(tenantUUID), gc.path.AgentSharedBinaryDirBase()}) - if err != nil { - log.Info("failed to get all mounted versions") - - return nil, err - } - - for _, imageDir := range imageDirs { - agentBin := imageDir.Name() - sharedPath := gc.path.AgentSharedBinaryDirForAgent(agentBin) - tenantPath := gc.path.AgentBinaryDirForVersion(tenantUUID, agentBin) - - switch { - case usedAgentVersions[agentBin]: // versions that may not be used, but a dynakube references it - continue - case usedAgentDigest[agentBin]: // images that may not be used, but a dynakube references it - continue - } - - if !mountedAgentBins[sharedPath] { // based on mount, active shared codemodule mounts - toDelete = append(toDelete, sharedPath) - } - - if !mountedAgentBins[tenantPath] { // based on mount, active tenant codemodule mounts - toDelete = append(toDelete, tenantPath) - } - } - - return toDelete, nil -} - -func (gc *CSIGarbageCollector) deleteBinDirs(imageDirs []string) error { - for _, dir := range imageDirs { - err := gc.fs.RemoveAll(dir) - if err != nil { - log.Info("failed to delete codemodule bin dir", "dir", dir) - - return errors.WithStack(err) - } - - log.Info("deleted codemodule bin dir", "dir", dir) - } - - return nil -} - -func (gc *CSIGarbageCollector) getTenantBinDirs(tenantUUID string) ([]os.FileInfo, error) { - binPath := gc.path.AgentBinaryDir(tenantUUID) - - binDirs, err := afero.Afero{Fs: gc.fs}.ReadDir(binPath) - if os.IsNotExist(err) { - log.Info("no codemodule versions stored in deprecated path", "path", binPath) - - return nil, nil - } else if err != nil { - log.Info("failed to read codemodule versions stored in deprecated path", "path", binPath) - - return nil, errors.WithStack(err) - } - - return binDirs, nil -} - -func (gc *CSIGarbageCollector) getSharedBinDirs() ([]os.FileInfo, error) { - sharedPath := gc.path.AgentSharedBinaryDirBase() - - imageDirs, err := afero.Afero{Fs: gc.fs}.ReadDir(sharedPath) - if os.IsNotExist(err) { - log.Info("no shared codemodules stored ", "path", sharedPath) - - return nil, nil - } - - if err != nil { - log.Info("failed to read shared image directory", "path", sharedPath) - - return nil, errors.WithStack(err) - } - - return imageDirs, nil -} - -func getRelevantOverlayMounts(mounter mount.Interface, baseFolders []string) (map[string]bool, error) { - mountPoints, err := mounter.List() - if err != nil { - log.Error(err, "failed to list all mount points") - - return nil, err - } - - relevantMounts := map[string]bool{} - - for _, mountPoint := range mountPoints { - if mountPoint.Device == "overlay" { - for _, opt := range mountPoint.Opts { - for _, baseFolder := range baseFolders { - if strings.HasPrefix(opt, "lowerdir="+baseFolder) { - split := strings.Split(opt, "=") - relevantMounts[split[1]] = true - - break - } - } - } - } - } - - return relevantMounts, nil -} diff --git a/pkg/controllers/csi/gc/binaries_test.go b/pkg/controllers/csi/gc/binaries_test.go deleted file mode 100644 index dedfb527b6..0000000000 --- a/pkg/controllers/csi/gc/binaries_test.go +++ /dev/null @@ -1,171 +0,0 @@ -package csigc - -import ( - "context" - "os" - "testing" - - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - mount "k8s.io/mount-utils" -) - -const ( - testVersion = "some-version" -) - -var ( - testPathResolver = metadata.PathResolver{ - RootDir: "test", - } -) - -func TestRunBinaryGarbageCollection(t *testing.T) { - ctx := context.Background() - - t.Run("bad database", func(t *testing.T) { - testDir := testPathResolver.AgentSharedBinaryDirForAgent(testVersion) - fs := createTestDirs(t, testDir) - gc := CSIGarbageCollector{ - fs: fs, - db: &metadata.FakeFailDB{}, - path: testPathResolver, - } - err := gc.runBinaryGarbageCollection(ctx, testTenantUUID) - require.Error(t, err) - }) - t.Run("no error on empty fs", func(t *testing.T) { - gc := CSIGarbageCollector{ - fs: afero.NewMemMapFs(), - mounter: mount.NewFakeMounter(nil), - db: metadata.FakeMemoryDB(), - } - err := gc.runBinaryGarbageCollection(ctx, testTenantUUID) - require.NoError(t, err) - }) - t.Run("deletes unused", func(t *testing.T) { - testSharedDir := testPathResolver.AgentSharedBinaryDirForAgent(testVersion) - testTenantBinDir := testPathResolver.AgentBinaryDirForVersion(testTenantUUID, testVersion) - fs := createTestDirs(t, testSharedDir, testTenantBinDir) - gc := CSIGarbageCollector{ - fs: fs, - db: metadata.FakeMemoryDB(), - mounter: mount.NewFakeMounter(nil), - path: testPathResolver, - } - err := gc.runBinaryGarbageCollection(ctx, testTenantUUID) - require.NoError(t, err) - _, err = fs.Stat(testSharedDir) - require.Error(t, err) - assert.True(t, os.IsNotExist(err)) - - _, err = fs.Stat(testTenantBinDir) - require.Error(t, err) - assert.True(t, os.IsNotExist(err)) - }) - t.Run("deletes nothing, because of dynakube metadata present", func(t *testing.T) { - testDir := testPathResolver.AgentSharedBinaryDirForAgent(testVersion) - fs := createTestDirs(t, testDir) - gc := CSIGarbageCollector{ - fs: fs, - db: metadata.FakeMemoryDB(), - mounter: mount.NewFakeMounter(nil), - } - gc.db.InsertDynakube(ctx, &metadata.Dynakube{ - Name: "test", - TenantUUID: "test", - LatestVersion: "test", - ImageDigest: testVersion, - }) - - err := gc.runBinaryGarbageCollection(ctx, testTenantUUID) - require.NoError(t, err) - - _, err = fs.Stat(testDir) - require.NoError(t, err) - }) - t.Run("deletes nothing, because of volume metadata present", func(t *testing.T) { - testDir := testPathResolver.AgentSharedBinaryDirForAgent(testVersion) - fs := createTestDirs(t, testDir) - gc := CSIGarbageCollector{ - fs: fs, - db: metadata.FakeMemoryDB(), - mounter: mount.NewFakeMounter(nil), - } - gc.db.InsertVolume(ctx, &metadata.Volume{ - VolumeID: "test", - TenantUUID: "test", - Version: testVersion, - PodName: "test", - }) - - err := gc.runBinaryGarbageCollection(ctx, testTenantUUID) - require.NoError(t, err) - - _, err = fs.Stat(testDir) - require.NoError(t, err) - }) - t.Run("deletes nothing, because directory is mounted", func(t *testing.T) { - testSharedDir := testPathResolver.AgentSharedBinaryDirForAgent(testVersion) - testTenantBinDir := testPathResolver.AgentBinaryDirForVersion(testTenantUUID, testVersion) - fs := createTestDirs(t, testSharedDir, testTenantBinDir) - gc := CSIGarbageCollector{ - fs: fs, - db: metadata.FakeMemoryDB(), - mounter: mount.NewFakeMounter([]mount.MountPoint{ - { - Type: "overlay", - Opts: []string{"upperdir=beep", "lowerdir=" + testSharedDir, "workdir=boop"}, - }, - { - Type: "overlay", - Opts: []string{"lowerdir=" + testTenantBinDir, "upperdir=beep", "workdir=boop"}, - }, - }), - } - - err := gc.runBinaryGarbageCollection(ctx, testTenantUUID) - require.NoError(t, err) - - _, err = fs.Stat(testSharedDir) - require.NoError(t, err) - - _, err = fs.Stat(testTenantBinDir) - require.NoError(t, err) - }) -} - -func TestGetSharedImageDirs(t *testing.T) { - t.Run("no error on empty fs", func(t *testing.T) { - fs := afero.NewMemMapFs() - gc := CSIGarbageCollector{ - fs: fs, - path: testPathResolver, - } - dirs, err := gc.getSharedBinDirs() - require.NoError(t, err) - assert.Nil(t, dirs) - }) - t.Run("get image cache dirs", func(t *testing.T) { - testDir := testPathResolver.AgentSharedBinaryDirForAgent(testVersion) - fs := createTestDirs(t, testDir) - gc := CSIGarbageCollector{ - fs: fs, - path: testPathResolver, - } - dirs, err := gc.getSharedBinDirs() - require.NoError(t, err) - assert.Len(t, dirs, 1) - }) -} - -func createTestDirs(t *testing.T, paths ...string) afero.Fs { - fs := afero.NewMemMapFs() - for _, path := range paths { - require.NoError(t, fs.MkdirAll(path, 0755)) - } - - return fs -} diff --git a/pkg/controllers/csi/gc/config.go b/pkg/controllers/csi/gc/config.go deleted file mode 100644 index e530420989..0000000000 --- a/pkg/controllers/csi/gc/config.go +++ /dev/null @@ -1,38 +0,0 @@ -package csigc - -import ( - "github.com/Dynatrace/dynatrace-operator/pkg/logd" - "github.com/prometheus/client_golang/prometheus" - "sigs.k8s.io/controller-runtime/pkg/metrics" -) - -var ( - log = logd.Get().WithName("csi-gc") - - reclaimedMemoryMetric = prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "dynatrace", - Subsystem: "csi_driver", - Name: "gc_reclaimed", - Help: "Amount of memory reclaimed by the GC", - }) - - foldersRemovedMetric = prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "dynatrace", - Subsystem: "csi_driver", - Name: "gc_folder_rmv", - Help: "Number of folders deleted by the GC", - }) - - gcRunsMetric = prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "dynatrace", - Subsystem: "csi_driver", - Name: "gc_runs", - Help: "Number of GC runs", - }) -) - -func init() { - metrics.Registry.MustRegister(reclaimedMemoryMetric) - metrics.Registry.MustRegister(foldersRemovedMetric) - metrics.Registry.MustRegister(gcRunsMetric) -} diff --git a/pkg/controllers/csi/gc/reconciler.go b/pkg/controllers/csi/gc/reconciler.go deleted file mode 100644 index 5e549d4366..0000000000 --- a/pkg/controllers/csi/gc/reconciler.go +++ /dev/null @@ -1,107 +0,0 @@ -package csigc - -import ( - "context" - "os" - "time" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/pkg/errors" - "github.com/spf13/afero" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/mount-utils" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" -) - -// CSIGarbageCollector removes unused and outdated agent versions -type CSIGarbageCollector struct { - apiReader client.Reader - fs afero.Fs - db metadata.Access - mounter mount.Interface - - path metadata.PathResolver - - maxUnmountedVolumeAge time.Duration -} - -var _ reconcile.Reconciler = (*CSIGarbageCollector)(nil) - -// NewCSIGarbageCollector returns a new CSIGarbageCollector -func NewCSIGarbageCollector(apiReader client.Reader, opts dtcsi.CSIOptions, db metadata.Access) *CSIGarbageCollector { - mounter := mount.New("") - - return &CSIGarbageCollector{ - apiReader: apiReader, - fs: afero.NewOsFs(), - db: db, - path: metadata.PathResolver{RootDir: opts.RootDir}, - mounter: mounter, - maxUnmountedVolumeAge: determineMaxUnmountedVolumeAge(os.Getenv(maxUnmountedCsiVolumeAgeEnv)), - } -} - -func (gc *CSIGarbageCollector) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { - log.Info("running OneAgent garbage collection", "namespace", request.Namespace, "name", request.Name) - - defaultReconcileResult := reconcile.Result{} - - dynakube, err := getDynakubeFromRequest(ctx, gc.apiReader, request) - if err != nil { - return defaultReconcileResult, err - } - - if dynakube == nil { - return defaultReconcileResult, nil - } - - if !dynakube.OneAgent().IsAppInjectionNeeded() { - log.Info("app injection not enabled, skip garbage collection", "dynakube", dynakube.Name) - - return defaultReconcileResult, nil - } - - tenantUUID, err := dynakube.TenantUUIDFromApiUrl() - if err != nil { - log.Info("failed to get tenantUUID of DynaKube, checking later") - - return defaultReconcileResult, err - } - - log.Info("running log garbage collection") - gc.runUnmountedVolumeGarbageCollection(tenantUUID) - - if err := ctx.Err(); err != nil { - return defaultReconcileResult, err - } - - log.Info("running binary garbage collection") - - if err := gc.runBinaryGarbageCollection(ctx, tenantUUID); err != nil { - log.Info("failed to garbage collect the shared images") - - return defaultReconcileResult, err - } - - return defaultReconcileResult, nil -} - -func getDynakubeFromRequest(ctx context.Context, apiReader client.Reader, request reconcile.Request) (*dynakube.DynaKube, error) { - var dk dynakube.DynaKube - if err := apiReader.Get(ctx, request.NamespacedName, &dk); err != nil { - if k8serrors.IsNotFound(err) { - log.Info("given DynaKube object not found") - - return nil, nil //nolint:nilnil - } - - log.Info("failed to get DynaKube object") - - return nil, errors.WithStack(err) - } - - return &dk, nil -} diff --git a/pkg/controllers/csi/gc/reconciler_test.go b/pkg/controllers/csi/gc/reconciler_test.go deleted file mode 100644 index ee90537589..0000000000 --- a/pkg/controllers/csi/gc/reconciler_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package csigc - -import ( - "context" - "fmt" - "testing" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/reconcile" -) - -func TestReconcile(t *testing.T) { - tenantUUID := "testTenant" - apiUrl := fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", tenantUUID) - namespace := "test-namespace" - - t.Run(`no latest version in status`, func(t *testing.T) { - dk := dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: apiUrl, - }, - } - gc := CSIGarbageCollector{ - apiReader: fake.NewClient(&dk), - fs: afero.NewMemMapFs(), - db: metadata.FakeMemoryDB(), - } - result, err := gc.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: dk.Name}}) - - require.NoError(t, err) - assert.Equal(t, reconcile.Result{}, result) - }) -} diff --git a/pkg/controllers/csi/gc/unmounted.go b/pkg/controllers/csi/gc/unmounted.go deleted file mode 100644 index 9696add7eb..0000000000 --- a/pkg/controllers/csi/gc/unmounted.go +++ /dev/null @@ -1,97 +0,0 @@ -package csigc - -import ( - "os" - "strconv" - "time" - - "github.com/spf13/afero" -) - -const ( - defaultMaxUnmountedCsiVolumeAge = 7 * 24 * time.Hour - maxUnmountedCsiVolumeAgeEnv = "MAX_UNMOUNTED_VOLUME_AGE" -) - -func (gc *CSIGarbageCollector) runUnmountedVolumeGarbageCollection(tenantUUID string) { - unmountedVolumes, err := gc.getUnmountedVolumes(tenantUUID) - if err != nil { - log.Info("failed to get unmounted volume information", "error", err) - - return - } - - gc.removeUnmountedVolumesIfNecessary(unmountedVolumes, tenantUUID) -} - -func (gc *CSIGarbageCollector) getUnmountedVolumes(tenantUUID string) ([]os.FileInfo, error) { - var unusedVolumeIDs []os.FileInfo - - mountsDirectoryPath := gc.path.AgentRunDir(tenantUUID) - - volumeIDs, err := afero.ReadDir(gc.fs, mountsDirectoryPath) - if err != nil { - if os.IsNotExist(err) { - log.Info("no mount directories found for this tenant, moving on", "tenantUUID", tenantUUID, "path", mountsDirectoryPath) - - return nil, nil - } - - return nil, err - } - - for _, volumeID := range volumeIDs { - mappedDir := gc.path.OverlayMappedDir(tenantUUID, volumeID.Name()) - isUnused, err := afero.IsEmpty(gc.fs, mappedDir) - - if err != nil { - log.Info("failed to check if directory is empty, skipping", "folder", mappedDir, "error", err) - - continue - } - - if isUnused { - unusedVolumeIDs = append(unusedVolumeIDs, volumeID) - } - } - - return unusedVolumeIDs, nil -} - -func (gc *CSIGarbageCollector) removeUnmountedVolumesIfNecessary(unusedVolumeIDs []os.FileInfo, tenantUUID string) { - for _, unusedVolumeID := range unusedVolumeIDs { - if gc.isUnmountedVolumeTooOld(unusedVolumeID.ModTime()) { - err := gc.fs.RemoveAll(gc.path.AgentRunDirForVolume(tenantUUID, unusedVolumeID.Name())) - if err != nil { - log.Info("failed to remove logs for pod", "podUID", unusedVolumeID.Name(), "error", err) - } - } - } -} - -func (gc *CSIGarbageCollector) isUnmountedVolumeTooOld(t time.Time) bool { - return gc.maxUnmountedVolumeAge == 0 || time.Since(t) > gc.maxUnmountedVolumeAge -} - -func determineMaxUnmountedVolumeAge(maxAgeEnvValue string) time.Duration { - if maxAgeEnvValue == "" { - return defaultMaxUnmountedCsiVolumeAge - } - - maxAge, err := strconv.Atoi(maxAgeEnvValue) - if err != nil { - log.Error(err, "failed to parse MaxUnmountedCsiVolumeAge from", "env", maxUnmountedCsiVolumeAgeEnv, "value", maxAgeEnvValue) - - return defaultMaxUnmountedCsiVolumeAge - } - - if maxAge <= 0 { - log.Info("max unmounted csi volume age is set to 0, files will be deleted immediately") - - return 0 - } - - log.Info("max unmounted csi volume age used", "age in days", maxAge) - - return 24 * time.Duration(maxAge) * time.Hour -} diff --git a/pkg/controllers/csi/gc/unmounted_test.go b/pkg/controllers/csi/gc/unmounted_test.go deleted file mode 100644 index 4cef241376..0000000000 --- a/pkg/controllers/csi/gc/unmounted_test.go +++ /dev/null @@ -1,184 +0,0 @@ -package csigc - -import ( - "os" - "path/filepath" - "testing" - "time" - - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - mount "k8s.io/mount-utils" -) - -const ( - testRootDir = "root-dir" - testTenantUUID = "tenant-12" - - testVersion1 = "v1" - testVersion2 = "v2" - testVersion3 = "v3" -) - -var ( - testVolumeFolderPath = filepath.Join(testRootDir, testTenantUUID, "run") -) - -func TestGetUnmountedVolumes(t *testing.T) { - t.Run("no error if no volumes are present", func(t *testing.T) { - gc := NewMockGarbageCollector() - _ = gc.fs.MkdirAll(testVolumeFolderPath, 0770) - - unmountedVolumes, err := gc.getUnmountedVolumes(testTenantUUID) - - require.NoError(t, err) - assert.Equal(t, []os.FileInfo(nil), unmountedVolumes) - }) - t.Run("mounted volumes are not collected", func(t *testing.T) { - gc := NewMockGarbageCollector() - gc.mockMountedVolumeIDPath(testVersion1) - - unmountedVolumes, err := gc.getUnmountedVolumes(testTenantUUID) - - require.NoError(t, err) - assert.Equal(t, []os.FileInfo(nil), unmountedVolumes) - }) - t.Run("unmounted volumes are collected", func(t *testing.T) { - gc := NewMockGarbageCollector() - gc.mockUnmountedVolumeIDPath(testVersion1) - - unmountedVolumes, err := gc.getUnmountedVolumes(testTenantUUID) - - require.NoError(t, err) - assert.Equal(t, testVersion1, unmountedVolumes[0].Name()) - }) - t.Run("multiple unmounted volumes are collected", func(t *testing.T) { - gc := NewMockGarbageCollector() - gc.mockUnmountedVolumeIDPath(testVersion1, testVersion2, testVersion3) - - unmountedVolumes, err := gc.getUnmountedVolumes(testTenantUUID) - - require.NoError(t, err) - require.Len(t, unmountedVolumes, 3) - assert.Equal(t, testVersion1, unmountedVolumes[0].Name()) - assert.Equal(t, testVersion2, unmountedVolumes[1].Name()) - assert.Equal(t, testVersion3, unmountedVolumes[2].Name()) - }) - t.Run("multiple unmounted volumes are collected while mounted volume is present", func(t *testing.T) { - gc := NewMockGarbageCollector() - gc.mockMountedVolumeIDPath(testVersion3) - gc.mockUnmountedVolumeIDPath(testVersion1, testVersion2) - - unmountedVolumes, err := gc.getUnmountedVolumes(testTenantUUID) - - require.NoError(t, err) - require.Len(t, unmountedVolumes, 2) - assert.Equal(t, testVersion1, unmountedVolumes[0].Name()) - assert.Equal(t, testVersion2, unmountedVolumes[1].Name()) - }) -} - -func TestIsUnmountedVolumeTooOld(t *testing.T) { - t.Run("default is false for current timestamp", func(t *testing.T) { - gc := CSIGarbageCollector{ - maxUnmountedVolumeAge: defaultMaxUnmountedCsiVolumeAge, - } - - isOlder := gc.isUnmountedVolumeTooOld(time.Now()) - - assert.False(t, isOlder) - }) - - t.Run("default is true for timestamp 14 days in past", func(t *testing.T) { - gc := CSIGarbageCollector{ - maxUnmountedVolumeAge: defaultMaxUnmountedCsiVolumeAge, - } - - isOlder := gc.isUnmountedVolumeTooOld(time.Now().AddDate(0, 0, -15)) - - assert.True(t, isOlder) - }) - - t.Run("is true if maxUnmountedCsiVolumeAge == 0", func(t *testing.T) { - gc := CSIGarbageCollector{ - maxUnmountedVolumeAge: 0, - } - - isOlder := gc.isUnmountedVolumeTooOld(time.Now().AddDate(0, 0, 15)) - - assert.True(t, isOlder) - }) -} - -func TestRemoveUnmountedVolumesIfNecessary(t *testing.T) { - t.Run("remove only too old unmounted volume", func(t *testing.T) { - gc := NewMockGarbageCollector() - gc.mockUnmountedVolumeIDPath(testVersion1, testVersion2, testVersion3) - - unmountedVolumes, err := gc.getUnmountedVolumes(testTenantUUID) - require.NoError(t, err) - require.NotNil(t, unmountedVolumes) - - oldVolume := unmountedVolumes[0] - err = gc.fs.Chtimes(filepath.Join(testVolumeFolderPath, oldVolume.Name()), oldVolume.ModTime(), oldVolume.ModTime().AddDate(0, 0, -15)) - require.NoError(t, err) - - older := gc.isUnmountedVolumeTooOld(oldVolume.ModTime()) - require.True(t, older) - - gc.removeUnmountedVolumesIfNecessary(unmountedVolumes, testTenantUUID) - oldVolumeExists, err := afero.DirExists(gc.fs, filepath.Join(testVolumeFolderPath, oldVolume.Name())) - require.NoError(t, err) - assert.False(t, oldVolumeExists) - - for _, remainingVolume := range unmountedVolumes[1:] { - volumeExists, err := afero.DirExists(gc.fs, filepath.Join(testVolumeFolderPath, remainingVolume.Name())) - require.NoError(t, err) - assert.True(t, volumeExists) - } - }) -} - -func TestDetermineMaxUnmountedVolumeAge(t *testing.T) { - t.Run("no env set ==> use default", func(t *testing.T) { - maxVolumeAge := determineMaxUnmountedVolumeAge("") - - assert.Equal(t, defaultMaxUnmountedCsiVolumeAge, maxVolumeAge) - }) - - t.Run("use (short) duration from env", func(t *testing.T) { - maxVolumeAge := determineMaxUnmountedVolumeAge("1") - - assert.Equal(t, time.Hour*24, maxVolumeAge) - }) - - t.Run("negative duration in env => use 0", func(t *testing.T) { - maxVolumeAge := determineMaxUnmountedVolumeAge("-1") - - assert.Equal(t, time.Duration(0), maxVolumeAge) - }) -} - -func (gc *CSIGarbageCollector) mockMountedVolumeIDPath(volumeIDs ...string) { - for _, volumeID := range volumeIDs { - _ = gc.fs.MkdirAll(filepath.Join(testVolumeFolderPath, volumeID, "mapped", "something"), os.ModePerm) - } -} - -func (gc *CSIGarbageCollector) mockUnmountedVolumeIDPath(volumeIDs ...string) { - for _, volumeID := range volumeIDs { - _ = gc.fs.MkdirAll(filepath.Join(testVolumeFolderPath, volumeID, "mapped"), os.ModePerm) - } -} - -func NewMockGarbageCollector(mountPoints ...mount.MountPoint) *CSIGarbageCollector { - return &CSIGarbageCollector{ - fs: afero.NewMemMapFs(), - db: metadata.FakeMemoryDB(), - path: metadata.PathResolver{RootDir: testRootDir}, - mounter: mount.NewFakeMounter(mountPoints), - maxUnmountedVolumeAge: defaultMaxUnmountedCsiVolumeAge, - } -} diff --git a/pkg/controllers/csi/metadata/correctness.go b/pkg/controllers/csi/metadata/correctness.go index 19dd50e547..6e5b50f194 100644 --- a/pkg/controllers/csi/metadata/correctness.go +++ b/pkg/controllers/csi/metadata/correctness.go @@ -4,29 +4,37 @@ import ( "context" "os" "path/filepath" + "strings" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - "github.com/pkg/errors" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/symlink" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/spf13/afero" - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/mount-utils" "sigs.k8s.io/controller-runtime/pkg/client" ) type CorrectnessChecker struct { + fs afero.Afero apiReader client.Reader - fs afero.Fs - access Access + mounter mount.Interface path PathResolver } -func NewCorrectnessChecker(cl client.Reader, access Access, opts dtcsi.CSIOptions) *CorrectnessChecker { +type OverlayMount struct { + Path string + LowerDir string + UpperDir string + WorkDir string +} + +func NewCorrectnessChecker(apiReader client.Reader, opts dtcsi.CSIOptions) *CorrectnessChecker { return &CorrectnessChecker{ - apiReader: cl, - fs: afero.NewOsFs(), + apiReader: apiReader, + fs: afero.Afero{Fs: afero.NewOsFs()}, + mounter: mount.New(""), path: PathResolver{RootDir: opts.RootDir}, - access: access, } } @@ -34,180 +42,154 @@ func NewCorrectnessChecker(cl client.Reader, access Access, opts dtcsi.CSIOption // Removes not valid entries // "Moves" agent bins from deprecated location. (just creates a symlink) func (checker *CorrectnessChecker) CorrectCSI(ctx context.Context) error { - defer LogAccessOverview(checker.access) - - if err := checker.removeVolumesForMissingPods(ctx); err != nil { - return err - } - - if err := checker.removeMissingDynakubes(ctx); err != nil { - return err - } - - if err := checker.copyCodeModulesFromDeprecatedBin(ctx); err != nil { - return err - } - - checker.migrateAppMounts(ctx) + checker.migrateAppMounts() + checker.migrateHostMounts(ctx) return nil } -// Removes volume entries if their pod is no longer exists -func (checker *CorrectnessChecker) removeVolumesForMissingPods(ctx context.Context) error { - if checker.apiReader == nil { - log.Info("no kubernetes client configured, skipping orphaned volume metadata cleanup") - - return nil - } +func (checker *CorrectnessChecker) migrateAppMounts() { + baseDir := checker.path.RootDir - podNames, err := checker.access.GetPodNames(ctx) + appMounts, err := GetRelevantOverlayMounts(checker.mounter, baseDir) if err != nil { - return err + log.Error(err, "failed to get relevant overlay mounts") } - pruned := []string{} + oldAppMounts := []OverlayMount{} - for podName := range podNames { - var pod corev1.Pod - if err := checker.apiReader.Get(ctx, client.ObjectKey{Name: podName}, &pod); !k8serrors.IsNotFound(err) { - continue + for _, appMount := range appMounts { + if !strings.HasPrefix(appMount.Path, checker.path.AppMountsBaseDir()) { + oldAppMounts = append(oldAppMounts, appMount) } - - volumeID := podNames[podName] - if err := checker.access.DeleteVolume(ctx, volumeID); err != nil { - return err - } - - pruned = append(pruned, volumeID+"|"+podName) } - log.Info("CSI volumes database is corrected for missing pods (volume|pod)", "prunedRows", pruned) + checker.fs.MkdirAll(checker.path.AppMountsBaseDir(), os.ModePerm) - return nil -} - -// Removes dynakube entries if their Dynakube instance no longer exists in the cluster -func (checker *CorrectnessChecker) removeMissingDynakubes(ctx context.Context) error { - if checker.apiReader == nil { - log.Info("no kubernetes client configured, skipping orphaned dynakube metadata cleanup") - - return nil - } - - dynakubes, err := checker.access.GetTenantsToDynakubes(ctx) - if err != nil { - return err - } + for _, appMount := range oldAppMounts { + oldPath := filepath.Dir(appMount.Path) + volumeID := filepath.Base(oldPath) + newPath := checker.path.AppMountForID(volumeID) - pruned := []string{} - - for dynakubeName := range dynakubes { - var dk dynakube.DynaKube - if err := checker.apiReader.Get(ctx, client.ObjectKey{Name: dynakubeName}, &dk); !k8serrors.IsNotFound(err) { + exists, _ := checker.fs.DirExists(newPath) + if exists { continue } - if err := checker.access.DeleteDynakube(ctx, dynakubeName); err != nil { - return err + err := symlink.Create(checker.fs.Fs, oldPath, newPath) + if err != nil { + log.Error(err, "failed to symlink old app mount to new location", "old-path", oldPath, "new-path", newPath) + } else { + log.Info("migrated old app mount to new location", "old-path", oldPath, "new-path", newPath) } - - tenantUUID := dynakubes[dynakubeName] - pruned = append(pruned, tenantUUID+"|"+dynakubeName) } - - log.Info("CSI tenants database is corrected for missing dynakubes (tenant|dynakube)", "prunedRows", pruned) - - return nil } -func (checker *CorrectnessChecker) copyCodeModulesFromDeprecatedBin(ctx context.Context) error { - dynakubes, err := checker.access.GetAllDynakubes(ctx) +func (checker *CorrectnessChecker) migrateHostMounts(ctx context.Context) { + dks, err := GetRelevantDynaKubes(ctx, checker.apiReader) if err != nil { - return err - } + log.Error(err, "failed to list the available dynakubes, skipping host mount migration") - moved := []string{} + return + } - for _, dynakube := range dynakubes { - if dynakube.TenantUUID == "" || dynakube.LatestVersion == "" { + for _, dk := range dks { + if !dk.OneAgent().IsReadOnlyOneAgentsMode() { continue } - deprecatedBin := checker.path.AgentBinaryDirForVersion(dynakube.TenantUUID, dynakube.LatestVersion) - currentBin := checker.path.AgentSharedBinaryDirForAgent(dynakube.LatestVersion) + checker.fs.MkdirAll(checker.path.DynaKubeDir(dk.Name), os.ModePerm) - linked, err := checker.safelyLinkCodeModule(deprecatedBin, currentBin) - if err != nil { - return err - } + newPath := checker.path.OsAgentDir(dk.Name) - if linked { - moved = append(moved, dynakube.TenantUUID+"|"+dynakube.LatestVersion) + newExists, _ := checker.fs.DirExists(newPath) + if newExists { + continue } - } - - log.Info("CSI filesystem corrected, linked deprecated agent binary to current location (tenant|version-bin)", "movedBins", moved) - return nil -} - -func (checker *CorrectnessChecker) safelyLinkCodeModule(deprecatedBin, currentBin string) (bool, error) { - if folderExists(checker.fs, deprecatedBin) && !folderExists(checker.fs, currentBin) { - log.Info("linking codemodule from deprecated location", "path", deprecatedBin) - // MemMapFs (used for testing) doesn't comply with the Linker interface - linker, ok := checker.fs.(afero.Linker) - if !ok { - log.Info("symlinking not possible", "path", deprecatedBin) + tenantUUID, err := TenantUUIDFromApiUrl(dk.ApiUrl()) + if err != nil { + log.Error(err, "malformed ApiUrl for dynakube, skipping host dir migration for it", "dk", dk.Name, "apiUrl", dk.ApiUrl()) - return false, nil + continue } - err := checker.fs.MkdirAll(filepath.Dir(currentBin), 0755) + oldPath := checker.path.OsAgentDir(tenantUUID) + + oldExists, err := checker.fs.DirExists(oldPath) if err != nil { - log.Info("failed to create parent dir for new path", "path", currentBin) + log.Error(err, "failed to check deprecated host dir existence, skipping host dir migration for it", "dk", dk.Name, "apiUrl", dk.ApiUrl()) - return false, errors.WithStack(err) + continue } - log.Info("creating symlink", "from", deprecatedBin, "to", currentBin) - - if err := linker.SymlinkIfPossible(deprecatedBin, currentBin); err != nil { - log.Info("symlinking failed", "path", deprecatedBin) - - return false, errors.WithStack(err) + if !oldExists { + continue } - return true, nil + err = symlink.Create(checker.fs.Fs, oldPath, newPath) + if err != nil { + log.Error(err, "failed to symlink old host mount to new location", "old-path", oldPath, "new-path", newPath) + } else { + log.Info("migrated old host mount to new location", "old-path", oldPath, "new-path", newPath) + } } - - return false, nil } -func (checker *CorrectnessChecker) migrateAppMounts(ctx context.Context) { - volumes := checker.access.GetAllAppMounts(ctx) +func GetRelevantDynaKubes(ctx context.Context, apiReader client.Reader) ([]dynakube.DynaKube, error) { + var dkList dynakube.DynaKubeList - for _, volume := range volumes { - err := checker.access.InsertVolume(ctx, volume) - if err != nil { - log.Info("failed to insert volume", "id", volume.VolumeID, "error", err) + err := apiReader.List(ctx, &dkList, client.InNamespace(env.DefaultNamespace())) + if err != nil { + return nil, err + } - continue - } + var relevantDks []dynakube.DynaKube - // we need to prevent filling the DB with entries if the CSI Pod is restarted - err = checker.access.DeleteAppMount(ctx, volume.VolumeID) - if err != nil { - log.Info("failed to delete app_mount entry", "id", volume.VolumeID, "error", err) + for _, dk := range dkList.Items { + if dk.OneAgent().IsAppInjectionNeeded() || dk.OneAgent().IsReadOnlyOneAgentsMode() { + relevantDks = append(relevantDks, dk) } } + + return relevantDks, nil } -func folderExists(fs afero.Fs, filename string) bool { - info, err := fs.Stat(filename) - if os.IsNotExist(err) { - return false +func GetRelevantOverlayMounts(mounter mount.Interface, baseFolder string) ([]OverlayMount, error) { + mountPoints, err := mounter.List() + if err != nil { + return nil, err + } + + relevantMounts := []OverlayMount{} + + for _, mountPoint := range mountPoints { + if mountPoint.Device == "overlay" { + if !strings.HasPrefix(mountPoint.Path, baseFolder) { + continue + } + + overlayMount := OverlayMount{ + Path: mountPoint.Path, + } + + for _, opt := range mountPoint.Opts { + switch { + case strings.HasPrefix(opt, "lowerdir="): + split := strings.Split(opt, "=") + overlayMount.LowerDir = split[1] + case strings.HasPrefix(opt, "upperdir="): + split := strings.Split(opt, "=") + overlayMount.UpperDir = split[1] + case strings.HasPrefix(opt, "workdir="): + split := strings.Split(opt, "=") + overlayMount.WorkDir = split[1] + } + } + + relevantMounts = append(relevantMounts, overlayMount) + } } - return info.IsDir() + return relevantMounts, nil } diff --git a/pkg/controllers/csi/metadata/correctness_test.go b/pkg/controllers/csi/metadata/correctness_test.go index a833469daf..aeb200c339 100644 --- a/pkg/controllers/csi/metadata/correctness_test.go +++ b/pkg/controllers/csi/metadata/correctness_test.go @@ -1,163 +1,90 @@ package metadata import ( - "context" - "fmt" - "strconv" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/mount-utils" ) -func createTestDynakube(index int) Dynakube { - return Dynakube{ - TenantUUID: fmt.Sprintf("asc%d", index), - LatestVersion: strconv.Itoa(123 * index), - Name: fmt.Sprintf("dk%d", index), - ImageDigest: fmt.Sprintf("sha256:%d", 123*index), - MaxFailedMountAttempts: index, - } -} - -func createTestVolume(index int) Volume { - return Volume{ - VolumeID: fmt.Sprintf("vol-%d", index), - PodName: fmt.Sprintf("pod%d", index), - Version: createTestDynakube(index).LatestVersion, - TenantUUID: createTestDynakube(index).TenantUUID, - MountAttempts: index, - } -} - -func TestCorrectCSI(t *testing.T) { - t.Run("error on no db or missing tables", func(t *testing.T) { - db := emptyMemoryDB() - - checker := NewCorrectnessChecker(nil, db, dtcsi.CSIOptions{}) - - err := checker.CorrectCSI(context.TODO()) - - require.Error(t, err) +func TestGetRelevantOverlayMounts(t *testing.T) { + t.Run("get only relevant mounts", func(t *testing.T) { + baseFolder := "/test/folder" + expectedPath := baseFolder + "/some/sub/folder" + expectedLowerDir := "/test/lower" + expectedUpperDir := "/test/upper" + expectedWorkDir := "/test/work" + + relevantMountPoint := mount.MountPoint{ + Device: "overlay", + Path: expectedPath, + Type: "overlay", + Opts: []string{ + "lowerdir=" + expectedLowerDir, + "upperdir=" + expectedUpperDir, + "workdir=" + expectedWorkDir, + }, + } + + mounter := mount.NewFakeMounter([]mount.MountPoint{ + relevantMountPoint, + { + Device: "not-relevant-mount-type", + }, + { + Device: "overlay", + Path: "not-relevant-overlay-mount", + Type: "overlay", + }, + }) + + mounts, err := GetRelevantOverlayMounts(mounter, baseFolder) + require.NoError(t, err) + require.NotNil(t, mounts) + require.Len(t, mounts, 1) + assert.Equal(t, expectedPath, mounts[0].Path) + assert.Equal(t, expectedLowerDir, mounts[0].LowerDir) + assert.Equal(t, expectedUpperDir, mounts[0].UpperDir) + assert.Equal(t, expectedWorkDir, mounts[0].WorkDir) }) - t.Run("no error on empty db", func(t *testing.T) { - db := FakeMemoryDB() - - checker := NewCorrectnessChecker(nil, db, dtcsi.CSIOptions{}) - - err := checker.CorrectCSI(context.TODO()) + t.Run("works with no mount points", func(t *testing.T) { + mounter := mount.NewFakeMounter([]mount.MountPoint{}) + mounts, err := GetRelevantOverlayMounts(mounter, "") require.NoError(t, err) + require.NotNil(t, mounts) + require.Empty(t, mounts) }) - t.Run("no error on nil apiReader, database is not cleaned", func(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - testDynakube1 := createTestDynakube(1) - db := FakeMemoryDB() - db.InsertVolume(ctx, &testVolume1) - db.InsertDynakube(ctx, &testDynakube1) - - checker := NewCorrectnessChecker(nil, db, dtcsi.CSIOptions{}) - - err := checker.CorrectCSI(context.TODO()) - - require.NoError(t, err) - vol, err := db.GetVolume(ctx, testVolume1.VolumeID) - require.NoError(t, err) - assert.Equal(t, &testVolume1, vol) - - require.NoError(t, err) - dk, err := db.GetDynakube(ctx, testDynakube1.Name) - require.NoError(t, err) - assert.Equal(t, &testDynakube1, dk) - }) - - t.Run("nothing to remove, everything is still correct", func(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - testDynakube1 := createTestDynakube(1) - db := FakeMemoryDB() - db.InsertVolume(ctx, &testVolume1) - db.InsertDynakube(ctx, &testDynakube1) - client := fake.NewClient( - &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: testVolume1.PodName}}, - &dynakube.DynaKube{ObjectMeta: metav1.ObjectMeta{Name: testDynakube1.Name}}, - ) - - checker := NewCorrectnessChecker(client, db, dtcsi.CSIOptions{}) - - err := checker.CorrectCSI(ctx) - - require.NoError(t, err) - vol, err := db.GetVolume(ctx, testVolume1.VolumeID) - require.NoError(t, err) - assert.Equal(t, &testVolume1, vol) - - require.NoError(t, err) - dk, err := db.GetDynakube(ctx, testDynakube1.Name) - require.NoError(t, err) - assert.Equal(t, &testDynakube1, dk) + t.Run("ignores irrelevant mounts", func(t *testing.T) { + mounter := mount.NewFakeMounter([]mount.MountPoint{ + { + Device: "not-relevant-mount-type", + }, + { + Device: "overlay", + Path: "not-relevant-overlay-mount", + Type: "overlay", + }, + }) + mounts, err := GetRelevantOverlayMounts(mounter, "/test") + require.NoError(t, err) + require.NotNil(t, mounts) + require.Empty(t, mounts) }) - t.Run("remove unnecessary entries in the filesystem", func(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - testVolume2 := createTestVolume(2) - testVolume3 := createTestVolume(3) - - testDynakube1 := createTestDynakube(1) - testDynakube2 := createTestDynakube(2) - testDynakube3 := createTestDynakube(3) - - db := FakeMemoryDB() - db.InsertVolume(ctx, &testVolume1) - db.InsertVolume(ctx, &testVolume2) - db.InsertVolume(ctx, &testVolume3) - db.InsertDynakube(ctx, &testDynakube1) - db.InsertDynakube(ctx, &testDynakube2) - db.InsertDynakube(ctx, &testDynakube3) - - client := fake.NewClient( - &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: testVolume1.PodName}}, - &dynakube.DynaKube{ObjectMeta: metav1.ObjectMeta{Name: testDynakube1.Name}}, - ) - - checker := NewCorrectnessChecker(client, db, dtcsi.CSIOptions{}) - - err := checker.CorrectCSI(ctx) - require.NoError(t, err) - - vol, err := db.GetVolume(ctx, testVolume1.VolumeID) - require.NoError(t, err) - assert.Equal(t, &testVolume1, vol) - - ten, err := db.GetDynakube(ctx, testDynakube1.Name) - require.NoError(t, err) - assert.Equal(t, &testDynakube1, ten) - - // PURGED - vol, err = db.GetVolume(ctx, testVolume2.VolumeID) - require.NoError(t, err) - assert.Nil(t, vol) - - // PURGED - vol, err = db.GetVolume(ctx, testVolume3.VolumeID) - require.NoError(t, err) - assert.Nil(t, vol) +} - // PURGED - ten, err = db.GetDynakube(ctx, testDynakube2.TenantUUID) - require.NoError(t, err) - assert.Nil(t, ten) +func TestMigrateAppMounts(t *testing.T) { + // Unfortunately, this is not unit-testable. + // Its output would be a bunch of symlinks, + // however the afero.MemMapFs does not support symlinking. + t.SkipNow() +} - // PURGED - ten, err = db.GetDynakube(ctx, testDynakube3.TenantUUID) - require.NoError(t, err) - assert.Nil(t, ten) - }) +func TestMigrateHostMounts(t *testing.T) { + // Unfortunately, this is not unit-testable. + // Its output would be a bunch of symlinks, + // however the afero.MemMapFs does not support symlinking. + t.SkipNow() } diff --git a/pkg/controllers/csi/metadata/deprecared_test.go b/pkg/controllers/csi/metadata/deprecared_test.go new file mode 100644 index 0000000000..45868e0216 --- /dev/null +++ b/pkg/controllers/csi/metadata/deprecared_test.go @@ -0,0 +1,76 @@ +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTenantUUIDFromApiUrl(t *testing.T) { + t.Run("happy path", func(t *testing.T) { + apiUrl := "https://demo.dev.dynatracelabs.com/api" + expectedTenantId := "demo" + + actualTenantId, err := TenantUUIDFromApiUrl(apiUrl) + + require.NoErrorf(t, err, "Expected that getting tenant id from '%s' will be successful", apiUrl) + assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", + apiUrl, expectedTenantId, actualTenantId, + ) + }) + + t.Run("happy path (alternative)", func(t *testing.T) { + apiUrl := "https://dynakube-activegate.dynatrace/e/tenant/api/v2/metrics/ingest" + expectedTenantId := "tenant" + + actualTenantId, err := TenantUUIDFromApiUrl(apiUrl) + + require.NoErrorf(t, err, "Expected that getting tenant id from '%s' will be successful", apiUrl) + assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", + apiUrl, expectedTenantId, actualTenantId, + ) + }) + + t.Run("happy path (alternative, no domain)", func(t *testing.T) { + apiUrl := "https://dynakube-activegate/e/tenant/api/v2/metrics/ingest" + expectedTenantId := "tenant" + + actualTenantId, err := TenantUUIDFromApiUrl(apiUrl) + + require.NoErrorf(t, err, "Expected that getting tenant id from '%s' will be successful", apiUrl) + assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", + apiUrl, expectedTenantId, actualTenantId, + ) + }) + + t.Run("missing API URL protocol", func(t *testing.T) { + apiUrl := "demo.dev.dynatracelabs.com/api" + expectedTenantId := "" + expectedError := "problem getting tenant id from API URL 'demo.dev.dynatracelabs.com/api'" + + actualTenantId, err := TenantUUIDFromApiUrl(apiUrl) + + require.EqualErrorf(t, err, expectedError, "Expected that getting tenant id from '%s' will result in: '%v'", + apiUrl, expectedError, + ) + assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", + apiUrl, expectedTenantId, actualTenantId, + ) + }) + + t.Run("suffix-only, relative API URL", func(t *testing.T) { + apiUrl := "/api" + expectedTenantId := "" + expectedError := "problem getting tenant id from API URL '/api'" + + actualTenantId, err := TenantUUIDFromApiUrl(apiUrl) + + require.EqualErrorf(t, err, expectedError, "Expected that getting tenant id from '%s' will result in: '%v'", + apiUrl, expectedError, + ) + assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s", + apiUrl, expectedTenantId, actualTenantId, + ) + }) +} diff --git a/pkg/controllers/csi/metadata/deprecated.go b/pkg/controllers/csi/metadata/deprecated.go new file mode 100644 index 0000000000..f3bddb740c --- /dev/null +++ b/pkg/controllers/csi/metadata/deprecated.go @@ -0,0 +1,35 @@ +package metadata + +import ( + "net/url" + "strings" + + "github.com/pkg/errors" +) + +// only kept for migration +func TenantUUIDFromApiUrl(apiUrl string) (string, error) { + parsedUrl, err := url.Parse(apiUrl) + if err != nil { + return "", errors.WithMessagef(err, "problem parsing tenant id from url %s", apiUrl) + } + + // Path = "/e//api" -> ["e", "", "api"] + subPaths := strings.FieldsFunc(parsedUrl.Path, runeIs('/')) + if len(subPaths) >= 3 && subPaths[0] == "e" && subPaths[2] == "api" { + return subPaths[1], nil + } + + hostnameWithDomains := strings.FieldsFunc(parsedUrl.Hostname(), runeIs('.')) + if len(hostnameWithDomains) >= 1 { + return hostnameWithDomains[0], nil + } + + return "", errors.Errorf("problem getting tenant id from API URL '%s'", apiUrl) +} + +func runeIs(wanted rune) func(rune) bool { + return func(actual rune) bool { + return actual == wanted + } +} diff --git a/pkg/controllers/csi/metadata/fakes.go b/pkg/controllers/csi/metadata/fakes.go deleted file mode 100644 index da034b8ff2..0000000000 --- a/pkg/controllers/csi/metadata/fakes.go +++ /dev/null @@ -1,117 +0,0 @@ -package metadata - -import ( - "context" - "database/sql" -) - -func emptyMemoryDB() *SqliteAccess { - db := SqliteAccess{} - _ = db.connect(sqliteDriverName, ":memory:") - - return &db -} - -func FakeMemoryDB() *SqliteAccess { - db := SqliteAccess{} - ctx := context.Background() - _ = db.Setup(ctx, ":memory:") - _ = db.createTables(ctx) - - return &db -} - -func checkIfTablesExist(db *SqliteAccess) bool { - var volumesTable string - - row := db.conn.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", volumesTableName) - - err := row.Scan(&volumesTable) - if err != nil { - return false - } - - var tenantsTable string - - row = db.conn.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", dynakubesTableName) - - err = row.Scan(&tenantsTable) - if err != nil { - return false - } - - if tenantsTable != dynakubesTableName || volumesTable != volumesTableName { - return false - } - - return true -} - -type FakeFailDB struct{} - -func (f *FakeFailDB) Setup(_ context.Context, _ string) error { return sql.ErrTxDone } -func (f *FakeFailDB) InsertDynakube(_ context.Context, _ *Dynakube) error { - return sql.ErrTxDone -} -func (f *FakeFailDB) UpdateDynakube(_ context.Context, _ *Dynakube) error { - return sql.ErrTxDone -} -func (f *FakeFailDB) DeleteDynakube(_ context.Context, _ string) error { - return sql.ErrTxDone -} -func (f *FakeFailDB) GetDynakube(_ context.Context, _ string) (*Dynakube, error) { - return nil, sql.ErrTxDone -} -func (f *FakeFailDB) GetTenantsToDynakubes(_ context.Context) (map[string]string, error) { - return nil, sql.ErrTxDone -} -func (f *FakeFailDB) GetAllDynakubes(_ context.Context) ([]*Dynakube, error) { - return nil, sql.ErrTxDone -} - -func (f *FakeFailDB) InsertOsAgentVolume(_ context.Context, _ *OsAgentVolume) error { - return sql.ErrTxDone -} -func (f *FakeFailDB) GetOsAgentVolumeViaVolumeID(_ context.Context, _ string) (*OsAgentVolume, error) { - return nil, sql.ErrTxDone -} -func (f *FakeFailDB) GetOsAgentVolumeViaTenantUUID(_ context.Context, _ string) (*OsAgentVolume, error) { - return nil, sql.ErrTxDone -} -func (f *FakeFailDB) UpdateOsAgentVolume(_ context.Context, _ *OsAgentVolume) error { - return sql.ErrTxDone -} -func (f *FakeFailDB) GetAllOsAgentVolumes(_ context.Context) ([]*OsAgentVolume, error) { - return nil, sql.ErrTxDone -} - -func (f *FakeFailDB) InsertVolume(_ context.Context, _ *Volume) error { return sql.ErrTxDone } -func (f *FakeFailDB) DeleteVolume(_ context.Context, _ string) error { return sql.ErrTxDone } -func (f *FakeFailDB) GetVolume(_ context.Context, _ string) (*Volume, error) { - return nil, sql.ErrTxDone -} -func (f *FakeFailDB) GetAllVolumes(_ context.Context) ([]*Volume, error) { return nil, sql.ErrTxDone } -func (f *FakeFailDB) GetPodNames(_ context.Context) (map[string]string, error) { - return nil, sql.ErrTxDone -} -func (f *FakeFailDB) GetUsedVersions(_ context.Context, _ string) (map[string]bool, error) { - return nil, sql.ErrTxDone -} -func (f *FakeFailDB) GetAllUsedVersions(_ context.Context) (map[string]bool, error) { - return nil, sql.ErrTxDone -} -func (f *FakeFailDB) GetLatestVersions(_ context.Context) (map[string]bool, error) { - return nil, sql.ErrTxDone -} -func (f *FakeFailDB) GetAllAppMounts(_ context.Context) []*Volume { - return nil -} -func (f *FakeFailDB) DeleteAppMount(_ context.Context, _ string) error { return nil } - -func (f *FakeFailDB) GetUsedImageDigests(_ context.Context) (map[string]bool, error) { - return nil, sql.ErrTxDone -} - -func (f *FakeFailDB) IsImageDigestUsed(_ context.Context, _ string) (bool, error) { - return false, sql.ErrTxDone -} diff --git a/pkg/controllers/csi/metadata/metadata.go b/pkg/controllers/csi/metadata/metadata.go deleted file mode 100644 index f86f2602b0..0000000000 --- a/pkg/controllers/csi/metadata/metadata.go +++ /dev/null @@ -1,143 +0,0 @@ -package metadata - -import ( - "context" - "time" -) - -// Dynakube stores the necessary info from the Dynakube that is needed to be used during volume mount/unmount. -type Dynakube struct { - Name string `json:"name"` - TenantUUID string `json:"tenantUUID"` - LatestVersion string `json:"latestVersion"` - ImageDigest string `json:"imageDigest"` - MaxFailedMountAttempts int `json:"maxFailedMountAttempts"` -} - -// NewDynakube returns a new metadata.Dynakube if all fields are set. -func NewDynakube(dynakubeName, tenantUUID, latestVersion, imageDigest string, maxFailedMountAttempts int) *Dynakube { - if tenantUUID == "" || dynakubeName == "" { - return nil - } - - return &Dynakube{ - Name: dynakubeName, - TenantUUID: tenantUUID, - LatestVersion: latestVersion, - ImageDigest: imageDigest, - MaxFailedMountAttempts: maxFailedMountAttempts, - } -} - -type Volume struct { - VolumeID string `json:"volumeID"` - PodName string `json:"podName"` - Version string `json:"version"` - TenantUUID string `json:"tenantUUID"` - MountAttempts int `json:"mountAttempts"` -} - -// NewVolume returns a new Volume if all fields (except version) are set. -func NewVolume(id, podName, version, tenantUUID string, mountAttempts int) *Volume { - if id == "" || podName == "" || tenantUUID == "" { - return nil - } - - if mountAttempts < 0 { - mountAttempts = 0 - } - - return &Volume{ - VolumeID: id, - PodName: podName, - Version: version, - TenantUUID: tenantUUID, - MountAttempts: mountAttempts, - } -} - -type OsAgentVolume struct { - LastModified *time.Time `json:"lastModified"` - VolumeID string `json:"volumeID"` - TenantUUID string `json:"tenantUUID"` - Mounted bool `json:"mounted"` -} - -// NewOsAgentVolume returns a new volume if all fields are set. -func NewOsAgentVolume(volumeID, tenantUUID string, mounted bool, timeStamp *time.Time) *OsAgentVolume { - if volumeID == "" || tenantUUID == "" || timeStamp == nil { - return nil - } - - return &OsAgentVolume{VolumeID: volumeID, TenantUUID: tenantUUID, Mounted: mounted, LastModified: timeStamp} -} - -type Access interface { - Setup(ctx context.Context, path string) error - - InsertDynakube(ctx context.Context, dynakube *Dynakube) error - UpdateDynakube(ctx context.Context, dynakube *Dynakube) error - DeleteDynakube(ctx context.Context, dynakubeName string) error - GetDynakube(ctx context.Context, dynakubeName string) (*Dynakube, error) - GetTenantsToDynakubes(ctx context.Context) (map[string]string, error) - GetAllDynakubes(ctx context.Context) ([]*Dynakube, error) - - InsertOsAgentVolume(ctx context.Context, volume *OsAgentVolume) error - GetOsAgentVolumeViaVolumeID(ctx context.Context, volumeID string) (*OsAgentVolume, error) - GetOsAgentVolumeViaTenantUUID(ctx context.Context, volumeID string) (*OsAgentVolume, error) - UpdateOsAgentVolume(ctx context.Context, volume *OsAgentVolume) error - GetAllOsAgentVolumes(ctx context.Context) ([]*OsAgentVolume, error) - - InsertVolume(ctx context.Context, volume *Volume) error - DeleteVolume(ctx context.Context, volumeID string) error - GetVolume(ctx context.Context, volumeID string) (*Volume, error) - GetAllVolumes(ctx context.Context) ([]*Volume, error) - GetPodNames(ctx context.Context) (map[string]string, error) - GetUsedVersions(ctx context.Context, tenantUUID string) (map[string]bool, error) - GetAllUsedVersions(ctx context.Context) (map[string]bool, error) - GetLatestVersions(ctx context.Context) (map[string]bool, error) - GetUsedImageDigests(ctx context.Context) (map[string]bool, error) - IsImageDigestUsed(ctx context.Context, imageDigest string) (bool, error) - GetAllAppMounts(ctx context.Context) []*Volume - DeleteAppMount(ctx context.Context, appMountName string) error -} - -type AccessOverview struct { - Volumes []*Volume `json:"volumes"` - Dynakubes []*Dynakube `json:"dynakubes"` - OsAgentVolumes []*OsAgentVolume `json:"osAgentVolumes"` -} - -func NewAccessOverview(access Access) (*AccessOverview, error) { - ctx := context.Background() - - volumes, err := access.GetAllVolumes(ctx) - if err != nil { - return nil, err - } - - dynakubes, err := access.GetAllDynakubes(ctx) - if err != nil { - return nil, err - } - - osVolumes, err := access.GetAllOsAgentVolumes(ctx) - if err != nil { - return nil, err - } - - return &AccessOverview{ - Volumes: volumes, - Dynakubes: dynakubes, - OsAgentVolumes: osVolumes, - }, nil -} - -func LogAccessOverview(access Access) { - overview, err := NewAccessOverview(access) - if err != nil { - log.Error(err, "Failed to get an overview of the stored csi metadata") - } - - log.Info("The current overview of the csi metadata", "overview", overview) -} diff --git a/pkg/controllers/csi/metadata/metadata_test.go b/pkg/controllers/csi/metadata/metadata_test.go deleted file mode 100644 index 50add01477..0000000000 --- a/pkg/controllers/csi/metadata/metadata_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package metadata - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -const ( - testName = "test-name" - testID = "test-id" - testUUID = "test-uuid" - testVersion = "test-version" - testDigest = "test-digest" - testMaxFailedMountAttempts = 3 - testMountAttempts = 1 -) - -func TestNewDynakube(t *testing.T) { - t.Run("initializes correctly", func(t *testing.T) { - dynakube := NewDynakube(testName, testUUID, testVersion, testDigest, testMaxFailedMountAttempts) - - assert.Equal(t, testName, dynakube.Name) - assert.Equal(t, testUUID, dynakube.TenantUUID) - assert.Equal(t, testVersion, dynakube.LatestVersion) - assert.Equal(t, testDigest, dynakube.ImageDigest) - assert.Equal(t, testMaxFailedMountAttempts, dynakube.MaxFailedMountAttempts) - }) - t.Run("returns nil if name or uuid is empty", func(t *testing.T) { - dynakube := NewDynakube("", testUUID, testVersion, testDigest, testMaxFailedMountAttempts) - - assert.Nil(t, dynakube) - - dynakube = NewDynakube(testName, "", testVersion, testDigest, testMaxFailedMountAttempts) - - assert.Nil(t, dynakube) - }) -} - -func TestNewVolume(t *testing.T) { - t.Run("initializes correctly", func(t *testing.T) { - volume := NewVolume(testID, testName, testVersion, testUUID, testMountAttempts) - - assert.Equal(t, testID, volume.VolumeID) - assert.Equal(t, testName, volume.PodName) - assert.Equal(t, testVersion, volume.Version) - assert.Equal(t, testUUID, volume.TenantUUID) - assert.Equal(t, testMountAttempts, volume.MountAttempts) - }) - t.Run("returns nil if id, name, or uuid is unset", func(t *testing.T) { - volume := NewVolume("", testName, testVersion, testUUID, testMountAttempts) - - assert.Nil(t, volume) - - volume = NewVolume(testID, "", testVersion, testUUID, testMountAttempts) - - assert.Nil(t, volume) - - volume = NewVolume(testID, testName, testVersion, "", testMountAttempts) - - assert.Nil(t, volume) - - volume = NewVolume(testID, testName, testVersion, testUUID, 0) - - assert.NotNil(t, volume) - assert.Equal(t, 0, volume.MountAttempts) - }) - t.Run("sets default value for mount attempts if less than 0", func(t *testing.T) { - volume := NewVolume(testID, testName, testVersion, testUUID, -1) - - assert.NotNil(t, volume) - assert.Equal(t, 0, volume.MountAttempts) - - volume = NewVolume(testID, testName, testVersion, testUUID, -2) - - assert.NotNil(t, volume) - assert.Equal(t, 0, volume.MountAttempts) - }) -} diff --git a/pkg/controllers/csi/metadata/path_resolver.go b/pkg/controllers/csi/metadata/path_resolver.go index da9d9e9488..72fb8bce78 100644 --- a/pkg/controllers/csi/metadata/path_resolver.go +++ b/pkg/controllers/csi/metadata/path_resolver.go @@ -11,25 +11,24 @@ type PathResolver struct { RootDir string } -func (pr PathResolver) TenantDir(tenantUUID string) string { - return filepath.Join(pr.RootDir, tenantUUID) +func (pr PathResolver) DynaKubeDir(dynakubeName string) string { + return filepath.Join(pr.RootDir, dynakubeName) } -func (pr PathResolver) OsAgentDir(tenantUUID string) string { - return filepath.Join(pr.TenantDir(tenantUUID), "osagent") +func (pr PathResolver) OsAgentDir(dynakubeName string) string { + return filepath.Join(pr.DynaKubeDir(dynakubeName), "osagent") } -func (pr PathResolver) AgentBinaryDir(tenantUUID string) string { - return filepath.Join(pr.TenantDir(tenantUUID), dtcsi.AgentBinaryDir) +func (pr PathResolver) AgentSharedBinaryDirBase() string { + return filepath.Join(pr.RootDir, dtcsi.SharedAgentBinDir) } -// Deprecated -func (pr PathResolver) AgentBinaryDirForVersion(tenantUUID string, version string) string { - return filepath.Join(pr.AgentBinaryDir(tenantUUID), version) +func (pr PathResolver) AgentSharedBinaryDirForAgent(versionOrDigest string) string { + return filepath.Join(pr.AgentSharedBinaryDirBase(), versionOrDigest) } -func (pr PathResolver) AgentSharedBinaryDirBase() string { - return filepath.Join(pr.RootDir, dtcsi.SharedAgentBinDir) +func (pr PathResolver) LatestAgentBinaryForDynaKube(dynakubeName string) string { + return filepath.Join(pr.DynaKubeDir(dynakubeName), "latest-codemodule") } func (pr PathResolver) AgentTempUnzipRootDir() string { @@ -40,38 +39,87 @@ func (pr PathResolver) AgentTempUnzipDir() string { return filepath.Join(pr.AgentTempUnzipRootDir(), "opt", "dynatrace", "oneagent") } -func (pr PathResolver) AgentSharedBinaryDirForAgent(versionOrDigest string) string { - return filepath.Join(pr.AgentSharedBinaryDirBase(), versionOrDigest) +func (pr PathResolver) AgentConfigDir(dynakubeName string) string { + return filepath.Join(pr.DynaKubeDir(dynakubeName), dtcsi.SharedAgentConfigDir) +} + +func (pr PathResolver) AgentSharedRuxitAgentProcConf(dynakubeName string) string { + return filepath.Join(pr.AgentConfigDir(dynakubeName), processmoduleconfig.RuxitAgentProcPath) +} + +func (pr PathResolver) OverlayVarRuxitAgentProcConf(volumeID string) string { + return filepath.Join(pr.AppMountVarDir(volumeID), processmoduleconfig.RuxitAgentProcPath) +} + +func (pr PathResolver) OverlayVarPodInfo(volumeID string) string { + return filepath.Join(pr.AppMountVarDir(volumeID), "pod-info") +} + +// AppMountsBaseDir replaces the AgentRunDir, the base directory where all the volumes for the app-mounts are stored +func (pr PathResolver) AppMountsBaseDir() string { + return filepath.Join(pr.RootDir, dtcsi.SharedAppMountsDir) +} + +// AppMountForID replaces AgentRunDirForVolume, the directory where a given app-mount volume is stored +func (pr PathResolver) AppMountForID(volumeID string) string { + return filepath.Join(pr.AppMountsBaseDir(), volumeID) +} + +// AppMountForDK is a directory where a given app-mount volume is stored under a certain dynakube +func (pr PathResolver) AppMountForDK(dkName string) string { + return filepath.Join(pr.RootDir, dkName, dtcsi.SharedAppMountsDir) +} + +// AppMountMappedDir replaces OverlayMappedDir, the directory where the overlay layers combine into +func (pr PathResolver) AppMountMappedDir(volumeID string) string { + return filepath.Join(pr.AppMountForID(volumeID), dtcsi.OverlayMappedDirPath) +} + +// AppMountVarDir replaces OverlayVarDir, the directory where the container using the volume writes +func (pr PathResolver) AppMountVarDir(volumeID string) string { + return filepath.Join(pr.AppMountForID(volumeID), dtcsi.OverlayVarDirPath) +} + +// AppMountWorkDir replaces OverlayWorkDir, the directory that is necessary for overlayFS to work +func (pr PathResolver) AppMountWorkDir(volumeID string) string { + return filepath.Join(pr.AppMountForID(volumeID), dtcsi.OverlayWorkDirPath) } -func (pr PathResolver) AgentConfigDir(tenantUUID string, dynakubeName string) string { - return filepath.Join(pr.TenantDir(tenantUUID), dynakubeName, dtcsi.SharedAgentConfigDir) +func (pr PathResolver) AppMountPodInfoDir(dkName, podNamespace, podName string) string { + return filepath.Join(pr.AppMountForDK(dkName), podNamespace, podName) } -func (pr PathResolver) AgentSharedRuxitAgentProcConf(tenantUUID, dynakubeName string) string { - return filepath.Join(pr.AgentConfigDir(tenantUUID, dynakubeName), processmoduleconfig.RuxitAgentProcPath) +// Deprecated kept for future migration/cleanup +func (pr PathResolver) AgentRunDir(dynakubeName string) string { + return filepath.Join(pr.DynaKubeDir(dynakubeName), dtcsi.AgentRunDir) } -func (pr PathResolver) OverlayVarRuxitAgentProcConf(tenantUUID, volumeId string) string { - return filepath.Join(pr.OverlayVarDir(tenantUUID, volumeId), processmoduleconfig.RuxitAgentProcPath) +// Deprecated kept for future migration/cleanup +func (pr PathResolver) AgentRunDirForVolume(dynakubeName string, volumeId string) string { + return filepath.Join(pr.AgentRunDir(dynakubeName), volumeId) } -func (pr PathResolver) AgentRunDir(tenantUUID string) string { - return filepath.Join(pr.TenantDir(tenantUUID), dtcsi.AgentRunDir) +// Deprecated kept for future migration/cleanup +func (pr PathResolver) OverlayMappedDir(dynakubeName string, volumeId string) string { + return filepath.Join(pr.AgentRunDirForVolume(dynakubeName, volumeId), dtcsi.OverlayMappedDirPath) } -func (pr PathResolver) AgentRunDirForVolume(tenantUUID string, volumeId string) string { - return filepath.Join(pr.AgentRunDir(tenantUUID), volumeId) +// Deprecated kept for future migration/cleanup +func (pr PathResolver) OverlayVarDir(dynakubeName string, volumeId string) string { + return filepath.Join(pr.AgentRunDirForVolume(dynakubeName, volumeId), dtcsi.OverlayVarDirPath) } -func (pr PathResolver) OverlayMappedDir(tenantUUID string, volumeId string) string { - return filepath.Join(pr.AgentRunDirForVolume(tenantUUID, volumeId), dtcsi.OverlayMappedDirPath) +// Deprecated kept for future migration/cleanup +func (pr PathResolver) OverlayWorkDir(dynakubeName string, volumeId string) string { + return filepath.Join(pr.AgentRunDirForVolume(dynakubeName, volumeId), dtcsi.OverlayWorkDirPath) } -func (pr PathResolver) OverlayVarDir(tenantUUID string, volumeId string) string { - return filepath.Join(pr.AgentRunDirForVolume(tenantUUID, volumeId), dtcsi.OverlayVarDirPath) +// Deprecated kept for future migration/cleanup +func (pr PathResolver) OldAgentConfigDir(tenantUUID string, dynakubeName string) string { + return filepath.Join(pr.DynaKubeDir(tenantUUID), dynakubeName, dtcsi.SharedAgentConfigDir) } -func (pr PathResolver) OverlayWorkDir(tenantUUID string, volumeId string) string { - return filepath.Join(pr.AgentRunDirForVolume(tenantUUID, volumeId), dtcsi.OverlayWorkDirPath) +// Deprecated kept for future migration/cleanup +func (pr PathResolver) OldAgentSharedRuxitAgentProcConf(tenantUUID, dynakubeName string) string { + return filepath.Join(pr.OldAgentConfigDir(tenantUUID, dynakubeName), processmoduleconfig.RuxitAgentProcPath) } diff --git a/pkg/controllers/csi/metadata/path_resolver_test.go b/pkg/controllers/csi/metadata/path_resolver_test.go deleted file mode 100644 index e93b3e2223..0000000000 --- a/pkg/controllers/csi/metadata/path_resolver_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package metadata - -import ( - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestPathResolver(t *testing.T) { - rootDir := "/testroot/tmp" - tenantUUID := "asj23443" - - pathResolver := PathResolver{RootDir: rootDir} - fakeEnv := filepath.Join(rootDir, tenantUUID) - fakeVolume := "csi-sdf3ijiji3jldisomeid" - agentRunDirForVolume := filepath.Join(fakeEnv, "run", fakeVolume) - - assert.Equal(t, fakeEnv, pathResolver.TenantDir(tenantUUID)) - assert.Equal(t, filepath.Join(fakeEnv, "bin"), pathResolver.AgentBinaryDir(tenantUUID)) - assert.Equal(t, filepath.Join(fakeEnv, "bin", "v1"), pathResolver.AgentBinaryDirForVersion(tenantUUID, "v1")) - assert.Equal(t, filepath.Join(fakeEnv, "run"), pathResolver.AgentRunDir(tenantUUID)) - assert.Equal(t, agentRunDirForVolume, pathResolver.AgentRunDirForVolume(tenantUUID, fakeVolume)) - assert.Equal(t, filepath.Join(agentRunDirForVolume, "mapped"), pathResolver.OverlayMappedDir(tenantUUID, fakeVolume)) - assert.Equal(t, filepath.Join(agentRunDirForVolume, "var"), pathResolver.OverlayVarDir(tenantUUID, fakeVolume)) - assert.Equal(t, filepath.Join(agentRunDirForVolume, "work"), pathResolver.OverlayWorkDir(tenantUUID, fakeVolume)) -} diff --git a/pkg/controllers/csi/metadata/sqlite.go b/pkg/controllers/csi/metadata/sqlite.go deleted file mode 100644 index c6f1ba91da..0000000000 --- a/pkg/controllers/csi/metadata/sqlite.go +++ /dev/null @@ -1,814 +0,0 @@ -package metadata - -import ( - "context" - "database/sql" - "strconv" - "strings" - "time" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/mattn/go-sqlite3" - "github.com/pkg/errors" -) - -var ( - dynakubesAlterStatementMaxFailedMountAttempts = ` - ALTER TABLE dynakubes - ADD COLUMN MaxFailedMountAttempts INT NOT NULL DEFAULT ` + strconv.FormatInt(dynakube.DefaultMaxFailedCsiMountAttempts, 10) + ";" - // "Not null"-columns need a default value set -) - -const ( - sqliteDriverName = "sqlite3" - - // CREATE - dynakubesTableName = "dynakubes" - dynakubesCreateStatement = ` - CREATE TABLE IF NOT EXISTS dynakubes ( - Name VARCHAR NOT NULL, - TenantUUID VARCHAR NOT NULL, - LatestVersion VARCHAR NOT NULL, - PRIMARY KEY (Name) - ); ` - - volumesTableName = "volumes" - volumesCreateStatement = ` - CREATE TABLE IF NOT EXISTS volumes ( - ID VARCHAR NOT NULL, - PodName VARCHAR NOT NULL, - Version VARCHAR NOT NULL, - TenantUUID VARCHAR NOT NULL, - PRIMARY KEY (ID) - );` - - osAgentVolumesTableName = "osagent_volumes" - osAgentVolumesCreateStatement = ` - CREATE TABLE IF NOT EXISTS osagent_volumes ( - TenantUUID VARCHAR NOT NULL, - VolumeID VARCHAR NOT NULL, - Mounted BOOLEAN NOT NULL, - LastModified DATETIME NOT NULL, - PRIMARY KEY (TenantUUID) - );` - - // ALTER - dynakubesAlterStatementImageDigestColumn = ` - ALTER TABLE dynakubes - ADD COLUMN ImageDigest VARCHAR NOT NULL DEFAULT ''; - ` - - volumesAlterStatementMountAttempts = ` - ALTER TABLE volumes - ADD COLUMN MountAttempts INT NOT NULL DEFAULT 0;` - - // INSERT - insertDynakubeStatement = ` - INSERT INTO dynakubes (Name, TenantUUID, LatestVersion, ImageDigest, MaxFailedMountAttempts) - VALUES (?,?,?,?, ?); - ` - - insertVolumeStatement = ` - INSERT INTO volumes (ID, PodName, Version, TenantUUID, MountAttempts) - VALUES (?,?,?,?,?) - ON CONFLICT(ID) DO UPDATE SET - PodName=excluded.PodName, - Version=excluded.Version, - TenantUUID=excluded.TenantUUID, - MountAttempts=excluded.MountAttempts; - ` - - insertOsAgentVolumeStatement = ` - INSERT INTO osagent_volumes (TenantUUID, VolumeID, Mounted, LastModified) - VALUES (?,?,?,?); - ` - - // UPDATE - updateDynakubeStatement = ` - UPDATE dynakubes - SET LatestVersion = ?, TenantUUID = ?, ImageDigest = ?, MaxFailedMountAttempts = ? - WHERE Name = ?; - ` - - updateOsAgentVolumeStatement = ` - UPDATE osagent_volumes - SET VolumeID = ?, Mounted = ?, LastModified = ? - WHERE TenantUUID = ?; - ` - - // GET - getDynakubeStatement = ` - SELECT TenantUUID, LatestVersion, ImageDigest, MaxFailedMountAttempts - FROM dynakubes - WHERE Name = ?; - ` - - getVolumeStatement = ` - SELECT PodName, Version, TenantUUID, MountAttempts - FROM volumes - WHERE ID = ?; - ` - - getOsAgentVolumeViaVolumeIDStatement = ` - SELECT TenantUUID, Mounted, LastModified - FROM osagent_volumes - WHERE VolumeID = ?; - ` - - getOsAgentVolumeViaTenantUUIDStatement = ` - SELECT VolumeID, Mounted, LastModified - FROM osagent_volumes - WHERE TenantUUID = ?; - ` - - // GET ALL - getAllDynakubesStatement = ` - SELECT Name, TenantUUID, LatestVersion, ImageDigest, MaxFailedMountAttempts - FROM dynakubes; - ` - - getAllVolumesStatement = ` - SELECT ID, PodName, Version, TenantUUID, MountAttempts - FROM volumes; - ` - - getAllOsAgentVolumes = ` - SELECT TenantUUID, VolumeID, Mounted, LastModified - FROM osagent_volumes; - ` - - // DELETE - deleteVolumeStatement = "DELETE FROM volumes WHERE ID = ?;" - - deleteDynakubeStatement = "DELETE FROM dynakubes WHERE Name = ?;" - - deleteAppMountStatement = "DELETE FROM app_mounts WHERE volume_meta_id = ?;" - - // SPECIAL - getUsedVersionsStatement = ` - SELECT DISTINCT Version - FROM volumes - WHERE TenantUUID = ?; - ` - - getAllUsedVersionsStatement = ` - SELECT DISTINCT Version - FROM volumes; - ` - - getUsedImageDigestStatement = ` - SELECT DISTINCT ImageDigest - FROM dynakubes - WHERE ImageDigest != ""; - ` - - getLatestVersionsStatement = ` - SELECT DISTINCT LatestVersion - FROM dynakubes; - ` - - getPodNamesStatement = ` - SELECT ID, PodName - FROM volumes; - ` - - getTenantsToDynakubesStatement = ` - SELECT tenantUUID, Name - FROM dynakubes; - ` - - countImageDigestStatement = ` - SELECT COUNT(*) - FROM dynakubes - WHERE ImageDigest = ?; - ` - - getAllAppMountsStatement = ` - SELECT volume_meta_id, code_module_version, location, mount_attempts, pod_name - FROM app_mounts - INNER JOIN volume_meta - WHERE volume_meta.id = app_mounts.volume_meta_id AND app_mounts.deleted_at IS NULL; - ` -) - -type SqliteAccess struct { - conn *sql.DB -} - -// NewAccess creates a new SqliteAccess, connects to the database. -func NewAccess(ctx context.Context, path string) (Access, error) { - access := SqliteAccess{} - - err := access.Setup(ctx, path) - if err != nil { - log.Error(err, "failed to connect to the database") - - return nil, err - } - - return &access, nil -} - -func (access *SqliteAccess) connect(driver, path string) error { - db, err := sql.Open(driver, path) - if err != nil { - err := errors.WithStack(errors.WithMessagef(err, "couldn't connect to db %s", path)) - access.conn = nil - - return err - } - - access.conn = db - - return nil -} - -func (access *SqliteAccess) createTables(ctx context.Context) error { - err := access.setupDynakubeTable(ctx) - if err != nil { - return err - } - - err = access.setupVolumeTable(ctx) - if err != nil { - return err - } - - if _, err := access.conn.ExecContext(ctx, osAgentVolumesCreateStatement); err != nil { - return errors.WithStack(errors.WithMessagef(err, "couldn't create the table %s", osAgentVolumesTableName)) - } - - return nil -} - -func (access *SqliteAccess) setupVolumeTable(ctx context.Context) error { - _, err := access.conn.Exec(volumesCreateStatement) - if err != nil { - return errors.WithMessagef(err, "couldn't create the table %s", volumesTableName) - } - - err = access.executeAlterStatement(ctx, volumesAlterStatementMountAttempts) - if err != nil { - return err - } - - return nil -} - -// setupDynakubeTable creates the dynakubes table if it doesn't exist and tries to add additional columns -func (access *SqliteAccess) setupDynakubeTable(ctx context.Context) error { - if _, err := access.conn.Exec(dynakubesCreateStatement); err != nil { - return errors.WithStack(errors.WithMessagef(err, "couldn't create the table %s", dynakubesTableName)) - } - - err := access.executeAlterStatement(ctx, dynakubesAlterStatementImageDigestColumn) - if err != nil { - return err - } - - err = access.executeAlterStatement(ctx, dynakubesAlterStatementMaxFailedMountAttempts) - if err != nil { - return err - } - - return nil -} - -func (access *SqliteAccess) executeAlterStatement(ctx context.Context, statement string) error { - if _, err := access.conn.ExecContext(ctx, statement); err != nil { - sqliteErr := sqlite3.Error{} - isSqliteErr := errors.As(err, &sqliteErr) - - if isSqliteErr && sqliteErr.Code != sqlite3.ErrError { - return errors.WithStack(err) - } - } - - return nil -} - -// Setup connects to the database and creates the necessary tables if they don't exist -func (access *SqliteAccess) Setup(ctx context.Context, path string) error { - if err := access.connect(sqliteDriverName, path); err != nil { - return err - } - - if err := access.createTables(ctx); err != nil { - return err - } - - return nil -} - -// InsertDynakube inserts a new Dynakube -func (access *SqliteAccess) InsertDynakube(ctx context.Context, dynakube *Dynakube) error { - err := access.executeStatement(ctx, insertDynakubeStatement, dynakube.Name, dynakube.TenantUUID, dynakube.LatestVersion, dynakube.ImageDigest, dynakube.MaxFailedMountAttempts) - if err != nil { - err = errors.WithMessagef(err, "couldn't insert dynakube entry, tenantUUID '%s', latest version '%s', name '%s', image digest '%s'", - dynakube.TenantUUID, - dynakube.LatestVersion, - dynakube.Name, - dynakube.ImageDigest) - } - - return err -} - -// UpdateDynakube updates an existing Dynakube by matching the name -func (access *SqliteAccess) UpdateDynakube(ctx context.Context, dynakube *Dynakube) error { - err := access.executeStatement(ctx, updateDynakubeStatement, dynakube.LatestVersion, dynakube.TenantUUID, dynakube.ImageDigest, dynakube.MaxFailedMountAttempts, dynakube.Name) - if err != nil { - err = errors.WithMessagef(err, "couldn't update dynakube, tenantUUID '%s', latest version '%s', name '%s', image digest '%s'", - dynakube.TenantUUID, - dynakube.LatestVersion, - dynakube.Name, - dynakube.ImageDigest) - } - - return err -} - -// DeleteDynakube deletes an existing Dynakube using its name -func (access *SqliteAccess) DeleteDynakube(ctx context.Context, dynakubeName string) error { - err := access.executeStatement(ctx, deleteDynakubeStatement, dynakubeName) - if err != nil { - err = errors.WithMessagef(err, "couldn't delete dynakube, name '%s'", dynakubeName) - } - - return err -} - -// GetDynakube gets Dynakube using its name -func (access *SqliteAccess) GetDynakube(ctx context.Context, dynakubeName string) (*Dynakube, error) { - var tenantUUID string - - var latestVersion string - - var imageDigest string - - var maxFailedMountAttempts int - - err := access.querySimpleStatement(ctx, getDynakubeStatement, dynakubeName, &tenantUUID, &latestVersion, &imageDigest, &maxFailedMountAttempts) - if err != nil { - err = errors.WithMessagef(err, "couldn't get dynakube, name '%s'", dynakubeName) - } - - return NewDynakube(dynakubeName, tenantUUID, latestVersion, imageDigest, maxFailedMountAttempts), err -} - -// InsertVolume inserts a new Volume -func (access *SqliteAccess) InsertVolume(ctx context.Context, volume *Volume) error { - err := access.executeStatement(ctx, insertVolumeStatement, volume.VolumeID, volume.PodName, volume.Version, volume.TenantUUID, volume.MountAttempts) - if err != nil { - err = errors.WithMessagef(err, "couldn't insert volume info, volume id '%s', pod '%s', version '%s', dynakube '%s'", - volume.VolumeID, - volume.PodName, - volume.Version, - volume.TenantUUID) - } - - return err -} - -// GetVolume gets Volume by its ID -func (access *SqliteAccess) GetVolume(ctx context.Context, volumeID string) (*Volume, error) { - var podName string - - var version string - - var tenantUUID string - - var mountAttempts int - - err := access.querySimpleStatement(ctx, getVolumeStatement, volumeID, &podName, &version, &tenantUUID, &mountAttempts) - if err != nil { - err = errors.WithMessagef(err, "couldn't get volume field for volume id '%s'", volumeID) - } - - return NewVolume(volumeID, podName, version, tenantUUID, mountAttempts), err -} - -// DeleteVolume deletes a Volume by its ID -func (access *SqliteAccess) DeleteVolume(ctx context.Context, volumeID string) error { - err := access.executeStatement(ctx, deleteVolumeStatement, volumeID) - if err != nil { - err = errors.WithMessagef(err, "couldn't delete volume for volume id '%s'", volumeID) - } - - return err -} - -// InsertOsAgentVolume inserts a new OsAgentVolume -func (access *SqliteAccess) InsertOsAgentVolume(ctx context.Context, volume *OsAgentVolume) error { - err := access.executeStatement(ctx, insertOsAgentVolumeStatement, volume.TenantUUID, volume.VolumeID, volume.Mounted, volume.LastModified) - if err != nil { - err = errors.WithMessagef(err, "couldn't insert osAgentVolume info, volume id '%s', tenant UUID '%s', mounted '%t', last modified '%s'", - volume.VolumeID, - volume.TenantUUID, - volume.Mounted, - volume.LastModified) - } - - return err -} - -// UpdateOsAgentVolume updates an existing OsAgentVolume by matching the tenantUUID -func (access *SqliteAccess) UpdateOsAgentVolume(ctx context.Context, volume *OsAgentVolume) error { - err := access.executeStatement(ctx, updateOsAgentVolumeStatement, volume.VolumeID, volume.Mounted, volume.LastModified, volume.TenantUUID) - if err != nil { - err = errors.WithMessagef(err, "couldn't update osAgentVolume info, tenantUUID '%s', mounted '%t', last modified '%s', volume id '%s'", - volume.TenantUUID, - volume.Mounted, - volume.LastModified, - volume.VolumeID) - } - - return err -} - -// GetOsAgentVolumeViaVolumeID gets an OsAgentVolume by its VolumeID -func (access *SqliteAccess) GetOsAgentVolumeViaVolumeID(ctx context.Context, volumeID string) (*OsAgentVolume, error) { - var tenantUUID string - - var mounted bool - - var lastModified time.Time - - err := access.querySimpleStatement(ctx, getOsAgentVolumeViaVolumeIDStatement, volumeID, &tenantUUID, &mounted, &lastModified) - if err != nil { - err = errors.WithMessagef(err, "couldn't get osAgentVolume info for volume id '%s'", volumeID) - } - - return NewOsAgentVolume(volumeID, tenantUUID, mounted, &lastModified), err -} - -// GetOsAgentVolumeViaTenantUUID gets an OsAgentVolume by its tenantUUID -func (access *SqliteAccess) GetOsAgentVolumeViaTenantUUID(ctx context.Context, tenantUUID string) (*OsAgentVolume, error) { - var volumeID string - - var mounted bool - - var lastModified time.Time - - err := access.querySimpleStatement(ctx, getOsAgentVolumeViaTenantUUIDStatement, tenantUUID, &volumeID, &mounted, &lastModified) - if err != nil { - err = errors.WithMessagef(err, "couldn't get osAgentVolume info for tenant uuid '%s'", tenantUUID) - } - - return NewOsAgentVolume(volumeID, tenantUUID, mounted, &lastModified), err -} - -// GetAllVolumes gets all the Volumes from the database -func (access *SqliteAccess) GetAllVolumes(ctx context.Context) ([]*Volume, error) { - rows, err := access.conn.QueryContext(ctx, getAllVolumesStatement) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't get all the volumes")) - } - - volumes := []*Volume{} - - defer func() { _ = rows.Close() }() - - for rows.Next() { - var id string - - var podName string - - var version string - - var tenantUUID string - - var mountAttempts int - - err := rows.Scan(&id, &podName, &version, &tenantUUID, &mountAttempts) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't scan volume from database")) - } - - volumes = append(volumes, NewVolume(id, podName, version, tenantUUID, mountAttempts)) - } - - return volumes, nil -} - -// GetAllDynakubes gets all the Dynakubes from the database -func (access *SqliteAccess) GetAllDynakubes(ctx context.Context) ([]*Dynakube, error) { - rows, err := access.conn.QueryContext(ctx, getAllDynakubesStatement) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't get all the dynakubes")) - } - - dynakubes := []*Dynakube{} - - defer func() { _ = rows.Close() }() - - for rows.Next() { - var name string - - var version string - - var tenantUUID string - - var imageDigest string - - var maxFailedMountAttempts int - - err := rows.Scan(&name, &tenantUUID, &version, &imageDigest, &maxFailedMountAttempts) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't scan dynakube from database")) - } - - dynakubes = append(dynakubes, NewDynakube(name, tenantUUID, version, imageDigest, maxFailedMountAttempts)) - } - - return dynakubes, nil -} - -// GetAllOsAgentVolumes gets all the OsAgentVolume from the database -func (access *SqliteAccess) GetAllOsAgentVolumes(ctx context.Context) ([]*OsAgentVolume, error) { - rows, err := access.conn.QueryContext(ctx, getAllOsAgentVolumes) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't get all the osagent volumes")) - } - - osVolumes := []*OsAgentVolume{} - - defer func() { _ = rows.Close() }() - - for rows.Next() { - var volumeID string - - var tenantUUID string - - var mounted bool - - var timeStamp time.Time - - err := rows.Scan(&tenantUUID, &volumeID, &mounted, &timeStamp) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't scan osagent volume from database")) - } - - osVolumes = append(osVolumes, NewOsAgentVolume(volumeID, tenantUUID, mounted, &timeStamp)) - } - - return osVolumes, nil -} - -// GetUsedVersions gets all UNIQUE versions present in the `volumes` for a given tenantUUID database in map. -// Map is used to make sure we don't return the same version multiple time, -// it's also easier to check if a version is in it or not. (a Set in style of Golang) -func (access *SqliteAccess) GetUsedVersions(ctx context.Context, tenantUUID string) (map[string]bool, error) { - rows, err := access.conn.QueryContext(ctx, getUsedVersionsStatement, tenantUUID) - if err != nil { - return nil, errors.WithStack(errors.WithMessagef(err, "couldn't get used version info for tenant uuid '%s'", tenantUUID)) - } - - versions := map[string]bool{} - - defer func() { _ = rows.Close() }() - - for rows.Next() { - var version string - - err := rows.Scan(&version) - if err != nil { - return nil, errors.WithStack(errors.WithMessagef(err, "couldn't scan used version info for tenant uuid '%s'", tenantUUID)) - } - - versions[version] = true - } - - return versions, nil -} - -// GetUsedVersions gets all UNIQUE versions present in the `volumes` database in map. -// Map is used to make sure we don't return the same version multiple time, -// it's also easier to check if a version is in it or not. (a Set in style of Golang) -func (access *SqliteAccess) GetAllUsedVersions(ctx context.Context) (map[string]bool, error) { - rows, err := access.conn.QueryContext(ctx, getAllUsedVersionsStatement) - if err != nil { - return nil, errors.WithStack(errors.WithMessagef(err, "couldn't get all used version info")) - } - - versions := map[string]bool{} - - defer func() { _ = rows.Close() }() - - for rows.Next() { - var version string - - err := rows.Scan(&version) - if err != nil { - return nil, errors.WithStack(errors.WithMessagef(err, "couldn't scan used version info")) - } - - if _, ok := versions[version]; !ok { - versions[version] = true - } - } - - return versions, nil -} - -// GetLatestVersions gets all UNIQUE latestVersions present in the `dynakubes` database in map. -// Map is used to make sure we don't return the same version multiple time, -// it's also easier to check if a version is in it or not. (a Set in style of Golang) -func (access *SqliteAccess) GetLatestVersions(ctx context.Context) (map[string]bool, error) { - rows, err := access.conn.QueryContext(ctx, getLatestVersionsStatement) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't get all the latests version info for tenant uuid")) - } - - versions := map[string]bool{} - - defer func() { _ = rows.Close() }() - - for rows.Next() { - var version string - - err := rows.Scan(&version) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't scan latest version info ")) - } - - versions[version] = true - } - - return versions, nil -} - -// GetUsedImageDigests gets all UNIQUE image digests present in the `dynakubes` database in a map. -// Map is used to make sure we don't return the same digest multiple time, -// it's also easier to check if a digest is in it or not. (a Set in style of Golang) -func (access *SqliteAccess) GetUsedImageDigests(ctx context.Context) (map[string]bool, error) { - rows, err := access.conn.QueryContext(ctx, getUsedImageDigestStatement) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't get used image digests from database")) - } - - imageDigests := map[string]bool{} - - defer func() { _ = rows.Close() }() - - for rows.Next() { - var digest string - - err := rows.Scan(&digest) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "failed to scan from image digests database")) - } - - if _, ok := imageDigests[digest]; !ok { - imageDigests[digest] = true - } - } - - return imageDigests, nil -} - -// IsImageDigestUsed checks if the specified image digest is present in the database. -func (access *SqliteAccess) IsImageDigestUsed(ctx context.Context, imageDigest string) (bool, error) { - var count int - - err := access.querySimpleStatement(ctx, countImageDigestStatement, imageDigest, &count) - if err != nil { - return false, errors.WithMessagef(err, "couldn't count usage of image digest: %s", imageDigest) - } - - return count > 0, nil -} - -// GetPodNames gets all PodNames present in the `volumes` database in map with their corresponding volumeIDs. -func (access *SqliteAccess) GetPodNames(ctx context.Context) (map[string]string, error) { - rows, err := access.conn.QueryContext(ctx, getPodNamesStatement) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't get all pod names")) - } - - podNames := map[string]string{} - - defer func() { _ = rows.Close() }() - - for rows.Next() { - var podName string - - var volumeID string - - err := rows.Scan(&volumeID, &podName) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't scan pod name from database")) - } - - podNames[podName] = volumeID - } - - return podNames, nil -} - -// GetTenantsToDynakubes gets all Dynakubes and maps their name to the corresponding TenantUUID. -func (access *SqliteAccess) GetTenantsToDynakubes(ctx context.Context) (map[string]string, error) { - rows, err := access.conn.QueryContext(ctx, getTenantsToDynakubesStatement) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't get all tenants to dynakube metadata")) - } - - dynakubes := map[string]string{} - - defer func() { _ = rows.Close() }() - - for rows.Next() { - var uuid string - - var dynakube string - - err := rows.Scan(&uuid, &dynakube) - if err != nil { - return nil, errors.WithStack(errors.WithMessage(err, "couldn't scan tenant to dynakube metadata from database")) - } - - dynakubes[dynakube] = uuid - } - - return dynakubes, nil -} - -func (access *SqliteAccess) GetAllAppMounts(ctx context.Context) []*Volume { - rows, err := access.conn.QueryContext(ctx, getAllAppMountsStatement) - if err != nil { - log.Info("skipping migration due to error getting all app mounts", "error", err) - - return nil - } - - defer func() { _ = rows.Close() }() - - var volumes = make([]*Volume, 0) - - for rows.Next() { - var code_module_version, volume_meta_id, location, pod_name string - - var mount_attempts int - - err := rows.Scan(&volume_meta_id, &code_module_version, &location, &mount_attempts, &pod_name) - if err != nil { - log.Info("couldn't scan app_mount from database", "error", err) - - continue - } - - tenantUUID := getTenantUUIDFromLocation(location) - if tenantUUID == "" { - log.Info("could not parse tenantUUID from location", "location", location) - - continue - } - - volumes = append(volumes, NewVolume(volume_meta_id, pod_name, code_module_version, tenantUUID, mount_attempts)) - } - - return volumes -} - -func (access *SqliteAccess) DeleteAppMount(ctx context.Context, appMountID string) error { - err := access.executeStatement(ctx, deleteAppMountStatement, appMountID) - if err != nil { - return err - } - - return nil -} - -// Executes the provided SQL statement on the database. -// The `vars` are passed to the SQL statement (in-order), to fill in the SQL wildcards. -func (access *SqliteAccess) executeStatement(ctx context.Context, statement string, vars ...any) error { - _, err := access.conn.ExecContext(ctx, statement, vars...) - - return errors.WithStack(err) -} - -// Executes the provided SQL SELECT statement on the database. -// The SQL statement should always return a single row. -// The `id` is passed to the SQL query to fill in an SQL wildcard -// The `vars` are filled with the values of the return of the SELECT statement, so the `vars` need to be pointers. -func (access *SqliteAccess) querySimpleStatement(ctx context.Context, statement, id string, vars ...any) error { - row := access.conn.QueryRowContext(ctx, statement, id) - - err := row.Scan(vars...) - if err != nil && err != sql.ErrNoRows { - return errors.WithStack(err) - } - - return nil -} - -func getTenantUUIDFromLocation(location string) string { - var tennantUUIDIndex = 2 - - result := strings.Split(location, "/") - if len(result) > tennantUUIDIndex { - return result[tennantUUIDIndex] - } - - return "" -} diff --git a/pkg/controllers/csi/metadata/sqlite_test.go b/pkg/controllers/csi/metadata/sqlite_test.go deleted file mode 100644 index e764db7fca..0000000000 --- a/pkg/controllers/csi/metadata/sqlite_test.go +++ /dev/null @@ -1,645 +0,0 @@ -package metadata - -import ( - "context" - "fmt" - "strconv" - "testing" - "time" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNewAccess(t *testing.T) { - db, err := NewAccess(context.TODO(), ":memory:") - require.NoError(t, err) - assert.NotNil(t, db.(*SqliteAccess).conn) -} - -func TestSetup(t *testing.T) { - db := SqliteAccess{} - err := db.Setup(context.TODO(), ":memory:") - - require.NoError(t, err) - assert.True(t, checkIfTablesExist(&db)) -} - -func TestSetup_badPath(t *testing.T) { - db := SqliteAccess{} - err := db.Setup(context.TODO(), "/asd") - require.Error(t, err) - - assert.False(t, checkIfTablesExist(&db)) -} - -func TestConnect(t *testing.T) { - path := ":memory:" - db := SqliteAccess{} - err := db.connect(sqliteDriverName, path) - require.NoError(t, err) - assert.NotNil(t, db.conn) -} - -func TestConnect_badDriver(t *testing.T) { - db := SqliteAccess{} - err := db.connect("die", "") - require.Error(t, err) - assert.Nil(t, db.conn) -} - -func TestCreateTables(t *testing.T) { - ctx := context.TODO() - - t.Run("volume table is created correctly", func(t *testing.T) { - db := emptyMemoryDB() - - err := db.createTables(ctx) - require.NoError(t, err) - - var volumeTableName string - - row := db.conn.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", volumesTableName) - err = row.Scan(&volumeTableName) - require.NoError(t, err) - assert.Equal(t, volumesTableName, volumeTableName) - - rows, err := db.conn.Query("PRAGMA table_info(" + volumesTableName + ")") - require.NoError(t, err) - assert.NotNil(t, rows) - - columns := []string{ - "ID", - "PodName", - "Version", - "TenantUUID", - "MountAttempts", - } - - for _, column := range columns { - assert.True(t, rows.Next()) - - var id, name, columnType, notNull, primaryKey string - - var defaultValue = new(string) - - err = rows.Scan(&id, &name, &columnType, ¬Null, &defaultValue, &primaryKey) - - require.NoError(t, err) - assert.Equal(t, column, name) - - if column == "MountAttempts" { - assert.Equal(t, "0", *defaultValue) - assert.Equal(t, "1", notNull) - } - } - }) - t.Run("dynakube table is created correctly", func(t *testing.T) { - db := emptyMemoryDB() - - err := db.createTables(ctx) - require.NoError(t, err) - - var dkTable string - - row := db.conn.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", dynakubesTableName) - err = row.Scan(&dkTable) - require.NoError(t, err) - assert.Equal(t, dynakubesTableName, dkTable) - - rows, err := db.conn.Query("PRAGMA table_info(" + dynakubesTableName + ")") - require.NoError(t, err) - assert.NotNil(t, rows) - - columns := []string{ - "Name", - "TenantUUID", - "LatestVersion", - "ImageDigest", - "MaxFailedMountAttempts", - } - - for _, column := range columns { - assert.True(t, rows.Next()) - - var id, name, columnType, notNull, primaryKey string - - var defaultValue = new(string) - - err = rows.Scan(&id, &name, &columnType, ¬Null, &defaultValue, &primaryKey) - - require.NoError(t, err) - assert.Equal(t, column, name) - - if column == "MaxFailedMountAttempts" { - maxFailedMountAttempts, err := strconv.Atoi(*defaultValue) - require.NoError(t, err) - assert.Equal(t, strconv.Itoa(dynakube.DefaultMaxFailedCsiMountAttempts), *defaultValue) - assert.Equal(t, dynakube.DefaultMaxFailedCsiMountAttempts, maxFailedMountAttempts) - assert.Equal(t, "1", notNull) - } - } - }) -} - -func TestInsertDynakube(t *testing.T) { - testDynakube1 := createTestDynakube(1) - - db := FakeMemoryDB() - - err := db.InsertDynakube(context.TODO(), &testDynakube1) - require.NoError(t, err) - - var uuid, lv, name string - - var imageDigest string - - var maxMountAttempts int - - row := db.conn.QueryRow(fmt.Sprintf("SELECT * FROM %s WHERE TenantUUID = ?;", dynakubesTableName), testDynakube1.TenantUUID) - err = row.Scan(&name, &uuid, &lv, &imageDigest, &maxMountAttempts) - require.NoError(t, err) - assert.Equal(t, testDynakube1.TenantUUID, uuid) - assert.Equal(t, testDynakube1.LatestVersion, lv) - assert.Equal(t, testDynakube1.Name, name) - assert.Equal(t, testDynakube1.ImageDigest, imageDigest) - assert.Equal(t, testDynakube1.MaxFailedMountAttempts, maxMountAttempts) -} - -func TestGetDynakube_Empty(t *testing.T) { - testDynakube1 := createTestDynakube(1) - db := FakeMemoryDB() - - gt, err := db.GetDynakube(context.TODO(), testDynakube1.TenantUUID) - require.NoError(t, err) - assert.Nil(t, gt) -} - -func TestGetDynakube(t *testing.T) { - ctx := context.TODO() - - t.Run("get dynakube", func(t *testing.T) { - testDynakube1 := createTestDynakube(1) - db := FakeMemoryDB() - err := db.InsertDynakube(ctx, &testDynakube1) - require.NoError(t, err) - - dynakube, err := db.GetDynakube(ctx, testDynakube1.Name) - require.NoError(t, err) - assert.Equal(t, testDynakube1, *dynakube) - }) -} - -func TestUpdateDynakube(t *testing.T) { - ctx := context.TODO() - testDynakube1 := createTestDynakube(1) - db := FakeMemoryDB() - err := db.InsertDynakube(ctx, &testDynakube1) - require.NoError(t, err) - - copyDynakube := testDynakube1 - copyDynakube.LatestVersion = "132.546" - copyDynakube.ImageDigest = "" - copyDynakube.MaxFailedMountAttempts = 10 - err = db.UpdateDynakube(ctx, ©Dynakube) - require.NoError(t, err) - - var uuid, lv, name string - - var imageDigest string - - var maxFailedMountAttempts int - - row := db.conn.QueryRow(fmt.Sprintf("SELECT Name, TenantUUID, LatestVersion, ImageDigest, MaxFailedMountAttempts FROM %s WHERE Name = ?;", dynakubesTableName), copyDynakube.Name) - err = row.Scan(&name, &uuid, &lv, &imageDigest, &maxFailedMountAttempts) - - require.NoError(t, err) - assert.Equal(t, copyDynakube.TenantUUID, uuid) - assert.Equal(t, copyDynakube.LatestVersion, lv) - assert.Equal(t, copyDynakube.Name, name) - assert.Equal(t, copyDynakube.MaxFailedMountAttempts, maxFailedMountAttempts) - assert.Empty(t, imageDigest) -} - -func TestGetTenantsToDynakubes(t *testing.T) { - ctx := context.TODO() - testDynakube1 := createTestDynakube(1) - testDynakube2 := createTestDynakube(2) - - db := FakeMemoryDB() - err := db.InsertDynakube(ctx, &testDynakube1) - require.NoError(t, err) - err = db.InsertDynakube(ctx, &testDynakube2) - require.NoError(t, err) - - dynakubes, err := db.GetTenantsToDynakubes(ctx) - require.NoError(t, err) - assert.Len(t, dynakubes, 2) - assert.Equal(t, testDynakube1.TenantUUID, dynakubes[testDynakube1.Name]) - assert.Equal(t, testDynakube2.TenantUUID, dynakubes[testDynakube2.Name]) -} - -func TestGetAllDynakubes(t *testing.T) { - ctx := context.TODO() - - t.Run("get multiple dynakubes", func(t *testing.T) { - testDynakube1 := createTestDynakube(1) - testDynakube2 := createTestDynakube(2) - - db := FakeMemoryDB() - err := db.InsertDynakube(ctx, &testDynakube1) - require.NoError(t, err) - err = db.InsertDynakube(ctx, &testDynakube2) - require.NoError(t, err) - - dynakubes, err := db.GetAllDynakubes(ctx) - require.NoError(t, err) - assert.Len(t, dynakubes, 2) - }) -} - -func TestGetAllVolumes(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - testVolume2 := createTestVolume(2) - - db := FakeMemoryDB() - err := db.InsertVolume(ctx, &testVolume1) - require.NoError(t, err) - err = db.InsertVolume(ctx, &testVolume2) - require.NoError(t, err) - - volumes, err := db.GetAllVolumes(ctx) - require.NoError(t, err) - assert.Len(t, volumes, 2) - assert.Equal(t, testVolume1, *volumes[0]) - assert.Equal(t, testVolume2, *volumes[1]) -} - -func TestGetAllOsAgentVolumes(t *testing.T) { - ctx := context.TODO() - testDynakube1 := createTestDynakube(1) - testDynakube2 := createTestDynakube(2) - - now := time.Now() - osVolume1 := OsAgentVolume{ - VolumeID: "vol-1", - TenantUUID: testDynakube1.TenantUUID, - Mounted: true, - LastModified: &now, - } - osVolume2 := OsAgentVolume{ - VolumeID: "vol-2", - TenantUUID: testDynakube2.TenantUUID, - Mounted: true, - LastModified: &now, - } - db := FakeMemoryDB() - err := db.InsertOsAgentVolume(ctx, &osVolume1) - require.NoError(t, err) - err = db.InsertOsAgentVolume(ctx, &osVolume2) - require.NoError(t, err) - - osVolumes, err := db.GetAllOsAgentVolumes(ctx) - require.NoError(t, err) - assert.Len(t, osVolumes, 2) -} - -func TestDeleteDynakube(t *testing.T) { - ctx := context.TODO() - testDynakube1 := createTestDynakube(1) - testDynakube2 := createTestDynakube(2) - - db := FakeMemoryDB() - err := db.InsertDynakube(ctx, &testDynakube1) - require.NoError(t, err) - err = db.InsertDynakube(ctx, &testDynakube2) - require.NoError(t, err) - - err = db.DeleteDynakube(ctx, testDynakube1.Name) - require.NoError(t, err) - dynakubes, err := db.GetTenantsToDynakubes(ctx) - require.NoError(t, err) - assert.Len(t, dynakubes, 1) - assert.Equal(t, testDynakube2.TenantUUID, dynakubes[testDynakube2.Name]) -} - -func TestGetVolume_Empty(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - db := FakeMemoryDB() - - vo, err := db.GetVolume(ctx, testVolume1.PodName) - require.NoError(t, err) - assert.Nil(t, vo) -} - -func TestInsertVolume(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - db := FakeMemoryDB() - - err := db.InsertVolume(ctx, &testVolume1) - require.NoError(t, err) - - row := db.conn.QueryRow(fmt.Sprintf("SELECT * FROM %s WHERE ID = ?;", volumesTableName), testVolume1.VolumeID) - - var id string - - var puid string - - var ver string - - var tuid string - - var mountAttempts int - err = row.Scan(&id, &puid, &ver, &tuid, &mountAttempts) - - require.NoError(t, err) - assert.Equal(t, testVolume1.VolumeID, id) - assert.Equal(t, testVolume1.PodName, puid) - assert.Equal(t, testVolume1.Version, ver) - assert.Equal(t, testVolume1.TenantUUID, tuid) - assert.Equal(t, testVolume1.MountAttempts, mountAttempts) - - newPodName := "something-else" - testVolume1.PodName = newPodName - err = db.InsertVolume(ctx, &testVolume1) - require.NoError(t, err) - - row = db.conn.QueryRow(fmt.Sprintf("SELECT * FROM %s WHERE ID = ?;", volumesTableName), testVolume1.VolumeID) - err = row.Scan(&id, &puid, &ver, &tuid, &mountAttempts) - - require.NoError(t, err) - assert.Equal(t, testVolume1.VolumeID, id) - assert.Equal(t, testVolume1.PodName, puid) - assert.Equal(t, testVolume1.Version, ver) - assert.Equal(t, testVolume1.TenantUUID, tuid) - assert.Equal(t, testVolume1.MountAttempts, mountAttempts) -} - -func TestInsertOsAgentVolume(t *testing.T) { - testDynakube1 := createTestDynakube(1) - db := FakeMemoryDB() - - now := time.Now() - volume := OsAgentVolume{ - VolumeID: "vol-4", - TenantUUID: testDynakube1.TenantUUID, - Mounted: true, - LastModified: &now, - } - - err := db.InsertOsAgentVolume(context.TODO(), &volume) - require.NoError(t, err) - - row := db.conn.QueryRow(fmt.Sprintf("SELECT * FROM %s WHERE TenantUUID = ?;", osAgentVolumesTableName), volume.TenantUUID) - - var volumeID string - - var tenantUUID string - - var mounted bool - - var lastModified time.Time - err = row.Scan(&tenantUUID, &volumeID, &mounted, &lastModified) - require.NoError(t, err) - assert.Equal(t, volumeID, volume.VolumeID) - assert.Equal(t, tenantUUID, volume.TenantUUID) - assert.Equal(t, mounted, volume.Mounted) - assert.True(t, volume.LastModified.Equal(lastModified)) -} - -func TestGetOsAgentVolumeViaVolumeID(t *testing.T) { - ctx := context.TODO() - testDynakube1 := createTestDynakube(1) - db := FakeMemoryDB() - - now := time.Now() - expected := OsAgentVolume{ - VolumeID: "vol-4", - TenantUUID: testDynakube1.TenantUUID, - Mounted: true, - LastModified: &now, - } - - err := db.InsertOsAgentVolume(ctx, &expected) - require.NoError(t, err) - actual, err := db.GetOsAgentVolumeViaVolumeID(ctx, expected.VolumeID) - require.NoError(t, err) - require.NoError(t, err) - assert.Equal(t, expected.VolumeID, actual.VolumeID) - assert.Equal(t, expected.TenantUUID, actual.TenantUUID) - assert.Equal(t, expected.Mounted, actual.Mounted) - assert.True(t, expected.LastModified.Equal(*actual.LastModified)) -} - -func TestGetOsAgentVolumeViaTennatUUID(t *testing.T) { - ctx := context.TODO() - testDynakube1 := createTestDynakube(1) - db := FakeMemoryDB() - - now := time.Now() - expected := OsAgentVolume{ - VolumeID: "vol-4", - TenantUUID: testDynakube1.TenantUUID, - Mounted: true, - LastModified: &now, - } - - err := db.InsertOsAgentVolume(ctx, &expected) - require.NoError(t, err) - actual, err := db.GetOsAgentVolumeViaTenantUUID(ctx, expected.TenantUUID) - require.NoError(t, err) - assert.Equal(t, expected.VolumeID, actual.VolumeID) - assert.Equal(t, expected.TenantUUID, actual.TenantUUID) - assert.Equal(t, expected.Mounted, actual.Mounted) - assert.True(t, expected.LastModified.Equal(*actual.LastModified)) -} - -func TestUpdateOsAgentVolume(t *testing.T) { - ctx := context.TODO() - testDynakube1 := createTestDynakube(1) - db := FakeMemoryDB() - - now := time.Now() - - oldEntry := OsAgentVolume{ - VolumeID: "vol-4", - TenantUUID: testDynakube1.TenantUUID, - Mounted: true, - LastModified: &now, - } - - err := db.InsertOsAgentVolume(ctx, &oldEntry) - require.NoError(t, err) - - newEntry := oldEntry - newEntry.Mounted = false - err = db.UpdateOsAgentVolume(ctx, &newEntry) - require.NoError(t, err) - - actual, err := db.GetOsAgentVolumeViaVolumeID(ctx, oldEntry.VolumeID) - require.NoError(t, err) - assert.Equal(t, oldEntry.VolumeID, actual.VolumeID) - assert.Equal(t, oldEntry.TenantUUID, actual.TenantUUID) - assert.NotEqual(t, oldEntry.Mounted, actual.Mounted) - assert.True(t, oldEntry.LastModified.Equal(*actual.LastModified)) -} - -func TestGetVolume(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - db := FakeMemoryDB() - err := db.InsertVolume(ctx, &testVolume1) - require.NoError(t, err) - - volume, err := db.GetVolume(ctx, testVolume1.VolumeID) - require.NoError(t, err) - assert.Equal(t, testVolume1, *volume) -} - -func TestUpdateVolume(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - db := FakeMemoryDB() - err := db.InsertVolume(ctx, &testVolume1) - - require.NoError(t, err) - - testVolume1.PodName = "different pod name" - testVolume1.Version = "new version" - testVolume1.TenantUUID = "asdf-1234" - testVolume1.MountAttempts = 10 - err = db.InsertVolume(ctx, &testVolume1) - - require.NoError(t, err) - - insertedVolume, err := db.GetVolume(ctx, testVolume1.VolumeID) - - require.NoError(t, err) - assert.Equal(t, testVolume1.VolumeID, insertedVolume.VolumeID) - assert.Equal(t, testVolume1.PodName, insertedVolume.PodName) - assert.Equal(t, testVolume1.Version, insertedVolume.Version) - assert.Equal(t, testVolume1.TenantUUID, insertedVolume.TenantUUID) - assert.Equal(t, testVolume1.MountAttempts, insertedVolume.MountAttempts) -} - -func TestGetUsedVersions(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - db := FakeMemoryDB() - err := db.InsertVolume(ctx, &testVolume1) - testVolume11 := testVolume1 - testVolume11.VolumeID = "vol-11" - testVolume11.Version = "321" - - require.NoError(t, err) - err = db.InsertVolume(ctx, &testVolume11) - require.NoError(t, err) - - versions, err := db.GetUsedVersions(ctx, testVolume1.TenantUUID) - require.NoError(t, err) - assert.Len(t, versions, 2) - assert.True(t, versions[testVolume1.Version]) - assert.True(t, versions[testVolume11.Version]) -} - -func TestGetAllUsedVersions(t *testing.T) { - ctx := context.TODO() - db := FakeMemoryDB() - testVolume1 := createTestVolume(1) - err := db.InsertVolume(ctx, &testVolume1) - testVolume11 := testVolume1 - testVolume11.VolumeID = "vol-11" - testVolume11.Version = "321" - - require.NoError(t, err) - err = db.InsertVolume(ctx, &testVolume11) - require.NoError(t, err) - - versions, err := db.GetAllUsedVersions(ctx) - require.NoError(t, err) - assert.Len(t, versions, 2) - assert.True(t, versions[testVolume1.Version]) - assert.True(t, versions[testVolume11.Version]) -} - -func TestGetUsedImageDigests(t *testing.T) { - ctx := context.TODO() - db := FakeMemoryDB() - testDynakube1 := createTestDynakube(1) - err := db.InsertDynakube(ctx, &testDynakube1) - require.NoError(t, err) - - copyDynakube := testDynakube1 - copyDynakube.Name = "copy" - err = db.InsertDynakube(ctx, ©Dynakube) - require.NoError(t, err) - - testDynakube2 := createTestDynakube(2) - err = db.InsertDynakube(ctx, &testDynakube2) - require.NoError(t, err) - - digests, err := db.GetUsedImageDigests(ctx) - require.NoError(t, err) - assert.Len(t, digests, 2) - assert.True(t, digests[testDynakube1.ImageDigest]) - assert.True(t, digests[copyDynakube.ImageDigest]) - assert.True(t, digests[testDynakube2.ImageDigest]) -} - -func TestIsImageDigestUsed(t *testing.T) { - ctx := context.TODO() - db := FakeMemoryDB() - - isUsed, err := db.IsImageDigestUsed(ctx, "test") - require.NoError(t, err) - require.False(t, isUsed) - - testDynakube1 := createTestDynakube(1) - err = db.InsertDynakube(ctx, &testDynakube1) - require.NoError(t, err) - - isUsed, err = db.IsImageDigestUsed(ctx, testDynakube1.ImageDigest) - require.NoError(t, err) - require.True(t, isUsed) -} - -func TestGetPodNames(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - testVolume2 := createTestVolume(2) - - db := FakeMemoryDB() - err := db.InsertVolume(ctx, &testVolume1) - require.NoError(t, err) - err = db.InsertVolume(ctx, &testVolume2) - require.NoError(t, err) - - podNames, err := db.GetPodNames(ctx) - require.NoError(t, err) - assert.Len(t, podNames, 2) - assert.Equal(t, testVolume1.VolumeID, podNames[testVolume1.PodName]) - assert.Equal(t, testVolume2.VolumeID, podNames[testVolume2.PodName]) -} - -func TestDeleteVolume(t *testing.T) { - ctx := context.TODO() - testVolume1 := createTestVolume(1) - testVolume2 := createTestVolume(2) - - db := FakeMemoryDB() - err := db.InsertVolume(ctx, &testVolume1) - require.NoError(t, err) - err = db.InsertVolume(ctx, &testVolume2) - require.NoError(t, err) - - err = db.DeleteVolume(ctx, testVolume2.VolumeID) - require.NoError(t, err) - podNames, err := db.GetPodNames(ctx) - require.NoError(t, err) - assert.Len(t, podNames, 1) - assert.Equal(t, testVolume1.VolumeID, podNames[testVolume1.PodName]) -} diff --git a/pkg/controllers/csi/provisioner/cleanup/appmounts.go b/pkg/controllers/csi/provisioner/cleanup/appmounts.go new file mode 100644 index 0000000000..5c5d352814 --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/appmounts.go @@ -0,0 +1,57 @@ +package cleanup + +func (c *Cleaner) removeDeprecatedMounts(fsState fsState) { + stillMountedCounter := 0 + + for _, depDir := range fsState.deprecatedDks { + runDir := c.path.AgentRunDir(depDir) + + volumeDirs, err := c.fs.ReadDir(runDir) + if err != nil { + log.Info("couldn't list volume dirs", "path", runDir) + + continue + } + + for _, volumeDir := range volumeDirs { + mappedDir := c.path.OverlayMappedDir(depDir, volumeDir.Name()) + + isEmpty, _ := c.fs.IsEmpty(mappedDir) + if isEmpty { + volumeDirPath := c.path.AgentRunDirForVolume(depDir, volumeDir.Name()) + + err := c.fs.RemoveAll(volumeDirPath) + if err == nil { + log.Info("removed unused volume", "path", volumeDirPath) + + continue + } + } + + stillMountedCounter++ + } + + isEmpty, _ := c.fs.IsEmpty(runDir) + if !isEmpty { + continue + } + + err = c.fs.RemoveAll(runDir) + if err == nil { + log.Info("removed empty deprecated run dir", "path", runDir) + } else { + continue + } + + tenantDir := c.path.DynaKubeDir(depDir) + + err = c.fs.RemoveAll(c.path.DynaKubeDir(tenantDir)) + if err == nil { + log.Info("removed empty deprecated dir", "path", tenantDir) + } + } + + if stillMountedCounter > 0 { + log.Info("there are a still mounted deprecated app mounts", "count", stillMountedCounter) + } +} diff --git a/pkg/controllers/csi/provisioner/cleanup/appmounts_test.go b/pkg/controllers/csi/provisioner/cleanup/appmounts_test.go new file mode 100644 index 0000000000..22c626d744 --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/appmounts_test.go @@ -0,0 +1,83 @@ +package cleanup + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestRemoveDeprecatedMounts(t *testing.T) { + t.Run("empty fsState -> no panic", func(t *testing.T) { + cleaner := createCleaner(t) + + cleaner.removeDeprecatedMounts(fsState{}) + }) + + t.Run("remove unmounted deprecated dirs (empty mapped subdir)", func(t *testing.T) { + cleaner := createCleaner(t) + + deprecateDir := []string{ + "t0", + "t1", + "t2", + } + + for i, folder := range deprecateDir { + cleaner.createDeprecatedDirs(t, folder, i, i*2) + + expectedDir := cleaner.path.AgentRunDir(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + + subdirs, err := cleaner.fs.ReadDir(expectedDir) + require.NoError(t, err) + require.Len(t, subdirs, i+i*2) + } + + cleaner.removeDeprecatedMounts(fsState{ + deprecatedDks: deprecateDir, + }) + + for i, folder := range deprecateDir { + expectedDir := cleaner.path.AgentRunDir(folder) + + exists, _ := cleaner.fs.Exists(expectedDir) + if i == 0 { + require.False(t, exists) + } else { + require.True(t, exists) + + subdirs, err := cleaner.fs.ReadDir(expectedDir) + require.NoError(t, err) + require.Len(t, subdirs, i) + } + } + }) +} + +func (c *Cleaner) createDeprecatedDirs(t *testing.T, name string, subDirAmount, emptySubDirAmount int) { + t.Helper() + + runDir := c.path.AgentRunDir(name) + err := c.fs.MkdirAll(runDir, os.ModePerm) + require.NoError(t, err) + + for i := range subDirAmount { + mappedDir := c.path.OverlayMappedDir(name, fmt.Sprintf("volume-%d", i)) + err := c.fs.MkdirAll(mappedDir, os.ModePerm) + require.NoError(t, err) + file, err := c.fs.Create(filepath.Join(mappedDir, "something")) + require.NoError(t, err) + _, err = file.WriteString("something") + require.NoError(t, err) + } + + for i := range emptySubDirAmount { + mappedDir := c.path.OverlayMappedDir(name, fmt.Sprintf("volume-%d", i+subDirAmount)) + err := c.fs.MkdirAll(mappedDir, os.ModePerm) + require.NoError(t, err) + } +} diff --git a/pkg/controllers/csi/provisioner/cleanup/binaries.go b/pkg/controllers/csi/provisioner/cleanup/binaries.go new file mode 100644 index 0000000000..3089ba180b --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/binaries.go @@ -0,0 +1,117 @@ +package cleanup + +import ( + "strings" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "golang.org/x/exp/maps" +) + +func (c *Cleaner) removeUnusedBinaries(dks []dynakube.DynaKube, fsState fsState) { + c.removeOldBinarySymlinks(dks, fsState) + + keptBins, err := c.collectStillMountedBins() + if err != nil { + return + } + + relevantLatestBins := c.collectRelevantLatestBins(dks) + + for k, v := range relevantLatestBins { + keptBins[k] = v + } + + c.removeOldSharedBinaries(keptBins) +} + +func (c *Cleaner) removeOldSharedBinaries(keptBins map[string]bool) { + sharedBins, err := c.fs.ReadDir(c.path.AgentSharedBinaryDirBase()) + if err != nil { + log.Info("failed to list the shared binaries directory, skipping unused binaries cleanup") + + return + } + + for _, dir := range sharedBins { + sharedBinPath := c.path.AgentSharedBinaryDirForAgent(dir.Name()) + + _, ok := keptBins[sharedBinPath] + if !ok { + err := c.fs.RemoveAll(sharedBinPath) + if err != nil { + log.Error(err, "failed to remove shared binary", "path", sharedBinPath) + + continue + } + + log.Info("removed old shared binary", "path", sharedBinPath) + } + } +} + +func (c *Cleaner) removeOldBinarySymlinks(dks []dynakube.DynaKube, fsState fsState) { + shouldBePresent := map[string]bool{} + for _, dk := range dks { + shouldBePresent[dk.Name] = true + } + + for _, dkDir := range fsState.binDks { + if _, ok := shouldBePresent[dkDir]; !ok { + latest := c.path.LatestAgentBinaryForDynaKube(dkDir) + if err := c.fs.Remove(latest); err == nil { + log.Info("removed old latest bin symlink", "path", latest) + } + } + } + + for _, depDir := range fsState.deprecatedDks { + if _, ok := shouldBePresent[depDir]; !ok { // for the rare case where dk.Name == tenantUUID + latest := c.path.LatestAgentBinaryForDynaKube(depDir) + if err := c.fs.Remove(latest); err == nil { + log.Info("removed old deprecated latest bin symlink", "path", latest) + } + } + } +} + +func (c *Cleaner) collectStillMountedBins() (map[string]bool, error) { + mountedBins := map[string]bool{} + + overlays, err := metadata.GetRelevantOverlayMounts(c.mounter, c.path.RootDir) + if err != nil { + log.Info("failed to list active overlay mounts, skipping unused binaries cleanup") + + return nil, err + } + + for _, overlay := range overlays { + mountedBins[overlay.LowerDir] = true + } + + if len(mountedBins) > 0 { + log.Info("binaries to keep because they are still mounted", "paths", strings.Join(maps.Keys(mountedBins), ",")) + } + + return mountedBins, nil +} + +func (c *Cleaner) collectRelevantLatestBins(dks []dynakube.DynaKube) map[string]bool { + latestBins := map[string]bool{} + + for _, dk := range dks { + if !dk.OneAgent().IsAppInjectionNeeded() { + continue + } + + latestLink := c.path.LatestAgentBinaryForDynaKube(dk.Name) + + c.addRelevantPath(latestLink, latestBins) + } + + if len(latestBins) > 0 { + log.Info("binaries to keep because they are the latest for existing dynakubes", "paths", strings.Join(maps.Keys(latestBins), ",")) + } + + return latestBins +} diff --git a/pkg/controllers/csi/provisioner/cleanup/binaries_test.go b/pkg/controllers/csi/provisioner/cleanup/binaries_test.go new file mode 100644 index 0000000000..f425a0fb64 --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/binaries_test.go @@ -0,0 +1,286 @@ +package cleanup + +import ( + "os" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/mount-utils" +) + +func TestRemoveUnusedBinaries(t *testing.T) { + // Not possible to test, as parts of it rely on turning symlinks into actual paths, and clearing up according to these paths. + // each individual part is testable + t.SkipNow() +} + +func TestRemoveOldSharedBinaries(t *testing.T) { + t.Run("empty fs -> no panic", func(t *testing.T) { + cleaner := createCleaner(t) + + keptBins := map[string]bool{} + + cleaner.removeOldSharedBinaries(keptBins) + }) + t.Run("empty shared dir -> no panic", func(t *testing.T) { + cleaner := createCleaner(t) + cleaner.fs.MkdirAll(cleaner.path.AgentSharedBinaryDirBase(), os.ModePerm) + + keptBins := map[string]bool{} + + cleaner.removeOldSharedBinaries(keptBins) + }) + + t.Run("empty keptBins -> remove all", func(t *testing.T) { + cleaner := createCleaner(t) + cleaner.fs.MkdirAll(cleaner.path.AgentSharedBinaryDirBase(), os.ModePerm) + + keptBins := map[string]bool{} + agentVersions := []string{"test1", "test2"} + + for _, folder := range agentVersions { + cleaner.createSharedBinDir(t, folder) + + expectedDir := cleaner.path.AgentSharedBinaryDirForAgent(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + } + + cleaner.removeOldSharedBinaries(keptBins) + + for _, folder := range agentVersions { + expectedDir := cleaner.path.AgentSharedBinaryDirForAgent(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.False(t, exists) + } + }) + + t.Run("keptBins set -> only remove orphans", func(t *testing.T) { + cleaner := createCleaner(t) + cleaner.fs.MkdirAll(cleaner.path.AgentSharedBinaryDirBase(), os.ModePerm) + + keptBins := map[string]bool{ + cleaner.path.AgentSharedBinaryDirForAgent("test1"): true, + cleaner.path.AgentSharedBinaryDirForAgent("test2"): true, + } + agentVersions := []string{"test1", "test2"} + orphans := []string{"o1", "o2"} + + for _, version := range append(agentVersions, orphans...) { + cleaner.createSharedBinDir(t, version) + + expectedDir := cleaner.path.AgentSharedBinaryDirForAgent(version) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + } + + cleaner.removeOldSharedBinaries(keptBins) + + for _, folder := range agentVersions { + expectedDir := cleaner.path.AgentSharedBinaryDirForAgent(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + } + + for _, folder := range orphans { + expectedDir := cleaner.path.AgentSharedBinaryDirForAgent(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.False(t, exists) + } + }) +} + +func TestCollectStillMountedBins(t *testing.T) { + t.Run("0 mounts -> empty", func(t *testing.T) { + cleaner := createCleaner(t) + + relevantBins, err := cleaner.collectStillMountedBins() + + require.NoError(t, err) + require.Empty(t, relevantBins) + }) + t.Run("get mounted bins", func(t *testing.T) { + cleaner := createCleaner(t) + cleaner.path.RootDir = "special" + expectedPath := cleaner.path.RootDir + "/something" + expectedLowerDir := expectedPath + "/else" + + relevantMountPoint := mount.MountPoint{ + Device: "overlay", + Path: expectedPath, + Type: "overlay", + Opts: []string{ + "lowerdir=" + expectedLowerDir, + "upperdir=...", + "workdir=...", + }, + } + + mockMountPoints(t, cleaner, relevantMountPoint) + + relevantBins, err := cleaner.collectStillMountedBins() + + require.NoError(t, err) + require.Len(t, relevantBins, 1) + assert.True(t, relevantBins[expectedLowerDir]) + }) +} + +func TestCollectRelevantLatestBins(t *testing.T) { + t.Run("no dk -> do nothing", func(t *testing.T) { + cleaner := createCleaner(t) + + relevantBins := cleaner.collectRelevantLatestBins([]dynakube.DynaKube{}) + + require.Empty(t, relevantBins) + }) + t.Run("no relevant dk -> do nothing", func(t *testing.T) { + cleaner := createCleaner(t) + + relevantBins := cleaner.collectRelevantLatestBins([]dynakube.DynaKube{ + createHostMonDk(t, "hostmon", "url"), + }) + + require.Empty(t, relevantBins) + }) + + t.Run("relevant dk -> try to resolve symlink", func(t *testing.T) { + cleaner := createCleaner(t) + + relevantBins := cleaner.collectRelevantLatestBins([]dynakube.DynaKube{ + createAppMonDk(t, "appmon", "url"), + }) + + require.NotEmpty(t, relevantBins) + }) +} + +func TestRemoveOldBinarySymlinks(t *testing.T) { + t.Run("no dk -> remove everything", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{} + + binDirs := []string{"test1", "test2"} + + for _, folder := range binDirs { + cleaner.createBinDirs(t, folder) + + expectedDir := cleaner.path.LatestAgentBinaryForDynaKube(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + } + + cleaner.removeOldBinarySymlinks(dks, fsState{ + binDks: binDirs, + }) + + for _, folder := range binDirs { + exists, _ := cleaner.fs.Exists(cleaner.path.LatestAgentBinaryForDynaKube(folder)) + require.False(t, exists) + } + }) + + t.Run("dk -> don't remove", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{ + createCloudNativeDk(t, "cloudnative", "-"), + createAppMonDk(t, "appmon", "-"), + } + + binDirs := []string{dks[0].Name, dks[1].Name, "test1", "test2"} + + for _, folder := range binDirs { + cleaner.createBinDirs(t, folder) + + expectedDir := cleaner.path.LatestAgentBinaryForDynaKube(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + } + + cleaner.removeOldBinarySymlinks(dks, fsState{ + binDks: binDirs, + }) + + for _, folder := range binDirs[:2] { + exists, _ := cleaner.fs.Exists(cleaner.path.LatestAgentBinaryForDynaKube(folder)) + require.True(t, exists) + } + + for _, folder := range binDirs[2:] { + exists, _ := cleaner.fs.Exists(cleaner.path.LatestAgentBinaryForDynaKube(folder)) + require.False(t, exists) + } + }) + + t.Run("dk.Name == tenantUUID -> don't remove", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{ + createCloudNativeDk(t, "cloudnative", "-"), + createAppMonDk(t, "appmon", "-"), + } + + binDirs := []string{dks[0].Name, dks[1].Name, "test1", "test2"} + + for _, folder := range binDirs { + cleaner.createBinDirs(t, folder) + + expectedDir := cleaner.path.LatestAgentBinaryForDynaKube(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + } + + cleaner.removeOldBinarySymlinks(dks, fsState{ + deprecatedDks: binDirs, + }) + + for _, folder := range binDirs[:2] { + exists, _ := cleaner.fs.Exists(cleaner.path.LatestAgentBinaryForDynaKube(folder)) + require.True(t, exists) + } + + for _, folder := range binDirs[2:] { + exists, _ := cleaner.fs.Exists(cleaner.path.LatestAgentBinaryForDynaKube(folder)) + require.False(t, exists) + } + }) +} + +func mockMountPoints(t *testing.T, cleaner *Cleaner, mountPoints ...mount.MountPoint) { + t.Helper() + + cleaner.mounter = mount.NewFakeMounter(mountPoints) +} + +func createAppMonDk(t *testing.T, name, apiUrl string) dynakube.DynaKube { + t.Helper() + + dk := createBaseDk(t, name, apiUrl) + dk.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} + + return dk +} + +func createBaseDk(t *testing.T, name, apiUrl string) dynakube.DynaKube { + t.Helper() + + return dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: apiUrl, + }, + } +} + +func (c *Cleaner) createSharedBinDir(t *testing.T, version string) { + t.Helper() + + binDir := c.path.AgentSharedBinaryDirForAgent(version) + err := c.fs.MkdirAll(binDir, os.ModePerm) + require.NoError(t, err) +} diff --git a/pkg/controllers/csi/provisioner/cleanup/config.go b/pkg/controllers/csi/provisioner/cleanup/config.go new file mode 100644 index 0000000000..df646bf98a --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/config.go @@ -0,0 +1,9 @@ +package cleanup + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/logd" +) + +var ( + log = logd.Get().WithName("csi-cleanup") +) diff --git a/pkg/controllers/csi/provisioner/cleanup/hostmounts.go b/pkg/controllers/csi/provisioner/cleanup/hostmounts.go new file mode 100644 index 0000000000..4b267f6caf --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/hostmounts.go @@ -0,0 +1,77 @@ +package cleanup + +import ( + "strings" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "golang.org/x/exp/maps" + "k8s.io/mount-utils" +) + +func (c *Cleaner) isMountPoint(file string) (bool, error) { + fakeMounter, ok := c.mounter.(*mount.FakeMounter) + if ok { + // you can't use the fake mounter IsLikelyNotMountPoint, as it will still use the os package + err, ok := fakeMounter.MountCheckErrors[file] + if ok { + if err == nil { + return true, nil + } + + return false, err + } else { + return false, nil + } + } + + return c.mounter.IsMountPoint(file) +} + +func (c *Cleaner) removeHostMounts(dks []dynakube.DynaKube, fsState fsState) { + relevantHostDirs := c.collectRelevantHostDirs(dks) + + for _, hostDk := range fsState.hostDks { + hostDir := c.path.OsAgentDir(hostDk) + + isMountPoint, err := c.isMountPoint(hostDir) + if err == nil && !isMountPoint && !relevantHostDirs[hostDir] { + err := c.fs.RemoveAll(hostDir) + if err == nil { + log.Info("removed old host mount directory", "path", hostDir) + } + } + } +} + +func (c *Cleaner) collectRelevantHostDirs(dks []dynakube.DynaKube) map[string]bool { + hostDirs := map[string]bool{} + + for _, dk := range dks { + if !dk.OneAgent().IsReadOnlyOneAgentsMode() { + continue + } + + hostDir := c.path.OsAgentDir(dk.Name) + + hostDirs[hostDir] = true + + c.safeAddRelevantPath(hostDir, hostDirs) + + tenantUUID, err := metadata.TenantUUIDFromApiUrl(dk.ApiUrl()) + if err != nil { + log.Error(err, "malformed ApiUrl for dynakube during host mount directory cleanup", "dk", dk.Name, "apiUrl", dk.ApiUrl()) + + continue + } + + deprecatedHostDirLink := c.path.OsAgentDir(tenantUUID) + c.safeAddRelevantPath(deprecatedHostDirLink, hostDirs) + } + + if len(hostDirs) > 0 { + log.Info("host directories to keep because they have a related dynakube", "paths", strings.Join(maps.Keys(hostDirs), ",")) + } + + return hostDirs +} diff --git a/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go b/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go new file mode 100644 index 0000000000..46dcfe9b63 --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go @@ -0,0 +1,189 @@ +package cleanup + +import ( + "fmt" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/mount-utils" +) + +func TestRemoveHostMounts(t *testing.T) { + tenantUUID1 := "tenant1" + apiUrl1 := fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", tenantUUID1) + + tenantUUID2 := "tenant2" + apiUrl2 := fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", tenantUUID2) + + t.Run("no dk -> no relevant dirs -> remove all", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{} + hostFolders := []string{tenantUUID1, tenantUUID2, "random-name1", "random-name2"} + + for _, folder := range hostFolders { + cleaner.createHostDirs(t, folder) + + expectedDir := cleaner.path.OsAgentDir(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + } + + cleaner.removeHostMounts(dks, fsState{ + hostDks: hostFolders, + }) + + for _, folder := range hostFolders { + exists, _ := cleaner.fs.Exists(cleaner.path.OsAgentDir(folder)) + require.False(t, exists) + } + }) + + t.Run("relevant dk -> remove only orphans", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{ + createHostMonDk(t, "hostmon", apiUrl1), + createCloudNativeDk(t, "cloudnative", apiUrl2), + } + hostFolders := []string{tenantUUID1, dks[0].Name, dks[1].Name, "random-name1", "random-name2"} + + for _, folder := range hostFolders { + cleaner.createHostDirs(t, folder) + + expectedDir := cleaner.path.OsAgentDir(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + } + + cleaner.removeHostMounts(dks, fsState{ + hostDks: hostFolders, + }) + + for _, folder := range hostFolders[:3] { + exists, _ := cleaner.fs.Exists(cleaner.path.OsAgentDir(folder)) + require.True(t, exists) + } + + for _, folder := range hostFolders[3:] { + exists, _ := cleaner.fs.Exists(cleaner.path.OsAgentDir(folder)) + require.False(t, exists) + } + }) + + t.Run("don't remove mounted orphans", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{} + hostFolders := []string{tenantUUID1, tenantUUID2} + fakeMounter := mount.NewFakeMounter(nil) + fakeMounter.MountCheckErrors = map[string]error{} + + for _, folder := range hostFolders { + cleaner.createHostDirs(t, folder) + + expectedDir := cleaner.path.OsAgentDir(folder) + exists, _ := cleaner.fs.Exists(expectedDir) + require.True(t, exists) + + fakeMounter.MountCheckErrors[expectedDir] = nil + } + + cleaner.mounter = fakeMounter + + cleaner.removeHostMounts(dks, fsState{ + hostDks: hostFolders, + }) + + for _, folder := range hostFolders { + exists, _ := cleaner.fs.Exists(cleaner.path.OsAgentDir(folder)) + require.True(t, exists) + } + }) +} + +func TestCollectRelevantHostDirs(t *testing.T) { + tenantUUID1 := "tenant1" + apiUrl1 := fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", tenantUUID1) + + tenantUUID2 := "tenant2" + apiUrl2 := fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", tenantUUID2) + + t.Run("no dk -> no relevant dirs", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{} + + relevantDirs := cleaner.collectRelevantHostDirs(dks) + + require.Empty(t, relevantDirs) + }) + + t.Run("not-relevant dk -> no relevant dirs", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{ + createAppMonDk(t, "appmon1", apiUrl1), + createAppMonDk(t, "appmon2", apiUrl2), + } + + relevantDirs := cleaner.collectRelevantHostDirs(dks) + + require.Empty(t, relevantDirs) + }) + + t.Run("relevant dks, but not existing -> current path always added", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{ + createHostMonDk(t, "hostmon", apiUrl1), + createCloudNativeDk(t, "cloudnative", apiUrl2), + } + + relevantDirs := cleaner.collectRelevantHostDirs(dks) + + require.NotEmpty(t, relevantDirs) + require.Len(t, relevantDirs, 2) + assert.Contains(t, relevantDirs, cleaner.path.OsAgentDir(dks[0].Name)) + assert.Contains(t, relevantDirs, cleaner.path.OsAgentDir(dks[1].Name)) + assert.NotContains(t, relevantDirs, cleaner.path.OsAgentDir(tenantUUID1)) + assert.NotContains(t, relevantDirs, cleaner.path.OsAgentDir(tenantUUID2)) + }) + + t.Run("relevant dk -> relevant dirs, deprecated(tenantUUID) location dir included if exists", func(t *testing.T) { + cleaner := createCleaner(t) + dks := []dynakube.DynaKube{ + createHostMonDk(t, "hostmon", apiUrl1), + createCloudNativeDk(t, "cloudnative", apiUrl2), + createAppMonDk(t, "appmon", apiUrl1), + } + + cleaner.createHostDirs(t, tenantUUID1) + cleaner.createHostDirs(t, dks[0].Name) + + relevantDirs := cleaner.collectRelevantHostDirs(dks) + + require.NotEmpty(t, relevantDirs) + require.Len(t, relevantDirs, 3) + assert.Contains(t, relevantDirs, cleaner.path.OsAgentDir(dks[0].Name)) + assert.Contains(t, relevantDirs, cleaner.path.OsAgentDir(dks[1].Name)) + assert.NotContains(t, relevantDirs, cleaner.path.OsAgentDir(dks[2].Name)) + assert.Contains(t, relevantDirs, cleaner.path.OsAgentDir(tenantUUID1)) + assert.NotContains(t, relevantDirs, cleaner.path.OsAgentDir(tenantUUID2)) + }) +} + +func createHostMonDk(t *testing.T, name, apiUrl string) dynakube.DynaKube { + t.Helper() + + dk := createBaseDk(t, name, apiUrl) + dk.Spec.OneAgent.HostMonitoring = &oneagent.HostInjectSpec{} + + return dk +} + +func createCloudNativeDk(t *testing.T, name, apiUrl string) dynakube.DynaKube { + t.Helper() + + dk := createBaseDk(t, name, apiUrl) + dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} + + return dk +} diff --git a/pkg/controllers/csi/provisioner/cleanup/run.go b/pkg/controllers/csi/provisioner/cleanup/run.go new file mode 100644 index 0000000000..3ea503f5a9 --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/run.go @@ -0,0 +1,166 @@ +package cleanup + +import ( + "context" + "os" + + dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "github.com/spf13/afero" + "k8s.io/mount-utils" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Cleaner struct { + fs afero.Afero + apiReader client.Reader + mounter mount.Interface + path metadata.PathResolver +} + +// fsState collects all the "top-level" folders we care about and categorizes them +type fsState struct { + // deprecatedDks are the dynakube-dirs under /data that have a /run directory, which used to contain the app-mounts, these directories are named after the tenantUUID + deprecatedDks []string + // binDks are dynakube-dirs that have a "latest-symlink" pointing at a codemodule binary + binDks []string + // hostDks are dynakube-dirs that contain the folder that was mounted to Host OneAgents + hostDks []string +} + +func New(fs afero.Afero, apiReader client.Reader, path metadata.PathResolver, mounter mount.Interface) *Cleaner { + return &Cleaner{ + fs: fs, + apiReader: apiReader, + path: path, + mounter: mounter, + } +} + +// Run will only execute the cleanup logic if enough time has passed from the previous run, to not overload the IO of the node +func (c *Cleaner) Run(ctx context.Context) error { + tickerResetFunc := checkTicker() + if tickerResetFunc == nil { + return nil + } + defer tickerResetFunc() + + return c.run(ctx) +} + +// InstantRun will always execute the cleanup logic ignoring the time passed from previous run +func (c *Cleaner) InstantRun(ctx context.Context) error { + defer resetTickerAfterDelete() + + return c.run(ctx) +} + +func (c *Cleaner) run(ctx context.Context) error { + fsState, err := c.getFilesystemState() + if err != nil { + return err + } + + c.removeDeprecatedMounts(fsState) + + dks, err := metadata.GetRelevantDynaKubes(ctx, c.apiReader) + if err != nil { + log.Info("failed to list available dynakubes, skipping cleanup") + + return err + } + + c.removeHostMounts(dks, fsState) + c.removeUnusedBinaries(dks, fsState) + + return nil +} + +func (c *Cleaner) getFilesystemState() (fsState fsState, err error) { //nolint:revive + rootSubDirs, err := c.fs.ReadDir(c.path.RootDir) + if err != nil { + log.Info("failed to list the contents of the root directory of the csi-provisioner", "rootDir", c.path.RootDir) + + return fsState, err + } + + var unknownDirs []string + + for _, fileInfo := range rootSubDirs { + if !fileInfo.IsDir() || + fileInfo.Name() == dtcsi.SharedAppMountsDir || + fileInfo.Name() == dtcsi.SharedAgentBinDir { + continue + } + + deprecatedExists, _ := c.fs.Exists(c.path.AgentRunDir(fileInfo.Name())) + if deprecatedExists { + fsState.deprecatedDks = append(fsState.deprecatedDks, fileInfo.Name()) + } + + binExists, _ := c.fs.Exists(c.path.LatestAgentBinaryForDynaKube(fileInfo.Name())) + if binExists { + fsState.binDks = append(fsState.binDks, fileInfo.Name()) + } + + hostExists, _ := c.fs.Exists(c.path.OsAgentDir(fileInfo.Name())) + if hostExists { + fsState.hostDks = append(fsState.hostDks, fileInfo.Name()) + } + + if !deprecatedExists && !binExists && !hostExists { + unknownDirs = append(unknownDirs, c.path.DynaKubeDir(fileInfo.Name())) + } + } + + for _, unknown := range unknownDirs { + log.Info("removing unknown path", "path", unknown) + _ = c.fs.RemoveAll(unknown) + } + + return fsState, nil +} + +// safeAddRelevantPath follows the symlink that is provided in the `path` param and adds the actual path to the provided map +// It checks for the existence of the path and verifies if it is a symlink. +// Trying to follow a path that is not a symlink will case an error. +// Should be used for paths that are "maybe" symlinks, more expensive then its addRelevantPath. +func (c *Cleaner) safeAddRelevantPath(path string, relevantPaths map[string]bool) { + fInfo, err := c.fs.Stat(path) + if err != nil { + if !os.IsNotExist(err) { + log.Error(err, "failed to check if host mount directory is a symlink") + } + + return + } + + if fInfo.Mode() != os.ModeSymlink { + relevantPaths[path] = true + + return + } + + c.addRelevantPath(path, relevantPaths) +} + +// addRelevantPath follows the symlink that is provided in the `path` param and adds the actual path to the provided map +// does no checking for the existence of the path and does not verify if it is a symlink. +// Should be used for paths that are 100% to be symlinks to save on IO. +func (c *Cleaner) addRelevantPath(path string, relevantPaths map[string]bool) { + linker, ok := c.fs.Fs.(afero.LinkReader) + if ok { + actualPath, err := linker.ReadlinkIfPossible(path) + if err != nil { + log.Error(err, "failed to follow symlink", "path", path) + + return + } + + relevantPaths[actualPath] = true + } else { // only should happen during tests + log.Info("following symlinks not possible, unexpected behavior") + + relevantPaths[path] = true + } +} diff --git a/pkg/controllers/csi/provisioner/cleanup/run_test.go b/pkg/controllers/csi/provisioner/cleanup/run_test.go new file mode 100644 index 0000000000..55c186396d --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/run_test.go @@ -0,0 +1,170 @@ +package cleanup + +import ( + "os" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "github.com/spf13/afero" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/mount-utils" +) + +func TestGetFilesystemState(t *testing.T) { + t.Run("no error on empty FS", func(t *testing.T) { + cleaner := createCleaner(t) + + fsState, err := cleaner.getFilesystemState() + + require.NoError(t, err) + assert.Empty(t, fsState) + }) + t.Run("remove unknown dirs", func(t *testing.T) { + cleaner := createCleaner(t) + + cleaner.fs.Mkdir(cleaner.path.DynaKubeDir("test1"), os.ModePerm) + cleaner.fs.Mkdir(cleaner.path.DynaKubeDir("test2"), os.ModePerm) + + files, err := cleaner.fs.ReadDir(cleaner.path.RootDir) + require.NoError(t, err) + assert.Len(t, files, 2) + + fsState, err := cleaner.getFilesystemState() + + require.NoError(t, err) + assert.Empty(t, fsState) + + files, err = cleaner.fs.ReadDir(cleaner.path.RootDir) + require.NoError(t, err) + assert.Empty(t, files) + }) + t.Run("don't touch unknown files, to keep the db intact, just in case", func(t *testing.T) { + cleaner := createCleaner(t) + + cleaner.fs.Create(cleaner.path.DynaKubeDir("test1")) + cleaner.fs.Create(cleaner.path.DynaKubeDir("test2")) + + files, err := cleaner.fs.ReadDir(cleaner.path.RootDir) + require.NoError(t, err) + assert.Len(t, files, 2) + + fsState, err := cleaner.getFilesystemState() + + require.NoError(t, err) + assert.Empty(t, fsState) + + files, err = cleaner.fs.ReadDir(cleaner.path.RootDir) + require.NoError(t, err) + assert.Len(t, files, 2) + }) + t.Run("don't touch well-known dirs", func(t *testing.T) { + cleaner := createCleaner(t) + + cleaner.fs.Mkdir(cleaner.path.AgentSharedBinaryDirBase(), os.ModePerm) + cleaner.fs.Mkdir(cleaner.path.AppMountsBaseDir(), os.ModePerm) + + files, err := cleaner.fs.ReadDir(cleaner.path.RootDir) + require.NoError(t, err) + assert.Len(t, files, 2) + + fsState, err := cleaner.getFilesystemState() + + require.NoError(t, err) + assert.Empty(t, fsState) + + files, err = cleaner.fs.ReadDir(cleaner.path.RootDir) + require.NoError(t, err) + assert.Len(t, files, 2) + }) + + t.Run("get fsState", func(t *testing.T) { + cleaner := createCleaner(t) + + dkName1 := "dk1" + dkName2 := "dk2" + dkName3 := "dk3" + + cleaner.createDeprecatedDirs(t, dkName1, 0, 2) + + cleaner.createBinDirs(t, dkName1) + cleaner.createBinDirs(t, dkName2) + + cleaner.createHostDirs(t, dkName2) + cleaner.createHostDirs(t, dkName3) + + fsState, err := cleaner.getFilesystemState() + require.NoError(t, err) + + assert.Len(t, fsState.deprecatedDks, 1) + assert.Contains(t, fsState.deprecatedDks, dkName1) + + assert.Len(t, fsState.binDks, 2) + assert.Contains(t, fsState.binDks, dkName1) + assert.Contains(t, fsState.binDks, dkName2) + + assert.Len(t, fsState.hostDks, 2) + assert.Contains(t, fsState.hostDks, dkName2) + assert.Contains(t, fsState.hostDks, dkName3) + }) +} + +func TestSafeAddRelevantPath(t *testing.T) { + t.Run("no error if path doesn't exist and no addition", func(t *testing.T) { + cleaner := createCleaner(t) + + relevantPaths := map[string]bool{} + + cleaner.safeAddRelevantPath("something", relevantPaths) + assert.Empty(t, relevantPaths) + }) + + t.Run("not symlink => added without change", func(t *testing.T) { + cleaner := createCleaner(t) + path := "something" + cleaner.fs.Mkdir(path, os.ModePerm) + + relevantPaths := map[string]bool{} + + cleaner.safeAddRelevantPath(path, relevantPaths) + assert.Contains(t, relevantPaths, path) + }) + + t.Run("symlink => would be added after following the link", func(t *testing.T) { + // can't be tested, as it relies on following symlinks + t.SkipNow() + }) +} + +func TestAddRelevantPath(t *testing.T) { + // can't be tested, as it relies on following symlinks + t.SkipNow() +} + +func createCleaner(t *testing.T) *Cleaner { + t.Helper() + + return &Cleaner{ + fs: afero.Afero{Fs: afero.NewMemMapFs()}, + mounter: mount.NewFakeMounter(nil), + apiReader: fake.NewClient(), + path: metadata.PathResolver{}, + } +} + +func (c *Cleaner) createBinDirs(t *testing.T, name string) { + t.Helper() + + binDir := c.path.LatestAgentBinaryForDynaKube(name) + err := c.fs.MkdirAll(binDir, os.ModePerm) + require.NoError(t, err) +} + +func (c *Cleaner) createHostDirs(t *testing.T, name string) { + t.Helper() + + hostDir := c.path.OsAgentDir(name) + err := c.fs.MkdirAll(hostDir, os.ModePerm) + require.NoError(t, err) +} diff --git a/pkg/controllers/csi/provisioner/cleanup/ticker.go b/pkg/controllers/csi/provisioner/cleanup/ticker.go new file mode 100644 index 0000000000..a90f898921 --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/ticker.go @@ -0,0 +1,75 @@ +package cleanup + +import ( + "os" + "sync" + "time" +) + +const ( + defaultCleanupPeriod = "30m" + cleanupEnv = "CLEANUP_PERIOD" +) + +var ( + cleanupPeriod time.Duration + ticker *time.Ticker +) + +// checkTicker will initialize (if needed) and check the a ticker if enough time has passed since the last cleanup +func checkTicker() func() { + setupCleanUpPeriod() + + if ticker == nil { + log.Info("initial run of CSI filesystem cleanup") + + return func() { + ticker = time.NewTicker(cleanupPeriod) + } + } + + select { + case <-ticker.C: + log.Info("running CSI filesystem cleanup") + + return func() { + ticker.Reset(cleanupPeriod) + } + default: + log.Info("skipping CSI filesystem cleanup, it only runs every given period", "period", cleanupPeriod.String()) + + return nil + } +} + +func setupCleanUpPeriod() { + sync.OnceFunc(func() { + rawDuration := os.Getenv(cleanupEnv) + + duration, err := time.ParseDuration(rawDuration) + if err != nil { + if rawDuration != "" { + log.Info("custom cleanup period could be parsed, falling back to default", "env", cleanupEnv, "value", rawDuration, "default", defaultCleanupPeriod) + } + + duration, _ = time.ParseDuration(defaultCleanupPeriod) + } + + cleanupPeriod = duration + })() +} + +// resetTickerAfterDelete is for the specific scenario of dynakube deletion +// its purpose is to reset the ticker safely, but not check it, so the cleanup will always run after a DynaKube deletion +// meant to be called via defer +func resetTickerAfterDelete() { + setupCleanUpPeriod() + + if ticker == nil { + log.Info("initial run of CSI filesystem cleanup") + + ticker = time.NewTicker(cleanupPeriod) + } else { + ticker.Reset(cleanupPeriod) + } +} diff --git a/pkg/controllers/csi/provisioner/cleanup/ticker_test.go b/pkg/controllers/csi/provisioner/cleanup/ticker_test.go new file mode 100644 index 0000000000..b5c7529606 --- /dev/null +++ b/pkg/controllers/csi/provisioner/cleanup/ticker_test.go @@ -0,0 +1,49 @@ +package cleanup + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestTicker(t *testing.T) { + customCleanUpPeriod := "22m" + t.Setenv(cleanupEnv, customCleanUpPeriod) + + parsedDuration, _ := time.ParseDuration(customCleanUpPeriod) + + // Initially cleanup period is not set + require.Empty(t, cleanupPeriod) + + // Initially ticker is not set + require.Nil(t, ticker) + + // Works with nil ticker + resetTickerAfterDelete() + + // ticker is now set + require.NotNil(t, ticker) + // cleanup period is now set and respects env + require.Equal(t, parsedDuration, cleanupPeriod) + + // Works with not-nil ticker + resetTickerAfterDelete() + + ticker.Stop() + ticker = nil + + // Works with nil ticker + resetFunc := checkTicker() + require.NotNil(t, resetFunc) + require.Nil(t, ticker) + + resetFunc() + require.NotNil(t, ticker) + + // Works with not-nil ticker + resetFunc = checkTicker() + require.Nil(t, resetFunc) + + ticker.Stop() +} diff --git a/pkg/controllers/csi/provisioner/config.go b/pkg/controllers/csi/provisioner/config.go index 608fb0617a..a550d85ce5 100644 --- a/pkg/controllers/csi/provisioner/config.go +++ b/pkg/controllers/csi/provisioner/config.go @@ -4,11 +4,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/logd" ) -const ( - failedInstallAgentVersionEvent = "FailedInstallAgentVersion" - installAgentVersionEvent = "InstallAgentVersion" -) - var ( log = logd.Get().WithName("csi-provisioner") ) diff --git a/pkg/controllers/csi/provisioner/controller.go b/pkg/controllers/csi/provisioner/controller.go index 5287797105..f5bd45f54d 100644 --- a/pkg/controllers/csi/provisioner/controller.go +++ b/pkg/controllers/csi/provisioner/controller.go @@ -18,16 +18,14 @@ package csiprovisioner import ( "context" - "fmt" "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" - csigc "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/gc" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/provisioner/cleanup" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dynatraceclient" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/image" @@ -35,8 +33,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/afero" k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/tools/record" + "k8s.io/mount-utils" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -54,34 +51,29 @@ type imageInstallerBuilder func(context.Context, afero.Fs, *image.Properties) (i // OneAgentProvisioner reconciles a DynaKube object type OneAgentProvisioner struct { - client client.Client apiReader client.Reader fs afero.Fs - recorder record.EventRecorder - db metadata.Access - gc reconcile.Reconciler dynatraceClientBuilder dynatraceclient.Builder urlInstallerBuilder urlInstallerBuilder imageInstallerBuilder imageInstallerBuilder - opts dtcsi.CSIOptions + cleaner *cleanup.Cleaner path metadata.PathResolver } // NewOneAgentProvisioner returns a new OneAgentProvisioner -func NewOneAgentProvisioner(mgr manager.Manager, opts dtcsi.CSIOptions, db metadata.Access) *OneAgentProvisioner { +func NewOneAgentProvisioner(mgr manager.Manager, opts dtcsi.CSIOptions) *OneAgentProvisioner { + fs := afero.NewOsFs() + path := metadata.PathResolver{RootDir: opts.RootDir} + return &OneAgentProvisioner{ - client: mgr.GetClient(), apiReader: mgr.GetAPIReader(), - opts: opts, - fs: afero.NewOsFs(), - recorder: mgr.GetEventRecorderFor("OneAgentProvisioner"), - db: db, - path: metadata.PathResolver{RootDir: opts.RootDir}, - gc: csigc.NewCSIGarbageCollector(mgr.GetAPIReader(), opts, db), + fs: fs, + path: path, dynatraceClientBuilder: dynatraceclient.NewBuilder(mgr.GetAPIReader()), urlInstallerBuilder: url.NewUrlInstaller, imageInstallerBuilder: image.NewImageInstaller, + cleaner: cleanup.New(afero.Afero{Fs: fs}, mgr.GetAPIReader(), path, mount.New("")), } } @@ -95,19 +87,26 @@ func (provisioner *OneAgentProvisioner) SetupWithManager(mgr ctrl.Manager) error func (provisioner *OneAgentProvisioner) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { log.Info("reconciling DynaKube", "namespace", request.Namespace, "dynakube", request.Name) - dk, err := provisioner.getDynaKube(ctx, request.NamespacedName) + var dk dynakube.DynaKube + + err := provisioner.apiReader.Get(ctx, request.NamespacedName, &dk) if err != nil { if k8serrors.IsNotFound(err) { - return reconcile.Result{}, provisioner.db.DeleteDynakube(ctx, request.Name) + err = provisioner.cleaner.InstantRun(ctx) + if err != nil { + log.Error(err, "failed to run clean-up after dynakube deletion") + } + + return reconcile.Result{}, nil } return reconcile.Result{}, err } - if !isProvisionerNeeded(dk) { + if !isProvisionerNeeded(&dk) { log.Info("CSI driver provisioner not needed") - return reconcile.Result{RequeueAfter: longRequeueDuration}, provisioner.db.DeleteDynakube(ctx, request.Name) + return reconcile.Result{RequeueAfter: longRequeueDuration}, provisioner.cleaner.Run(ctx) } err = provisioner.setupFileSystem(dk) @@ -115,189 +114,50 @@ func (provisioner *OneAgentProvisioner) Reconcile(ctx context.Context, request r return reconcile.Result{}, err } - dynakubeMetadata, err := provisioner.setupDynakubeMetadata(ctx, dk) // needed for the CSI-resilience feature - if err != nil { - return reconcile.Result{}, err - } - if !dk.OneAgent().IsAppInjectionNeeded() { log.Info("app injection not necessary, skip agent codemodule download", "dynakube", dk.Name) + _ = provisioner.cleaner.Run(ctx) + return reconcile.Result{RequeueAfter: longRequeueDuration}, nil } if dk.OneAgent().GetCodeModulesImage() == "" && dk.OneAgent().GetCodeModulesVersion() == "" { log.Info("dynakube status is not yet ready, requeuing", "dynakube", dk.Name) - return reconcile.Result{RequeueAfter: shortRequeueDuration}, err + return reconcile.Result{RequeueAfter: shortRequeueDuration}, nil } - err = provisioner.provisionCodeModules(ctx, dk, dynakubeMetadata) + err = provisioner.installAgent(ctx, dk) if err != nil { return reconcile.Result{}, err } - err = provisioner.collectGarbage(ctx, request) - if err != nil { - return reconcile.Result{}, err - } + _ = provisioner.cleaner.Run(ctx) return reconcile.Result{RequeueAfter: defaultRequeueDuration}, nil } func isProvisionerNeeded(dk *dynakube.DynaKube) bool { - return dk.OneAgent().IsCloudNativeFullstackMode() || - dk.OneAgent().IsApplicationMonitoringMode() || - dk.OneAgent().IsHostMonitoringMode() + return dk.OneAgent().IsAppInjectionNeeded() || dk.OneAgent().IsReadOnlyOneAgentsMode() } -func (provisioner *OneAgentProvisioner) setupFileSystem(dk *dynakube.DynaKube) error { - tenantUUID, err := dk.TenantUUIDFromApiUrl() - if err != nil { - return err - } - - if err := provisioner.createCSIDirectories(tenantUUID); err != nil { - log.Error(err, "error when creating csi directories", "path", provisioner.path.TenantDir(tenantUUID)) - - return errors.WithStack(err) +func (provisioner *OneAgentProvisioner) setupFileSystem(dk dynakube.DynaKube) error { + dynakubeDir := provisioner.path.DynaKubeDir(dk.GetName()) + if err := provisioner.fs.MkdirAll(dynakubeDir, 0755); err != nil { + return errors.WithMessagef(err, "failed to create directory %s", dynakubeDir) } - log.Info("csi directories exist", "path", provisioner.path.TenantDir(tenantUUID)) - - return nil -} - -func (provisioner *OneAgentProvisioner) setupDynakubeMetadata(ctx context.Context, dk *dynakube.DynaKube) (*metadata.Dynakube, error) { - dynakubeMetadata, oldDynakubeMetadata, err := provisioner.handleMetadata(ctx, dk) - if err != nil { - return nil, err - } - - // Create/update the dynakubeMetadata entry while `LatestVersion` is not necessarily set - // so the host oneagent-storages can be mounted before the standalone agent binaries are ready to be mounted - return dynakubeMetadata, provisioner.createOrUpdateDynakubeMetadata(ctx, oldDynakubeMetadata, dynakubeMetadata) -} - -func (provisioner *OneAgentProvisioner) collectGarbage(ctx context.Context, request reconcile.Request) error { - _, err := provisioner.gc.Reconcile(ctx, request) - - return err -} - -func (provisioner *OneAgentProvisioner) provisionCodeModules(ctx context.Context, dk *dynakube.DynaKube, dynakubeMetadata *metadata.Dynakube) error { - oldDynakubeMetadata := *dynakubeMetadata - // creates a dt client and checks tokens exist for the given dynakube - dtc, err := buildDtc(provisioner, ctx, dk) - if err != nil { - return err - } - - requeue, err := provisioner.updateAgentInstallation(ctx, dtc, dynakubeMetadata, dk) - if requeue || err != nil { - return err - } - - // Set/Update the `LatestVersion` field in the database entry - err = provisioner.createOrUpdateDynakubeMetadata(ctx, oldDynakubeMetadata, dynakubeMetadata) - if err != nil { - return err - } - - return nil -} - -func (provisioner *OneAgentProvisioner) updateAgentInstallation( - ctx context.Context, dtc dtclient.Client, - dynakubeMetadata *metadata.Dynakube, - dk *dynakube.DynaKube, -) ( - requeue bool, - err error, -) { - latestProcessModuleConfig, err := processmoduleconfigsecret.GetSecretData(ctx, provisioner.apiReader, dk.Name, dk.Namespace) - if err != nil { - return false, err - } - - if dk.OneAgent().GetCodeModulesImage() != "" { - updatedDigest, err := provisioner.installAgentImage(ctx, *dk, latestProcessModuleConfig) - if err != nil { - log.Info("error when updating agent from image", "error", err.Error()) - // reporting error but not returning it to avoid immediate requeue and subsequently calling the API every few seconds - return true, nil - } else if updatedDigest != "" { - dynakubeMetadata.LatestVersion = "" - dynakubeMetadata.ImageDigest = updatedDigest - } - } else { - updateVersion, err := provisioner.installAgentZip(ctx, *dk, dtc, latestProcessModuleConfig) - if err != nil { - log.Info("error when updating agent from zip", "error", err.Error()) - // reporting error but not returning it to avoid immediate requeue and subsequently calling the API every few seconds - return true, nil - } else if updateVersion != "" { - dynakubeMetadata.LatestVersion = updateVersion - dynakubeMetadata.ImageDigest = "" - } - } - - return false, nil -} - -func (provisioner *OneAgentProvisioner) handleMetadata(ctx context.Context, dk *dynakube.DynaKube) (*metadata.Dynakube, metadata.Dynakube, error) { - dynakubeMetadata, err := provisioner.db.GetDynakube(ctx, dk.Name) - if err != nil { - return nil, metadata.Dynakube{}, errors.WithStack(err) - } - - // In case of a new dynakubeMetadata - var oldDynakubeMetadata metadata.Dynakube - if dynakubeMetadata != nil { - oldDynakubeMetadata = *dynakubeMetadata - } - - tenantUUID, err := dk.TenantUUIDFromApiUrl() - if err != nil { - return nil, metadata.Dynakube{}, err - } - - dynakubeMetadata = metadata.NewDynakube( - dk.Name, - tenantUUID, - oldDynakubeMetadata.LatestVersion, - oldDynakubeMetadata.ImageDigest, - dk.FeatureMaxFailedCsiMountAttempts()) - - return dynakubeMetadata, oldDynakubeMetadata, nil -} - -func (provisioner *OneAgentProvisioner) createOrUpdateDynakubeMetadata(ctx context.Context, oldDynakube metadata.Dynakube, dynakube *metadata.Dynakube) error { - if oldDynakube != *dynakube { - log.Info("dynakube has changed", - "name", dynakube.Name, - "tenantUUID", dynakube.TenantUUID, - "version", dynakube.LatestVersion, - "max mount attempts", dynakube.MaxFailedMountAttempts) - - if oldDynakube == (metadata.Dynakube{}) { - log.Info("adding dynakube to db", "tenantUUID", dynakube.TenantUUID, "version", dynakube.LatestVersion) - - return provisioner.db.InsertDynakube(ctx, dynakube) - } else { - log.Info("updating dynakube in db", - "old version", oldDynakube.LatestVersion, "new version", dynakube.LatestVersion, - "old tenantUUID", oldDynakube.TenantUUID, "new tenantUUID", dynakube.TenantUUID) - - return provisioner.db.UpdateDynakube(ctx, dynakube) - } + agentBinaryDir := provisioner.path.AgentSharedBinaryDirBase() + if err := provisioner.fs.MkdirAll(agentBinaryDir, 0755); err != nil { + return errors.WithMessagef(err, "failed to create directory %s", agentBinaryDir) } return nil } -func buildDtc(provisioner *OneAgentProvisioner, ctx context.Context, dk *dynakube.DynaKube) (dtclient.Client, error) { - tokenReader := token.NewReader(provisioner.apiReader, dk) +func buildDtc(provisioner *OneAgentProvisioner, ctx context.Context, dk dynakube.DynaKube) (dtclient.Client, error) { + tokenReader := token.NewReader(provisioner.apiReader, &dk) tokens, err := tokenReader.ReadTokens(ctx) if err != nil { @@ -306,34 +166,13 @@ func buildDtc(provisioner *OneAgentProvisioner, ctx context.Context, dk *dynakub dynatraceClient, err := provisioner.dynatraceClientBuilder. SetContext(ctx). - SetDynakube(*dk). + SetDynakube(dk). SetTokens(tokens). Build() if err != nil { - return nil, fmt.Errorf("failed to create Dynatrace client: %w", err) + return nil, errors.WithMessage(err, "failed to create Dynatrace client") } return dynatraceClient, nil } - -func (provisioner *OneAgentProvisioner) getDynaKube(ctx context.Context, name types.NamespacedName) (*dynakube.DynaKube, error) { - var dk dynakube.DynaKube - err := provisioner.apiReader.Get(ctx, name, &dk) - - return &dk, err -} - -func (provisioner *OneAgentProvisioner) createCSIDirectories(tenantUUID string) error { - tenantDir := provisioner.path.TenantDir(tenantUUID) - if err := provisioner.fs.MkdirAll(tenantDir, 0755); err != nil { - return fmt.Errorf("failed to create directory %s: %w", tenantDir, err) - } - - agentBinaryDir := provisioner.path.AgentBinaryDir(tenantUUID) - if err := provisioner.fs.MkdirAll(agentBinaryDir, 0755); err != nil { - return fmt.Errorf("failed to create directory %s: %w", agentBinaryDir, err) - } - - return nil -} diff --git a/pkg/controllers/csi/provisioner/controller_test.go b/pkg/controllers/csi/provisioner/controller_test.go index 0e03aa74f7..3b0060aa0c 100644 --- a/pkg/controllers/csi/provisioner/controller_test.go +++ b/pkg/controllers/csi/provisioner/controller_test.go @@ -2,712 +2,345 @@ package csiprovisioner import ( "context" - "encoding/base64" + "encoding/json" "errors" "os" "path/filepath" - "strings" "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/provisioner/cleanup" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dynatraceclient" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/image" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/url" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/processmoduleconfig" + dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" dtbuildermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/controllers/dynakube/dynatraceclient" installermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/injection/codemodule/installer" - reconcilermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/tools/record" + "k8s.io/mount-utils" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -const ( - testAPIURL = "http://test-uid/api" - tenantUUID = "test-uid" - dkName = "dynakube-test" - testNamespace = "test-namespace" - testVersion = "1.2.3" - testImageID = "test-image-id" - otherDkName = "other-dk" - errorMsg = "test-error" - agentVersion = "12345" - testRuxitConf = ` -[general] -key value -` -) - -type mkDirAllErrorFs struct { - afero.Fs -} - -func (fs *mkDirAllErrorFs) MkdirAll(_ string, _ os.FileMode) error { - return errors.New(errorMsg) -} - -func TestOneAgentProvisioner_Reconcile(t *testing.T) { +func TestReconcile(t *testing.T) { ctx := context.Background() - dynakubeName := "test-dk" - - t.Run("no dynakube instance", func(t *testing.T) { - gc := reconcilermock.NewReconciler[reconcile.Request](t) - provisioner := &OneAgentProvisioner{ - apiReader: fake.NewClient(), - db: metadata.FakeMemoryDB(), - gc: gc, - } - result, err := provisioner.Reconcile(context.TODO(), reconcile.Request{}) - require.NoError(t, err) - require.NotNil(t, result) - require.Equal(t, reconcile.Result{}, result) - }) - t.Run("dynakube deleted", func(t *testing.T) { - gc := reconcilermock.NewReconciler[reconcile.Request](t) - db := metadata.FakeMemoryDB() - metadataDk := metadata.Dynakube{TenantUUID: tenantUUID, LatestVersion: agentVersion, Name: dkName} - _ = db.InsertDynakube(ctx, &metadataDk) - provisioner := &OneAgentProvisioner{ - apiReader: fake.NewClient(), - db: db, - gc: gc, - } - result, err := provisioner.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: metadataDk.Name}}) + t.Run("no dynakube(ie.: delete case) => do nothing, no error", func(t *testing.T) { // TODO: Replace "do nothing" with "run GC" + prov := createProvisioner(t) + dk := createDynaKubeBase(t) + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) require.NoError(t, err) require.NotNil(t, result) - require.Equal(t, reconcile.Result{}, result) - ten, err := db.GetDynakube(ctx, metadataDk.TenantUUID) - require.NoError(t, err) - require.Nil(t, ten) + assert.False(t, areFsDirsCreated(t, prov, dk)) }) - t.Run("csi driver not used (classicFullstack)", func(t *testing.T) { - gc := reconcilermock.NewReconciler[reconcile.Request](t) - provisioner := &OneAgentProvisioner{ - apiReader: fake.NewClient( - &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: dynakubeName, - }, - Spec: dynakube.DynaKubeSpec{ - OneAgent: oneagent.Spec{ - ClassicFullStack: &oneagent.HostInjectSpec{}, - }, - }, - }, - ), - db: metadata.FakeMemoryDB(), - gc: gc, - } - result, err := provisioner.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: dynakubeName}}) - require.NoError(t, err) - require.NotNil(t, result) - require.Equal(t, reconcile.Result{RequeueAfter: longRequeueDuration}, result) - }) - t.Run("host monitoring used", func(t *testing.T) { - fakeClient := fake.NewClient( - addFakeTenantUUID( - &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: testAPIURL, - OneAgent: oneagent.Spec{ - HostMonitoring: &oneagent.HostInjectSpec{}, - }, - }, - }, - ), - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Data: map[string][]byte{ - dtclient.ApiToken: []byte("api-token"), - }, - }, - ) - mockDtcBuilder := dtbuildermock.NewBuilder(t) - - gc := reconcilermock.NewReconciler[reconcile.Request](t) - db := metadata.FakeMemoryDB() - - provisioner := &OneAgentProvisioner{ - apiReader: fakeClient, - client: fakeClient, - fs: afero.NewMemMapFs(), - db: db, - gc: gc, - path: metadata.PathResolver{}, - dynatraceClientBuilder: mockDtcBuilder, - } - result, err := provisioner.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: dkName}}) + t.Run("dynakube doesn't need app-injection => no error, long requeue", func(t *testing.T) { + dk := createDynaKubeNoCSI(t) + prov := createProvisioner(t, dk) + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) require.NoError(t, err) require.NotNil(t, result) - require.Equal(t, reconcile.Result{RequeueAfter: longRequeueDuration}, result) + assert.Equal(t, longRequeueDuration, result.RequeueAfter) - dynakubeMetadatas, err := db.GetAllDynakubes(ctx) - require.NoError(t, err) - require.Len(t, dynakubeMetadatas, 1) + assert.False(t, areFsDirsCreated(t, prov, dk)) }) - t.Run("no tokens", func(t *testing.T) { - gc := reconcilermock.NewReconciler[reconcile.Request](t) - provisioner := &OneAgentProvisioner{ - apiReader: fake.NewClient( - addFakeTenantUUID( - &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: testAPIURL, - OneAgent: oneagent.Spec{ - ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), - }, - }, - Status: dynakube.DynaKubeStatus{ - CodeModules: oneagent.CodeModulesStatus{ - VersionStatus: status.VersionStatus{ - Version: "1.2.3", - }, - }, - }, - }, - ), - ), - gc: gc, - db: metadata.FakeMemoryDB(), - fs: afero.NewMemMapFs(), - } - result, err := provisioner.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: dkName}}) - require.EqualError(t, err, `secrets "`+dkName+`" not found`) - require.NotNil(t, result) - }) - t.Run("error when creating dynatrace client", func(t *testing.T) { - gc := reconcilermock.NewReconciler[reconcile.Request](t) - mockDtcBuilder := dtbuildermock.NewBuilder(t) - mockDtcBuilder.On("SetContext", mock.Anything).Return(mockDtcBuilder) - mockDtcBuilder.On("SetDynakube", mock.Anything).Return(mockDtcBuilder) - mockDtcBuilder.On("SetTokens", mock.Anything).Return(mockDtcBuilder) - mockDtcBuilder.On("Build").Return(nil, errors.New(errorMsg)) - - provisioner := &OneAgentProvisioner{ - apiReader: fake.NewClient( - addFakeTenantUUID( - &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: testAPIURL, - OneAgent: oneagent.Spec{ - ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), - }, - }, - Status: dynakube.DynaKubeStatus{ - CodeModules: oneagent.CodeModulesStatus{ - VersionStatus: status.VersionStatus{ - Version: "1.2.3", - }, - }, - }, - }, - ), - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Data: map[string][]byte{ - dtclient.ApiToken: []byte("test-value"), - }, - }, - ), - dynatraceClientBuilder: mockDtcBuilder, - gc: gc, - db: metadata.FakeMemoryDB(), - fs: afero.NewMemMapFs(), - } - result, err := provisioner.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: dkName}}) + t.Run("dynakube status not ready => only setup base fs, no error, short requeue", func(t *testing.T) { + dk := createNotReadyDynaKube(t) + prov := createProvisioner(t, dk) - require.EqualError(t, err, "failed to create Dynatrace client: "+errorMsg) - require.NotNil(t, result) - }) - t.Run("error creating directories", func(t *testing.T) { - gc := reconcilermock.NewReconciler[reconcile.Request](t) - errorfs := &mkDirAllErrorFs{ - Fs: afero.NewMemMapFs(), - } - mockDtcBuilder := dtbuildermock.NewBuilder(t) - provisioner := &OneAgentProvisioner{ - apiReader: fake.NewClient( - addFakeTenantUUID( - &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: testAPIURL, - OneAgent: oneagent.Spec{ - ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), - }, - }, - }, - ), - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Data: map[string][]byte{ - dtclient.ApiToken: []byte("api-token"), - }, - }, - ), - dynatraceClientBuilder: mockDtcBuilder, - fs: errorfs, - db: metadata.FakeMemoryDB(), - gc: gc, - } - result, err := provisioner.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: dkName}}) - - require.EqualError(t, err, "failed to create directory "+tenantUUID+": "+errorMsg) + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) + require.NoError(t, err) require.NotNil(t, result) - require.Equal(t, reconcile.Result{}, result) + assert.Equal(t, shortRequeueDuration, result.RequeueAfter) - // Logging newline so go test can parse the output correctly - log.Info("") + assert.True(t, areFsDirsCreated(t, prov, dk)) }) - t.Run("error getting latest agent version", func(t *testing.T) { - gc := reconcilermock.NewReconciler[reconcile.Request](t) - memFs := afero.NewMemMapFs() - mockDtcBuilder := dtbuildermock.NewBuilder(t) - dynakube := addFakeTenantUUID( - &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: testAPIURL, - OneAgent: oneagent.Spec{ - ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), - }, - }, - }, - ) - installerMock := installermock.NewInstaller(t) - - provisioner := &OneAgentProvisioner{ - apiReader: fake.NewClient( - dynakube, - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Data: map[string][]byte{ - dtclient.ApiToken: []byte("api-token"), - }, - }, - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: dynakube.OneAgent().GetTenantSecret(), - }, - Data: map[string][]byte{ - connectioninfo.TenantTokenKey: []byte("tenant-token"), - }, - }, - ), - dynatraceClientBuilder: mockDtcBuilder, - fs: memFs, - db: metadata.FakeMemoryDB(), - recorder: &record.FakeRecorder{}, - gc: gc, - urlInstallerBuilder: mockUrlInstallerBuilder(installerMock), - } - - result, err := provisioner.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: dkName}}) - // "go test" breaks if the output does not end with a newline - // making sure one is printed here - log.Info("") + t.Run("dynakube with version => url installer used, no error", func(t *testing.T) { + dk := createDynaKubeWithVersion(t) + prov := createProvisioner(t, dk, createToken(t, dk), createPMCSecret(t, dk)) + installer := createSuccessfulInstaller(t) + prov.urlInstallerBuilder = mockUrlInstallerBuilder(t, installer) + prov.dynatraceClientBuilder = mockSuccessfulDtClientBuilder(t) + createPMCSourceFile(t, prov, dk) + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) require.NoError(t, err) - require.NotEmpty(t, result) - - exists, err := afero.Exists(memFs, tenantUUID) + require.NotNil(t, result) + assert.Equal(t, defaultRequeueDuration, result.RequeueAfter) - require.NoError(t, err) - require.True(t, exists) + assert.True(t, areFsDirsCreated(t, prov, dk)) + installer.AssertCalled(t, "InstallAgent", mock.Anything, mock.Anything) }) - t.Run("error getting dynakube from db", func(t *testing.T) { - gc := reconcilermock.NewReconciler[reconcile.Request](t) - memFs := afero.NewMemMapFs() - mockDtcBuilder := dtbuildermock.NewBuilder(t) - - provisioner := &OneAgentProvisioner{ - apiReader: fake.NewClient( - &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: testAPIURL, - OneAgent: oneagent.Spec{ - ApplicationMonitoring: buildValidApplicationMonitoringSpec(t), - }, - }, - Status: dynakube.DynaKubeStatus{ - CodeModules: oneagent.CodeModulesStatus{ - VersionStatus: status.VersionStatus{ - Version: "1.2.3", - }, - }, - }, - }, - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - }, - ), - dynatraceClientBuilder: mockDtcBuilder, - fs: memFs, - db: &metadata.FakeFailDB{}, - gc: gc, - } - result, err := provisioner.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: dkName}}) + t.Run("dynakube with version, issue with dtc => fail before installer creation", func(t *testing.T) { + dk := createDynaKubeWithVersion(t) + prov := createProvisioner(t, dk, createToken(t, dk)) + prov.dynatraceClientBuilder = mockFailingDtClientBuilder(t) + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) require.Error(t, err) - require.Empty(t, result) + require.NotNil(t, result) + + assert.True(t, areFsDirsCreated(t, prov, dk)) }) - t.Run("correct directories are created", func(t *testing.T) { - gc := reconcilermock.NewReconciler[reconcile.Request](t) - memFs := afero.NewMemMapFs() - memDB := metadata.FakeMemoryDB() - dynakube := addFakeTenantUUID( - &dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: testAPIURL, - OneAgent: oneagent.Spec{ - HostMonitoring: &oneagent.HostInjectSpec{}, - }, - }, - }, - ) - - r := &OneAgentProvisioner{ - apiReader: fake.NewClient(dynakube), - fs: memFs, - db: memDB, - gc: gc, - } - result, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: dkName}}) + t.Run("dynakube with image => image installer used, dtclient not created, no error", func(t *testing.T) { + dk := createDynaKubeWithImage(t) + prov := createProvisioner(t, dk, createPMCSecret(t, dk)) + installer := createSuccessfulInstaller(t) + prov.imageInstallerBuilder = mockImageInstallerBuilder(t, installer) + createPMCSourceFile(t, prov, dk) + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) require.NoError(t, err) require.NotNil(t, result) + assert.Equal(t, defaultRequeueDuration, result.RequeueAfter) - exists, err := afero.Exists(memFs, tenantUUID) + assert.True(t, areFsDirsCreated(t, prov, dk)) + installer.AssertCalled(t, "InstallAgent", mock.Anything, mock.Anything) + }) - require.NoError(t, err) - require.True(t, exists) + t.Run("installer fails => error", func(t *testing.T) { + dk := createDynaKubeWithImage(t) + prov := createProvisioner(t, dk) + installer := createFailingInstaller(t) + prov.imageInstallerBuilder = mockImageInstallerBuilder(t, installer) - fileInfo, err := memFs.Stat(tenantUUID) + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) + require.Error(t, err) + require.NotNil(t, result) - require.NoError(t, err) - require.True(t, fileInfo.IsDir()) + assert.True(t, areFsDirsCreated(t, prov, dk)) + installer.AssertCalled(t, "InstallAgent", mock.Anything, mock.Anything) }) } -func buildValidApplicationMonitoringSpec(_ *testing.T) *oneagent.ApplicationMonitoringSpec { - return &oneagent.ApplicationMonitoringSpec{} -} +func areFsDirsCreated(t *testing.T, prov OneAgentProvisioner, dk *dynakube.DynaKube) bool { + t.Helper() -func TestProvisioner_CreateDynakube(t *testing.T) { - ctx := context.Background() - db := metadata.FakeMemoryDB() - expectedOtherDynakube := metadata.NewDynakube(otherDkName, tenantUUID, "v1", "", 0) - _ = db.InsertDynakube(ctx, expectedOtherDynakube) - provisioner := &OneAgentProvisioner{ - db: db, + neededFolders := []string{ + prov.path.DynaKubeDir(dk.GetName()), + prov.path.AgentSharedBinaryDirBase(), + } + for _, folder := range neededFolders { + stat, err := prov.fs.Stat(folder) + if err != nil || stat == nil || !stat.IsDir() { + return false + } } - oldDynakube := metadata.Dynakube{} - newDynakube := metadata.NewDynakube(dkName, tenantUUID, "v1", "", 0) - - err := provisioner.createOrUpdateDynakubeMetadata(ctx, oldDynakube, newDynakube) - require.NoError(t, err) + return true +} - dynakube, err := db.GetDynakube(ctx, dkName) - require.NoError(t, err) - require.NotNil(t, dynakube) - require.Equal(t, *newDynakube, *dynakube) +func createProvisioner(t *testing.T, objs ...client.Object) OneAgentProvisioner { + t.Helper() - otherDynakube, err := db.GetDynakube(ctx, otherDkName) - require.NoError(t, err) - require.NotNil(t, dynakube) - require.Equal(t, *expectedOtherDynakube, *otherDynakube) -} + fs := afero.NewMemMapFs() + path := metadata.PathResolver{} + apiReader := fake.NewClient(objs...) -func TestProvisioner_UpdateDynakube(t *testing.T) { - ctx := context.Background() - db := metadata.FakeMemoryDB() - oldDynakube := metadata.NewDynakube(dkName, tenantUUID, "v1", "", 0) - _ = db.InsertDynakube(ctx, oldDynakube) - expectedOtherDynakube := metadata.NewDynakube(otherDkName, tenantUUID, "v1", "", 0) - _ = db.InsertDynakube(ctx, expectedOtherDynakube) - - provisioner := &OneAgentProvisioner{ - db: db, + return OneAgentProvisioner{ + fs: fs, + path: path, + apiReader: apiReader, + cleaner: cleanup.New(afero.Afero{Fs: fs}, apiReader, path, mount.NewFakeMounter(nil)), } - newDynakube := metadata.NewDynakube(dkName, "new-uuid", "v2", "", 0) +} - err := provisioner.createOrUpdateDynakubeMetadata(ctx, *oldDynakube, newDynakube) - require.NoError(t, err) +func createDynaKubeWithVersion(t *testing.T) *dynakube.DynaKube { + t.Helper() - dynakube, err := db.GetDynakube(ctx, dkName) - require.NoError(t, err) - require.NotNil(t, dynakube) - require.Equal(t, *newDynakube, *dynakube) + dk := createDynaKubeBase(t) + version := "test-version" + dk.Spec.OneAgent = oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + Version: version, + }, + } + dk.Status.CodeModules.Version = version - otherDynakube, err := db.GetDynakube(ctx, otherDkName) - require.NoError(t, err) - require.NotNil(t, dynakube) - require.Equal(t, *expectedOtherDynakube, *otherDynakube) + return dk } -func TestUpdateAgentInstallation(t *testing.T) { - ctx := context.Background() +func createDynaKubeWithImage(t *testing.T) *dynakube.DynaKube { + t.Helper() - t.Run("updateAgentInstallation with codeModules enabled", func(t *testing.T) { - dynakube := getDynakube() - enableCodeModules(dynakube) + dk := createDynaKubeBase(t) + imageId := "test-image" + dk.Spec.OneAgent = oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{CodeModulesImage: imageId}, + }, + } + dk.Status.CodeModules.ImageID = imageId - mockDtcBuilder := dtbuildermock.NewBuilder(t) + return dk +} - var dtc dtclient.Client +func createNotReadyDynaKube(t *testing.T) *dynakube.DynaKube { + t.Helper() - mockDtcBuilder.On("Build").Return(dtc, nil) - dtc, err := mockDtcBuilder.Build() - require.NoError(t, err) + dk := createDynaKubeBase(t) + dk.Spec.OneAgent = oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, + } - path := metadata.PathResolver{RootDir: "test"} - base64Image := base64.StdEncoding.EncodeToString([]byte(dynakube.OneAgent().GetCodeModulesImage())) - targetDir := path.AgentSharedBinaryDirForAgent(base64Image) - - mockK8sClient := createMockK8sClient(ctx, dynakube) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), targetDir). - Return(true, nil) - - provisioner := &OneAgentProvisioner{ - db: metadata.FakeMemoryDB(), - dynatraceClientBuilder: mockDtcBuilder, - apiReader: mockK8sClient, - client: mockK8sClient, - path: path, - fs: afero.NewMemMapFs(), - imageInstallerBuilder: mockImageInstallerBuilder(installerMock), - recorder: &record.FakeRecorder{}, - } + return dk +} - ruxitAgentProcPath := filepath.Join(targetDir, "agent", "conf", "ruxitagentproc.conf") - sourceRuxitAgentProcPath := filepath.Join(targetDir, "agent", "conf", "_ruxitagentproc.conf") +func createDynaKubeNoCSI(t *testing.T) *dynakube.DynaKube { + t.Helper() - setUpFS(provisioner.fs, ruxitAgentProcPath, sourceRuxitAgentProcPath) + dk := createDynaKubeBase(t) + dk.Spec.OneAgent = oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, + } - dynakubeMetadata := metadata.Dynakube{TenantUUID: tenantUUID, LatestVersion: agentVersion, Name: dkName} - isRequeue, err := provisioner.updateAgentInstallation(ctx, dtc, &dynakubeMetadata, dynakube) - require.NoError(t, err) + return dk +} - require.Equal(t, "", dynakubeMetadata.LatestVersion) - require.Equal(t, base64Image, dynakubeMetadata.ImageDigest) - assert.False(t, isRequeue) - }) - t.Run("updateAgentInstallation with codeModules enabled errors and requeues", func(t *testing.T) { - dynakube := getDynakube() - enableCodeModules(dynakube) +func createDynaKubeBase(t *testing.T) *dynakube.DynaKube { + t.Helper() - mockDtcBuilder := dtbuildermock.NewBuilder(t) + return &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-dk", + Namespace: "test-ns", + }, + } +} - var dtc dtclient.Client +func createSuccessfulInstaller(t *testing.T) *installermock.Installer { + t.Helper() - mockDtcBuilder.On("Build").Return(dtc, nil) - dtc, err := mockDtcBuilder.Build() - require.NoError(t, err) + m := installermock.NewInstaller(t) + m.On("InstallAgent", mock.Anything, mock.Anything).Return(true, nil) - path := metadata.PathResolver{RootDir: "test"} - base64Image := base64.StdEncoding.EncodeToString([]byte(dynakube.OneAgent().GetCodeModulesImage())) - targetDir := path.AgentSharedBinaryDirForAgent(base64Image) - - mockK8sClient := createMockK8sClient(ctx, dynakube) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), targetDir). - Return(true, nil) - - provisioner := &OneAgentProvisioner{ - db: metadata.FakeMemoryDB(), - dynatraceClientBuilder: mockDtcBuilder, - apiReader: mockK8sClient, - client: mockK8sClient, - path: metadata.PathResolver{RootDir: "test"}, - fs: afero.NewMemMapFs(), - imageInstallerBuilder: mockImageInstallerBuilder(installerMock), - recorder: &record.FakeRecorder{}, - } + return m +} - dynakubeMetadata := metadata.Dynakube{TenantUUID: tenantUUID, LatestVersion: agentVersion, Name: dkName} - isRequeue, err := provisioner.updateAgentInstallation(ctx, dtc, &dynakubeMetadata, dynakube) - require.NoError(t, err) +func createFailingInstaller(t *testing.T) *installermock.Installer { + t.Helper() - require.Equal(t, "12345", dynakubeMetadata.LatestVersion) - require.Equal(t, "", dynakubeMetadata.ImageDigest) - assert.True(t, isRequeue) - }) - t.Run("updateAgentInstallation without codeModules", func(t *testing.T) { - dynakube := getDynakube() + m := installermock.NewInstaller(t) + m.On("InstallAgent", mock.Anything, mock.Anything).Return(false, errors.New("BOOM")) - mockDtcBuilder := dtbuildermock.NewBuilder(t) + return m +} - var dtc dtclient.Client +func mockUrlInstallerBuilder(t *testing.T, mockedInstaller *installermock.Installer) urlInstallerBuilder { + t.Helper() - mockDtcBuilder.On("Build").Return(dtc, nil) - dtc, err := mockDtcBuilder.Build() - require.NoError(t, err) + return func(f afero.Fs, _ dtclient.Client, _ *url.Properties) installer.Installer { + return mockedInstaller + } +} - mockK8sClient := createMockK8sClient(ctx, dynakube) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), "test/codemodules"). - Return(true, nil) - - provisioner := &OneAgentProvisioner{ - db: metadata.FakeMemoryDB(), - dynatraceClientBuilder: mockDtcBuilder, - apiReader: mockK8sClient, - client: mockK8sClient, - path: metadata.PathResolver{RootDir: "test"}, - fs: afero.NewMemMapFs(), - recorder: &record.FakeRecorder{}, - urlInstallerBuilder: mockUrlInstallerBuilder(installerMock), - } - ruxitAgentProcPath := filepath.Join("test", "codemodules", "agent", "conf", "ruxitagentproc.conf") - sourceRuxitAgentProcPath := filepath.Join("test", "codemodules", "agent", "conf", "_ruxitagentproc.conf") +func mockImageInstallerBuilder(t *testing.T, mockedInstaller *installermock.Installer) imageInstallerBuilder { + t.Helper() - setUpFS(provisioner.fs, ruxitAgentProcPath, sourceRuxitAgentProcPath) + return func(_ context.Context, _ afero.Fs, _ *image.Properties) (installer.Installer, error) { + return mockedInstaller, nil + } +} - dynakubeMetadata := metadata.Dynakube{TenantUUID: tenantUUID, LatestVersion: agentVersion, Name: dkName} - isRequeue, err := provisioner.updateAgentInstallation(ctx, dtc, &dynakubeMetadata, dynakube) - require.NoError(t, err) +func createToken(t *testing.T, dk *dynakube.DynaKube) *corev1.Secret { + t.Helper() - require.Equal(t, "12345", dynakubeMetadata.LatestVersion) - require.Equal(t, "", dynakubeMetadata.ImageDigest) - assert.False(t, isRequeue) - }) - t.Run("updateAgentInstallation without codeModules errors and requeues", func(t *testing.T) { - dynakube := getDynakube() + return &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: dk.Tokens(), + Namespace: dk.Namespace, + }, + Data: map[string][]byte{ + dtclient.ApiToken: []byte("this is a token"), + }, + } +} - mockDtcBuilder := dtbuildermock.NewBuilder(t) +func createPMCSecret(t *testing.T, dk *dynakube.DynaKube) *corev1.Secret { + t.Helper() - var dtc dtclient.Client + return &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: dk.GetName() + processmoduleconfigsecret.SecretSuffix, + Namespace: dk.Namespace, + }, + Data: map[string][]byte{ + processmoduleconfigsecret.SecretKeyProcessModuleConfig: getPMC(t), + }, + } +} - mockDtcBuilder.On("Build").Return(dtc, nil) - dtc, err := mockDtcBuilder.Build() - require.NoError(t, err) +func createPMCSourceFile(t *testing.T, prov OneAgentProvisioner, dk *dynakube.DynaKube) { + t.Helper() - mockK8sClient := createMockK8sClient(ctx, dynakube) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), "test/codemodules"). - Return(true, nil) - - provisioner := &OneAgentProvisioner{ - db: metadata.FakeMemoryDB(), - dynatraceClientBuilder: mockDtcBuilder, - apiReader: mockK8sClient, - client: mockK8sClient, - path: metadata.PathResolver{RootDir: "test"}, - fs: afero.NewMemMapFs(), - recorder: &record.FakeRecorder{}, - urlInstallerBuilder: mockUrlInstallerBuilder(installerMock), - } + targetDir, err := prov.getTargetDir(*dk) + require.NoError(t, err) - dynakubeMetadata := metadata.Dynakube{TenantUUID: tenantUUID, LatestVersion: agentVersion, Name: dkName} - isRequeue, err := provisioner.updateAgentInstallation(ctx, dtc, &dynakubeMetadata, dynakube) - require.NoError(t, err) + pmcPath := filepath.Join(targetDir, processmoduleconfig.RuxitAgentProcPath) + pmcDir := filepath.Dir(pmcPath) + require.NoError(t, prov.fs.MkdirAll(pmcDir, os.ModePerm)) - require.Equal(t, "12345", dynakubeMetadata.LatestVersion) - require.Equal(t, "", dynakubeMetadata.ImageDigest) - assert.True(t, isRequeue) - }) + pmcFile, err := prov.fs.OpenFile(pmcPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm) + require.NoError(t, err) + _, err = pmcFile.Write(getPMC(t)) + require.NoError(t, err) } -func createMockK8sClient(ctx context.Context, dynakube *dynakube.DynaKube) client.Client { - mockK8sClient := fake.NewClient(dynakube) - mockK8sClient.Create(ctx, - &corev1.Secret{ - Data: map[string][]byte{processmoduleconfigsecret.SecretKeyProcessModuleConfig: []byte(`{"revision":0,"properties":[]}`)}, - ObjectMeta: metav1.ObjectMeta{ - Name: strings.Join([]string{dkName, "pmc-secret"}, "-"), - Namespace: "test-namespace", - }, +func getPMC(t *testing.T) []byte { + t.Helper() + + pmc := dtclient.ProcessModuleConfig{ + Revision: 0, + Properties: []dtclient.ProcessModuleProperty{ + {Section: "test-section", Key: "test-key", Value: "test-value"}, }, - ) + } - return mockK8sClient -} + pmcJson, err := json.Marshal(pmc) + require.NoError(t, err) -func getDynakube() *dynakube.DynaKube { - return addFakeTenantUUID(&dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: dkName, - Namespace: testNamespace, - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: testAPIURL, - OneAgent: oneagent.Spec{}, - }, - }) + return pmcJson } -func enableCodeModules(dk *dynakube.DynaKube) { - dk.Status.CodeModules = oneagent.CodeModulesStatus{ - VersionStatus: status.VersionStatus{ - Version: testVersion, - ImageID: testImageID, - }, - } -} +func mockFailingDtClientBuilder(t *testing.T) dynatraceclient.Builder { + t.Helper() -func addFakeTenantUUID(dynakube *dynakube.DynaKube) *dynakube.DynaKube { - dynakube.Status.OneAgent.ConnectionInfoStatus.TenantUUID = tenantUUID + mockDtcBuilder := dtbuildermock.NewBuilder(t) + mockDtcBuilder.On("SetContext", mock.Anything).Return(mockDtcBuilder) + mockDtcBuilder.On("SetDynakube", mock.Anything).Return(mockDtcBuilder) + mockDtcBuilder.On("SetTokens", mock.Anything).Return(mockDtcBuilder) + mockDtcBuilder.On("Build", mock.Anything).Return(nil, errors.New("BOOM")) - return dynakube + return mockDtcBuilder } -func setUpFS(fs afero.Fs, ruxitAgentProcPath string, sourceRuxitAgentProcPath string) { - _ = fs.MkdirAll(filepath.Base(sourceRuxitAgentProcPath), 0755) - _ = fs.MkdirAll(filepath.Base(ruxitAgentProcPath), 0755) - usedConf, _ := fs.OpenFile(ruxitAgentProcPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) - _, _ = usedConf.WriteString(testRuxitConf) +func mockSuccessfulDtClientBuilder(t *testing.T) dynatraceclient.Builder { + t.Helper() + + mockDtcBuilder := dtbuildermock.NewBuilder(t) + mockDtcBuilder.On("SetContext", mock.Anything).Return(mockDtcBuilder) + mockDtcBuilder.On("SetDynakube", mock.Anything).Return(mockDtcBuilder) + mockDtcBuilder.On("SetTokens", mock.Anything).Return(mockDtcBuilder) + mockDtcBuilder.On("Build", mock.Anything).Return(dtclientmock.NewClient(t), nil) + + return mockDtcBuilder } diff --git a/pkg/controllers/csi/provisioner/events.go b/pkg/controllers/csi/provisioner/events.go deleted file mode 100644 index 76637b9dc9..0000000000 --- a/pkg/controllers/csi/provisioner/events.go +++ /dev/null @@ -1,26 +0,0 @@ -package csiprovisioner - -import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/tools/record" -) - -type updaterEventRecorder struct { - dk *dynakube.DynaKube - recorder record.EventRecorder -} - -func (event *updaterEventRecorder) sendFailedInstallAgentVersionEvent(version, tenantUUID string) { - event.recorder.Eventf(event.dk, - corev1.EventTypeWarning, - failedInstallAgentVersionEvent, - "Failed to install agent version: %s to tenant: %s", version, tenantUUID) -} - -func (event *updaterEventRecorder) sendInstalledAgentVersionEvent(version, tenantUUID string) { - event.recorder.Eventf(event.dk, - corev1.EventTypeNormal, - installAgentVersionEvent, - "Installed agent version: %s to tenant: %s", version, tenantUUID) -} diff --git a/pkg/controllers/csi/provisioner/install.go b/pkg/controllers/csi/provisioner/install.go index e5a593be86..5c2646e024 100644 --- a/pkg/controllers/csi/provisioner/install.go +++ b/pkg/controllers/csi/provisioner/install.go @@ -3,117 +3,122 @@ package csiprovisioner import ( "context" "encoding/base64" + "errors" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/arch" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/image" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/symlink" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/url" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/processmoduleconfig" ) -func (provisioner *OneAgentProvisioner) installAgentImage( - ctx context.Context, - dk dynakube.DynaKube, - latestProcessModuleConfig *dtclient.ProcessModuleConfig, -) ( - string, - error, -) { - tenantUUID, err := dk.TenantUUIDFromApiUrl() +func (provisioner *OneAgentProvisioner) installAgent(ctx context.Context, dk dynakube.DynaKube) error { + agentInstaller, err := provisioner.getInstaller(ctx, dk) if err != nil { - return "", err - } + log.Info("failed to create CodeModule installer", "dk", dk.GetName()) - targetImage := dk.OneAgent().GetCodeModulesImage() - // An image URI often contains one or several /-s, which is problematic when trying to use it as a folder name. - // Easiest to just base64 encode it - base64Image := base64.StdEncoding.EncodeToString([]byte(targetImage)) - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(base64Image) - targetConfigDir := provisioner.path.AgentConfigDir(tenantUUID, dk.GetName()) - - props := &image.Properties{ - ImageUri: targetImage, - ApiReader: provisioner.apiReader, - Dynakube: &dk, - PathResolver: provisioner.path, - Metadata: provisioner.db, + return err } - imageInstaller, err := provisioner.imageInstallerBuilder(ctx, provisioner.fs, props) + targetDir, err := provisioner.getTargetDir(dk) if err != nil { - return "", err + return err } - err = provisioner.installAgent(ctx, imageInstaller, dk, targetDir, targetImage, tenantUUID) + _, err = agentInstaller.InstallAgent(ctx, targetDir) if err != nil { - return "", err + return err } - err = processmoduleconfig.CreateAgentConfigDir(provisioner.fs, targetConfigDir, targetDir, latestProcessModuleConfig) + err = provisioner.createLatestVersionSymlink(dk, targetDir) if err != nil { - return "", err + return err } - return base64Image, err + return provisioner.setupAgentConfigDir(ctx, dk, targetDir) } -func (provisioner *OneAgentProvisioner) installAgentZip(ctx context.Context, dk dynakube.DynaKube, dtc dtclient.Client, latestProcessModuleConfig *dtclient.ProcessModuleConfig) (string, error) { - tenantUUID, err := dk.TenantUUIDFromApiUrl() - if err != nil { - return "", err - } - - targetVersion := dk.OneAgent().GetCodeModulesVersion() - urlInstaller := provisioner.urlInstallerBuilder(provisioner.fs, dtc, getUrlProperties(targetVersion, provisioner.path)) - - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(targetVersion) - targetConfigDir := provisioner.path.AgentConfigDir(tenantUUID, dk.GetName()) - - err = provisioner.installAgent(ctx, urlInstaller, dk, targetDir, targetVersion, tenantUUID) - if err != nil { - return "", err +func (provisioner *OneAgentProvisioner) getInstaller(ctx context.Context, dk dynakube.DynaKube) (installer.Installer, error) { + switch { + case dk.OneAgent().GetCodeModulesVersion() != "": + dtc, err := buildDtc(provisioner, ctx, dk) + if err != nil { + return nil, err + } + + props := &url.Properties{ + Os: dtclient.OsUnix, + Type: dtclient.InstallerTypePaaS, + Arch: arch.Arch, + Flavor: arch.Flavor, + Technologies: []string{"all"}, + TargetVersion: dk.OneAgent().GetCodeModulesVersion(), + SkipMetadata: true, + PathResolver: provisioner.path, + } + + urlInstaller := provisioner.urlInstallerBuilder(provisioner.fs, dtc, props) + + return urlInstaller, nil + case dk.OneAgent().GetCodeModulesImage() != "": + props := &image.Properties{ + ImageUri: dk.OneAgent().GetCodeModulesImage(), + ApiReader: provisioner.apiReader, + Dynakube: &dk, + PathResolver: provisioner.path, + } + + imageInstaller, err := provisioner.imageInstallerBuilder(ctx, provisioner.fs, props) + if err != nil { + return nil, err + } + + return imageInstaller, nil + default: + return nil, errors.New("missing version/image information to download CodeModule") } +} - err = processmoduleconfig.CreateAgentConfigDir(provisioner.fs, targetConfigDir, targetDir, latestProcessModuleConfig) - if err != nil { - return "", err +func (provisioner *OneAgentProvisioner) getTargetDir(dk dynakube.DynaKube) (string, error) { + var dirName string + + switch { + case dk.OneAgent().GetCodeModulesImage() != "": + // An image URI often contains one or several slashes, which is problematic when trying to use it as a folder name. + // Easiest to just base64 encode it + dirName = base64.StdEncoding.EncodeToString([]byte(dk.OneAgent().GetCodeModulesImage())) + case dk.OneAgent().GetCodeModulesVersion() != "": + dirName = dk.OneAgent().GetCodeModulesVersion() + default: + return "", errors.New("failed to determine the target directory for the CodeModule download") } - return targetVersion, nil + return provisioner.path.AgentSharedBinaryDirForAgent(dirName), nil } -func (provisioner *OneAgentProvisioner) installAgent(ctx context.Context, agentInstaller installer.Installer, dk dynakube.DynaKube, targetDir, targetVersion, tenantUUID string) error { //nolint:revive - eventRecorder := updaterEventRecorder{ - recorder: provisioner.recorder, - dk: &dk, +func (provisioner *OneAgentProvisioner) createLatestVersionSymlink(dk dynakube.DynaKube, targetDir string) error { + symlinkPath := provisioner.path.LatestAgentBinaryForDynaKube(dk.GetName()) + if err := symlink.Remove(provisioner.fs, symlinkPath); err != nil { + return err } - isNewlyInstalled, err := agentInstaller.InstallAgent(ctx, targetDir) + err := symlink.Create(provisioner.fs, targetDir, symlinkPath) if err != nil { - eventRecorder.sendFailedInstallAgentVersionEvent(targetVersion, tenantUUID) - return err } - if isNewlyInstalled { - eventRecorder.sendInstalledAgentVersionEvent(targetVersion, tenantUUID) - } - - return nil + return err } -func getUrlProperties(targetVersion string, pathResolver metadata.PathResolver) *url.Properties { - return &url.Properties{ - Os: dtclient.OsUnix, - Type: dtclient.InstallerTypePaaS, - Arch: arch.Arch, - Flavor: arch.Flavor, - Technologies: []string{"all"}, - TargetVersion: targetVersion, - SkipMetadata: true, - PathResolver: pathResolver, +func (provisioner *OneAgentProvisioner) setupAgentConfigDir(ctx context.Context, dk dynakube.DynaKube, targetDir string) error { + latestProcessModuleConfig, err := processmoduleconfigsecret.GetSecretData(ctx, provisioner.apiReader, dk.Name, dk.Namespace) + if err != nil { + return err } + + return processmoduleconfig.UpdateFromDir(provisioner.fs, provisioner.path.AgentConfigDir(dk.GetName()), targetDir, latestProcessModuleConfig) } diff --git a/pkg/controllers/csi/provisioner/install_test.go b/pkg/controllers/csi/provisioner/install_test.go index b70c818fe6..5d239de3ef 100644 --- a/pkg/controllers/csi/provisioner/install_test.go +++ b/pkg/controllers/csi/provisioner/install_test.go @@ -1,354 +1,38 @@ package csiprovisioner import ( - "context" "encoding/base64" - "fmt" - "path/filepath" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" - dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" - "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" - "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/image" - "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/url" - "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/processmoduleconfig" - t_utils "github.com/Dynatrace/dynatrace-operator/pkg/util/testing" - dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" - installermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/injection/codemodule/installer" - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/tools/record" - "sigs.k8s.io/controller-runtime/pkg/client" ) -const ( - testTenantUUID = "zib123" -) - -func TestUpdateAgent(t *testing.T) { - ctx := context.Background() - testVersion := "test" - testImage := "my-image/1223:123" - - t.Run("zip install", func(t *testing.T) { - dk := createTestDynaKubeWithZip(testVersion) - provisioner := createTestProvisioner() - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.OneAgent().GetCodeModulesVersion()) - - var revision uint = 3 - processModule := createTestProcessModuleConfig(revision) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), targetDir). - Return(true, nil).Run(mockFsAfterInstall(provisioner, testVersion)) - - provisioner.urlInstallerBuilder = mockUrlInstallerBuilder(installerMock) - - currentVersion, err := provisioner.installAgentZip(ctx, dk, dtclientmock.NewClient(t), processModule) - require.NoError(t, err) - assert.Equal(t, testVersion, currentVersion) - t_utils.AssertEvents(t, - provisioner.recorder.(*record.FakeRecorder).Events, - t_utils.Events{ - t_utils.Event{ - EventType: corev1.EventTypeNormal, - Reason: installAgentVersionEvent, - }, - }, - ) - }) - t.Run("zip update", func(t *testing.T) { - dk := createTestDynaKubeWithZip(testVersion) - provisioner := createTestProvisioner() - previousTargetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.OneAgent().GetCodeModulesVersion()) - previousSourceConfigPath := filepath.Join(previousTargetDir, processmoduleconfig.RuxitAgentProcPath) - _ = provisioner.fs.MkdirAll(previousTargetDir, 0755) - _, _ = provisioner.fs.Create(previousSourceConfigPath) - - newVersion := "new" - dk.Status.CodeModules.Version = newVersion - newTargetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.OneAgent().GetCodeModulesVersion()) - - var revision uint = 3 - processModule := createTestProcessModuleConfig(revision) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), newTargetDir). - Return(true, nil).Run(mockFsAfterInstall(provisioner, newVersion)) - - provisioner.urlInstallerBuilder = mockUrlInstallerBuilder(installerMock) +func TestGetTargetDir(t *testing.T) { + t.Run("version set => folder is the version", func(t *testing.T) { + prov := createProvisioner(t) + dk := createDynaKubeWithVersion(t) - currentVersion, err := provisioner.installAgentZip(ctx, dk, dtclientmock.NewClient(t), processModule) + targetDir, err := prov.getTargetDir(*dk) require.NoError(t, err) - assert.Equal(t, newVersion, currentVersion) + require.Contains(t, targetDir, dk.OneAgent().GetCodeModulesVersion()) }) - t.Run("only process module config update", func(t *testing.T) { - dk := createTestDynaKubeWithZip(testVersion) - provisioner := createTestProvisioner() - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(dk.OneAgent().GetCodeModulesVersion()) - sourceConfigPath := filepath.Join(targetDir, processmoduleconfig.RuxitAgentProcPath) - _ = provisioner.fs.MkdirAll(targetDir, 0755) - _, _ = provisioner.fs.Create(sourceConfigPath) - var revision uint = 3 - processModule := createTestProcessModuleConfig(revision) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), targetDir). - Return(false, nil) - - provisioner.urlInstallerBuilder = mockUrlInstallerBuilder(installerMock) - currentVersion, err := provisioner.installAgentZip(ctx, dk, dtclientmock.NewClient(t), processModule) + t.Run("image set => folder is the base64 of the imageURI", func(t *testing.T) { + prov := createProvisioner(t) + dk := createDynaKubeWithImage(t) + expectedDir := base64.StdEncoding.EncodeToString([]byte(dk.OneAgent().GetCodeModulesImage())) + targetDir, err := prov.getTargetDir(*dk) require.NoError(t, err) - assert.Equal(t, testVersion, currentVersion) + require.Contains(t, targetDir, expectedDir) }) - t.Run("failed install", func(t *testing.T) { - dockerconfigjsonContent := `{"auths":{}}` - dk := createTestDynaKubeWithImage(testImage) - provisioner := createTestProvisioner(createMockedPullSecret(dk, dockerconfigjsonContent)) - - var revision uint = 3 - processModule := createTestProcessModuleConfig(revision) - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(base64.StdEncoding.EncodeToString([]byte(testImage))) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), targetDir). - Return(false, fmt.Errorf("BOOM")) - - provisioner.imageInstallerBuilder = mockImageInstallerBuilder(installerMock) - currentVersion, err := provisioner.installAgentImage(ctx, dk, processModule) + t.Run("nothing set => error (shouldn't be possible in real life)", func(t *testing.T) { + prov := createProvisioner(t) + dk := createDynaKubeBase(t) + targetDir, err := prov.getTargetDir(*dk) require.Error(t, err) - assert.Equal(t, "", currentVersion) - t_utils.AssertEvents(t, - provisioner.recorder.(*record.FakeRecorder).Events, - t_utils.Events{ - t_utils.Event{ - EventType: corev1.EventTypeWarning, - Reason: failedInstallAgentVersionEvent, - }, - }, - ) - }) - t.Run("codeModulesImage set without custom pull secret", func(t *testing.T) { - dockerconfigjsonContent := `{"auths":{}}` - - var revision uint = 3 - processModule := createTestProcessModuleConfig(revision) - - dk := createTestDynaKubeWithImage(testImage) - provisioner := createTestProvisioner(createMockedPullSecret(dk, dockerconfigjsonContent)) - base64Image := base64.StdEncoding.EncodeToString([]byte(testImage)) - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(base64Image) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), targetDir). - Return(true, nil).Run(mockFsAfterInstall(provisioner, base64Image)) - - provisioner.imageInstallerBuilder = mockImageInstallerBuilder(installerMock) - - currentVersion, err := provisioner.installAgentImage(ctx, dk, processModule) - require.NoError(t, err) - assert.Equal(t, base64Image, currentVersion) - }) - t.Run("codeModulesImage set with custom pull secret", func(t *testing.T) { - pullSecretName := "test-pull-secret" - dockerconfigjsonContent := `{"auths":{}}` - - var revision uint = 3 - processModule := createTestProcessModuleConfig(revision) - - dk := createTestDynaKubeWithImage(testImage) - dk.Spec.CustomPullSecret = pullSecretName - - provisioner := createTestProvisioner(createMockedPullSecret(dk, dockerconfigjsonContent)) - base64Image := base64.StdEncoding.EncodeToString([]byte(testImage)) - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(base64Image) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), targetDir). - Return(true, nil).Run(mockFsAfterInstall(provisioner, base64Image)) - - provisioner.imageInstallerBuilder = mockImageInstallerBuilder(installerMock) - - currentVersion, err := provisioner.installAgentImage(ctx, dk, processModule) - require.NoError(t, err) - assert.Equal(t, base64Image, currentVersion) - }) - t.Run("codeModulesImage + trustedCA set", func(t *testing.T) { - pullSecretName := "test-pull-secret" - trustedCAName := "test-trusted-ca" - customCertContent := ` ------BEGIN CERTIFICATE----- -MIIDazCCAlOgAwIBAgIUdKGNuWxm1t7auCtk+RYAgMKC4wkwDQYJKoZIhvcNAQEL -BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzA4MDcxMzUzMjBaFw0yNDA4 -MDYxMzUzMjBaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw -HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDGkW280WZbTyHPiNQXHVaWW/C3ZbaKh5cuarQUkHZc -1SVfFELuJXm3YAA5ZOtwaIuqsSO9Yieao0kWYWWCSyFdwcOIl5H85n9YaZ1/8ki3 -af7TwH1UppA3Zh24eV9ME+uJKsmn4AkMVaM9EKUaOTybZD6Sc0jxsmec9yDuE4md -P0vqIshcd6VmxruPnzzmOEXggP3QPFF5s9017uPnQ7k2kU8b0MG19HS2opeeSO59 -R2+kg/Xkz8UnCa5y+OSORW20DHjwc7DUr/Gr78X49iiFBzBewBfeqxQKwtYcC9eB -DxiDWiXENUnsS0EkMs4jNFjgiAJTzx6rBa4xiwe7SJWfAgMBAAGjUzBRMB0GA1Ud -DgQWBBR+L23VHT1LLmpAwz4esbVmfSCOdDAfBgNVHSMEGDAWgBR+L23VHT1LLmpA -wz4esbVmfSCOdDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCj -jU/luq9dNiZi6fhgfhDQRuZEYnHSV8L3+hEDn1j6Gn02c9wNcCDjOBH4i8pJz8g2 -x+Z1SNALXFcr+bGJQx94lw7S1Vm84YxELyNbwVYuHo+7aLAUXSQ62RMIhEJ/NCzW -yN0j8PhweOTBwUtvzPa+71f1gNbDgkfXqgLSXBgjNvolcg/lefmKBs0pU8swOmX1 -q8nrWV12953Gf9sMJ0mFP5/Lcv4l1SdnFLOSdVjWF4RX+SjnVgiHSuJxp9k3QiXz -5dlfTqc9/qZa1PRq4hdq/3Rs42Hiwa3FTWSgqjM1qcDycQtTIAeZu2zfYDQDkYcI -NK85cEJwyxQ+wahdNGUD ------END CERTIFICATE----- -` - dockerconfigjsonContent := `{"auths":{}}` - - var revision uint = 3 - processModule := createTestProcessModuleConfig(revision) - - dk := createTestDynaKubeWithImage(testImage) - dk.Spec.CustomPullSecret = pullSecretName - dk.Spec.TrustedCAs = trustedCAName - - provisioner := createTestProvisioner(createMockedPullSecret(dk, dockerconfigjsonContent), createMockedCAConfigMap(dk, customCertContent)) - base64Image := base64.StdEncoding.EncodeToString([]byte(testImage)) - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(base64Image) - installerMock := installermock.NewInstaller(t) - installerMock. - On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), targetDir). - Return(true, nil).Run(mockFsAfterInstall(provisioner, base64Image)) - - provisioner.imageInstallerBuilder = mockImageInstallerBuilder(installerMock) - - currentVersion, err := provisioner.installAgentImage(ctx, dk, processModule) - require.NoError(t, err) - assert.Equal(t, base64Image, currentVersion) - }) -} - -func mockFsAfterInstall(provisioner *OneAgentProvisioner, version string) func(mock.Arguments) { - return func(mock.Arguments) { - targetDir := provisioner.path.AgentSharedBinaryDirForAgent(version) - sourceConfigPath := filepath.Join(targetDir, processmoduleconfig.RuxitAgentProcPath) - _ = provisioner.fs.MkdirAll(targetDir, 0755) - _ = provisioner.fs.MkdirAll(filepath.Dir(sourceConfigPath), 0755) - _, _ = provisioner.fs.Create(sourceConfigPath) - } -} - -func createMockedPullSecret(dk dynakube.DynaKube, pullSecretContent string) *corev1.Secret { - return &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: dk.PullSecretName(), - Namespace: dk.Namespace, - }, - Data: map[string][]byte{ - ".dockerconfigjson": []byte(pullSecretContent), - }, - } -} - -func createMockedCAConfigMap(dk dynakube.DynaKube, certContent string) *corev1.ConfigMap { - return &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: dk.Spec.TrustedCAs, - Namespace: dk.Namespace, - }, - Data: map[string]string{ - dynakube.TrustedCAKey: certContent, - }, - } -} - -func createTestDynaKubeWithImage(image string) dynakube.DynaKube { - return *addFakeTenantUUID(&dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-dk", - Namespace: "test-ns", - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: "https://" + testTenantUUID + ".dynatrace.com", - }, - Status: dynakube.DynaKubeStatus{ - CodeModules: oneagent.CodeModulesStatus{ - VersionStatus: status.VersionStatus{ - ImageID: image, - }, - }, - }, - }) -} - -func createTestDynaKubeWithZip(version string) dynakube.DynaKube { - return *addFakeTenantUUID(&dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-dk", - Namespace: "test-ns", - }, - Spec: dynakube.DynaKubeSpec{ - APIURL: "https://" + testTenantUUID + ".dynatrace.com", - }, - Status: dynakube.DynaKubeStatus{ - CodeModules: oneagent.CodeModulesStatus{ - VersionStatus: status.VersionStatus{ - Version: version, - }, - }, - }, + require.Empty(t, targetDir) }) } - -func createTestProvisioner(obj ...client.Object) *OneAgentProvisioner { - path := metadata.PathResolver{RootDir: "test"} - fs := afero.NewMemMapFs() - rec := record.NewFakeRecorder(10) - db := metadata.FakeMemoryDB() - - fakeClient := fake.NewClient(obj...) - provisioner := &OneAgentProvisioner{ - client: fakeClient, - apiReader: fakeClient, - fs: fs, - recorder: rec, - path: path, - db: db, - } - - return provisioner -} - -func mockImageInstallerBuilder(mock *installermock.Installer) imageInstallerBuilder { - return func(_ context.Context, _ afero.Fs, _ *image.Properties) (installer.Installer, error) { - return mock, nil - } -} - -func mockUrlInstallerBuilder(mock *installermock.Installer) urlInstallerBuilder { - return func(_ afero.Fs, _ dtclient.Client, _ *url.Properties) installer.Installer { - return mock - } -} - -func createTestProcessModuleConfig(revision uint) *dtclient.ProcessModuleConfig { - return &dtclient.ProcessModuleConfig{ - Revision: revision, - Properties: []dtclient.ProcessModuleProperty{ - { - Section: "test", - Key: "test", - Value: "test3", - }, - }, - } -} diff --git a/pkg/controllers/dynakube/dtpullsecret/generate.go b/pkg/controllers/dynakube/dtpullsecret/generate.go index da5c434d9c..f6f3596c18 100644 --- a/pkg/controllers/dynakube/dtpullsecret/generate.go +++ b/pkg/controllers/dynakube/dtpullsecret/generate.go @@ -52,7 +52,7 @@ func (r *Reconciler) GenerateData() (map[string][]byte, error) { return nil, errors.New("token secret does not contain a paas or api token, cannot generate docker config") } - tenantUUID, err := r.dk.TenantUUIDFromConnectionInfoStatus() + tenantUUID, err := r.dk.TenantUUID() if err != nil { return nil, errors.WithMessage(err, "cannot generate docker config") } diff --git a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go index 7d36529e62..6bcaf6e5d3 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go @@ -76,7 +76,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { } func (r *Reconciler) generateDaemonSet() (*appsv1.DaemonSet, error) { - tenantUUID, err := r.dk.TenantUUIDFromConnectionInfoStatus() + tenantUUID, err := r.dk.TenantUUID() if err != nil { return nil, err } diff --git a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go index 8240decfcf..ba95acda5c 100644 --- a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go @@ -118,7 +118,7 @@ func (r *Reconciler) getSecretData(ctx context.Context) (map[string][]byte, erro return nil, err } - tenantUUID, err := r.dk.TenantUUIDFromConnectionInfoStatus() + tenantUUID, err := r.dk.TenantUUID() if err != nil { conditions.SetSecretGenFailed(r.dk.Conditions(), lmcConditionType, err) diff --git a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go index 4c7067cae8..4740896f6f 100644 --- a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go @@ -124,7 +124,7 @@ func checkSecretForValue(t *testing.T, k8sClient client.Client, dk *dynakube.Dyn deploymentConfig, ok := secret.Data[DeploymentConfigFilename] require.True(t, ok) - tenantUUID, err := dk.TenantUUIDFromConnectionInfoStatus() + tenantUUID, err := dk.TenantUUID() require.NoError(t, err) expectedLines := []string{ diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go index 6014cfbf86..f6f556cba1 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go @@ -80,7 +80,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { } func (r *Reconciler) generateDaemonSet() (*appsv1.DaemonSet, error) { - tenantUUID, err := r.dk.TenantUUIDFromConnectionInfoStatus() + tenantUUID, err := r.dk.TenantUUID() if err != nil { return nil, err } diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go index 9f303ec32a..fe0a89022a 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go @@ -20,7 +20,7 @@ import ( ) const ( - PullSecretSuffix = "-pmc-secret" + SecretSuffix = "-pmc-secret" SecretKeyProcessModuleConfig = "ruxitagentproc.conf" ) @@ -211,5 +211,5 @@ func unmarshal(secret *corev1.Secret) (*dtclient.ProcessModuleConfig, error) { } func extendWithSuffix(name string) string { - return name + PullSecretSuffix + return name + SecretSuffix } diff --git a/pkg/injection/codemodule/installer/image/installer.go b/pkg/injection/codemodule/installer/image/installer.go index 70cbcdcea6..9a555eb374 100644 --- a/pkg/injection/codemodule/installer/image/installer.go +++ b/pkg/injection/codemodule/installer/image/installer.go @@ -25,7 +25,6 @@ type Properties struct { ApiReader client.Reader Dynakube *dynakube.DynaKube PathResolver metadata.PathResolver - Metadata metadata.Access ImageDigest string } @@ -85,7 +84,7 @@ func (installer *Installer) InstallAgent(_ context.Context, targetDir string) (b return false, errors.WithStack(err) } - if err := symlink.CreateSymlinkForCurrentVersionIfNotExists(installer.fs, targetDir); err != nil { + if err := symlink.CreateForCurrentVersionIfNotExists(installer.fs, targetDir); err != nil { _ = installer.fs.RemoveAll(targetDir) log.Info("failed to create symlink for agent installation", "err", err) diff --git a/pkg/injection/codemodule/installer/symlink/symlink.go b/pkg/injection/codemodule/installer/symlink/symlink.go index 53c4ab72b9..b9ad2b9edd 100644 --- a/pkg/injection/codemodule/installer/symlink/symlink.go +++ b/pkg/injection/codemodule/installer/symlink/symlink.go @@ -9,39 +9,48 @@ import ( "github.com/spf13/afero" ) -func CreateSymlinkForCurrentVersionIfNotExists(fs afero.Fs, targetDir string) error { - var relativeSymlinkPath string - +func CreateForCurrentVersionIfNotExists(fs afero.Fs, targetDir string) error { var err error - targetBindDir := filepath.Join(targetDir, binDir) - - // MemMapFs (used for testing) doesn't comply with the Linker interface - linker, ok := fs.(afero.Linker) + _, ok := fs.(afero.Linker) if !ok { log.Info("symlinking not possible", "targetDir", targetDir, "fs", fs) return nil } - relativeSymlinkPath, err = findVersionFromFileSystem(fs, targetBindDir) + targetBinDir := filepath.Join(targetDir, binDir) + + relativeSymlinkPath, err := findVersionFromFileSystem(fs, targetBinDir) if err != nil { log.Info("failed to get the version from the filesystem", "targetDir", targetDir) return err } - symlinkTargetPath := filepath.Join(targetBindDir, "current") - if fileInfo, _ := fs.Stat(symlinkTargetPath); fileInfo != nil { - log.Info("symlink already exists", "location", symlinkTargetPath) + return Create(fs, relativeSymlinkPath, filepath.Join(targetBinDir, "current")) +} + +func Create(fs afero.Fs, targetDir, symlinkDir string) error { + // MemMapFs (used for testing) doesn't comply with the Linker interface + linker, ok := fs.(afero.Linker) + if !ok { + log.Info("symlinking not possible", "targetDir", targetDir, "fs", fs) + + return nil + } + + // Check if the symlink already exists + if fileInfo, _ := fs.Stat(symlinkDir); fileInfo != nil { + log.Info("symlink already exists", "location", symlinkDir) return nil } - log.Info("creating symlink", "points-to(relative)", relativeSymlinkPath, "location", symlinkTargetPath) + log.Info("creating symlink", "points-to(relative)", targetDir, "location", symlinkDir) - if err := linker.SymlinkIfPossible(relativeSymlinkPath, symlinkTargetPath); err != nil { - log.Info("symlinking failed", "version", relativeSymlinkPath) + if err := linker.SymlinkIfPossible(targetDir, symlinkDir); err != nil { + log.Info("symlinking failed", "source", targetDir) return errors.WithStack(err) } @@ -49,6 +58,18 @@ func CreateSymlinkForCurrentVersionIfNotExists(fs afero.Fs, targetDir string) er return nil } +func Remove(fs afero.Fs, symlinkPath string) error { + if info, _ := fs.Stat(symlinkPath); info != nil { + log.Info("symlink to directory exists, removing it to ensure proper reinstallation or reconfiguration", "directory", symlinkPath) + + if err := fs.Remove(symlinkPath); err != nil { + return err + } + } + + return nil +} + func findVersionFromFileSystem(fs afero.Fs, targetDir string) (string, error) { var version string diff --git a/pkg/injection/codemodule/installer/url/installer.go b/pkg/injection/codemodule/installer/url/installer.go index 2b7df03cd5..dcc404a147 100644 --- a/pkg/injection/codemodule/installer/url/installer.go +++ b/pkg/injection/codemodule/installer/url/installer.go @@ -77,7 +77,7 @@ func (installer Installer) InstallAgent(ctx context.Context, targetDir string) ( return false, err } - if err := symlink.CreateSymlinkForCurrentVersionIfNotExists(installer.fs, targetDir); err != nil { + if err := symlink.CreateForCurrentVersionIfNotExists(installer.fs, targetDir); err != nil { _ = installer.fs.RemoveAll(targetDir) log.Info("failed to create symlink for agent installation", "targetDir", targetDir) diff --git a/pkg/injection/codemodule/processmoduleconfig/update.go b/pkg/injection/codemodule/processmoduleconfig/update.go index b01d1d15be..c5e9a06408 100644 --- a/pkg/injection/codemodule/processmoduleconfig/update.go +++ b/pkg/injection/codemodule/processmoduleconfig/update.go @@ -15,7 +15,7 @@ var ( sourceRuxitAgentProcPath = filepath.Join("agent", "conf", "_ruxitagentproc.conf") ) -func UpdateProcessModuleConfigInPlace(fs afero.Fs, targetDir string, processModuleConfig *dtclient.ProcessModuleConfig) error { +func UpdateInPlace(fs afero.Fs, targetDir string, processModuleConfig *dtclient.ProcessModuleConfig) error { if processModuleConfig != nil { log.Info("updating ruxitagentproc.conf", "targetDir", targetDir) usedProcessModuleConfigPath := filepath.Join(targetDir, RuxitAgentProcPath) @@ -33,7 +33,7 @@ func UpdateProcessModuleConfigInPlace(fs afero.Fs, targetDir string, processModu return nil } -func CreateAgentConfigDir(fs afero.Fs, targetDir, sourceDir string, processModuleConfig *dtclient.ProcessModuleConfig) error { +func UpdateFromDir(fs afero.Fs, targetDir, sourceDir string, processModuleConfig *dtclient.ProcessModuleConfig) error { if processModuleConfig != nil { log.Info("updating ruxitagentproc.conf", "targetDir", targetDir, "sourceDir", sourceDir) sourceProcessModuleConfigPath := filepath.Join(sourceDir, RuxitAgentProcPath) diff --git a/pkg/injection/codemodule/processmoduleconfig/update_test.go b/pkg/injection/codemodule/processmoduleconfig/update_test.go index 3457da6733..ab445f5c58 100644 --- a/pkg/injection/codemodule/processmoduleconfig/update_test.go +++ b/pkg/injection/codemodule/processmoduleconfig/update_test.go @@ -34,7 +34,7 @@ func TestUpdateProcessModuleConfigInPlace(t *testing.T) { t.Run("no processModuleConfig", func(t *testing.T) { memFs := afero.NewMemMapFs() - err := UpdateProcessModuleConfigInPlace(memFs, "", nil) + err := UpdateInPlace(memFs, "", nil) require.NoError(t, err) }) t.Run("update file", func(t *testing.T) { @@ -49,7 +49,7 @@ key value test test3 ` - err := UpdateProcessModuleConfigInPlace(memFs, "", &testProcessModuleConfig) + err := UpdateInPlace(memFs, "", &testProcessModuleConfig) require.NoError(t, err) assertTestConf(t, memFs, RuxitAgentProcPath, expectedUsed) assertTestConf(t, memFs, sourceRuxitAgentProcPath, testRuxitConf) @@ -60,7 +60,7 @@ func TestCreateAgentConfigDir(t *testing.T) { t.Run("no processModuleConfig", func(t *testing.T) { memFs := afero.NewMemMapFs() - err := CreateAgentConfigDir(memFs, "", "", nil) + err := UpdateFromDir(memFs, "", "", nil) require.NoError(t, err) }) @@ -78,7 +78,7 @@ key value test test3 ` - err := CreateAgentConfigDir(memFs, targetDir, sourceDir, &testProcessModuleConfig) + err := UpdateFromDir(memFs, targetDir, sourceDir, &testProcessModuleConfig) require.NoError(t, err) assertTestConf(t, memFs, filepath.Join(targetDir, RuxitAgentProcPath), expectedUsed) assertTestConf(t, memFs, filepath.Join(sourceDir, RuxitAgentProcPath), testRuxitConf) diff --git a/pkg/injection/namespace/ingestendpoint/secret.go b/pkg/injection/namespace/ingestendpoint/secret.go index a7e9005b81..0ef55e4704 100644 --- a/pkg/injection/namespace/ingestendpoint/secret.go +++ b/pkg/injection/namespace/ingestendpoint/secret.go @@ -189,7 +189,7 @@ func metricsIngestUrlForDynatraceActiveGate(dk *dynakube.DynaKube) (string, erro } func metricsIngestUrlForClusterActiveGate(dk *dynakube.DynaKube) (string, error) { - tenant, err := dk.TenantUUIDFromConnectionInfoStatus() + tenant, err := dk.TenantUUID() if err != nil { return "", err } diff --git a/pkg/injection/startup/run.go b/pkg/injection/startup/run.go index e6e95081be..415d31de35 100644 --- a/pkg/injection/startup/run.go +++ b/pkg/injection/startup/run.go @@ -173,7 +173,7 @@ func (runner *Runner) installOneAgent(ctx context.Context) error { return err } - err = processmoduleconfig.UpdateProcessModuleConfigInPlace(runner.fs, consts.AgentBinDirMount, processModuleConfig) + err = processmoduleconfig.UpdateInPlace(runner.fs, consts.AgentBinDirMount, processModuleConfig) if err != nil { return err } diff --git a/pkg/util/testing/events.go b/pkg/util/testing/events.go deleted file mode 100644 index 20cfa76196..0000000000 --- a/pkg/util/testing/events.go +++ /dev/null @@ -1,38 +0,0 @@ -package testing - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -type Event struct { - EventType string - Reason string - Message string -} -type Events []Event - -// FakeEventRecorders(aka.: FakeRecorders) push the "sent" events into a string channel, using this format: "eventType eventReason eventMessage" -// So this function just parses this format and compares the produced fields with the fields of the provided Event structs IN ORDER. -// In case of the Event.Message field it only checks if it "CONTAINED" in sent event. -func AssertEvents(t *testing.T, eventsCh chan string, expectedEvents Events) { - assert.Equal(t, len(eventsCh), len(expectedEvents)) - - for _, event := range expectedEvents { - eventString := <-eventsCh - assert.NotNil(t, eventString) - tmp := strings.Split(eventString, " ") - eventType := tmp[0] - reason := tmp[1] - message := strings.Join(tmp[2:], " ") - - assert.Equal(t, eventType, event.EventType) - assert.Equal(t, reason, event.Reason) - - if len(event.Message) > 0 { - assert.Contains(t, message, event.Message) - } - } -} diff --git a/pkg/webhook/mutation/pod/oneagent/mutator.go b/pkg/webhook/mutation/pod/oneagent/mutator.go index 43e30a3057..5d237f6ad8 100644 --- a/pkg/webhook/mutation/pod/oneagent/mutator.go +++ b/pkg/webhook/mutation/pod/oneagent/mutator.go @@ -119,7 +119,7 @@ func (mut *Mutator) isInjectionPossible(request *dtwebhook.MutationRequest) (boo dk := request.DynaKube - _, err := dk.TenantUUIDFromConnectionInfoStatus() + _, err := dk.TenantUUID() if err != nil { log.Info("tenant UUID is not available, OneAgent cannot be injected", "pod", request.PodName()) From af845f4e313b21de70190692aa2dbb1579730a91 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 17 Jan 2025 12:09:10 +0100 Subject: [PATCH 119/426] Add --platform to Dockerfile (#4308) --- Dockerfile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index a3451127fa..cd5d9e448e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,8 +25,9 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ go build -tags "${GO_BUILD_TAGS}" -trimpath -ldflags="${GO_LINKER_ARGS}" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ -FROM registry.access.redhat.com/ubi9-micro:9.5-1736426761@sha256:f6e0a71b7e0875b54ea559c2e0a6478703268a8d4b8bdcf5d911d0dae76aef51 AS base -FROM registry.access.redhat.com/ubi9:9.5-1736404036@sha256:53d6c19d664f4f418ce5c823d3a33dbb562a2550ea249cf07ef10aa063ace38f AS dependency +# platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1736426761@sha256:f6e0a71b7e0875b54ea559c2e0a6478703268a8d4b8bdcf5d911d0dae76aef51 AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1736404036@sha256:53d6c19d664f4f418ce5c823d3a33dbb562a2550ea249cf07ef10aa063ace38f AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ @@ -40,7 +41,8 @@ RUN dnf install --installroot /tmp/rootfs-dependency \ /tmp/rootfs-dependency/var/log/dnf* \ /tmp/rootfs-dependency/var/log/yum.* -FROM base +# platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings +FROM --platform=$TARGETPLATFORM base COPY --from=dependency /tmp/rootfs-dependency / From 6f81a28395912eef400a3ff3f84129b60b835153 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 08:26:49 +0000 Subject: [PATCH 120/426] chore(deps): update module github.com/vektra/mockery to v2.51.1 (main) (#4310) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index c26c3f260b..3419c81c86 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.29.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.51.0 +mockery_version=v2.51.1 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.43.0 # renovate depName=github.com/helm-unittest/helm-unittest From 671c4676ea3ce409e18732edf9a98b8053c2cb5e Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Mon, 20 Jan 2025 14:05:10 +0100 Subject: [PATCH 121/426] Add default initContainer resources in case of only metadata enrichment (#4288) Co-authored-by: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> --- pkg/webhook/mutation/pod/init_container.go | 4 +++ .../mutation/pod/init_container_test.go | 32 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/pkg/webhook/mutation/pod/init_container.go b/pkg/webhook/mutation/pod/init_container.go index 90013eec66..e88f61793c 100644 --- a/pkg/webhook/mutation/pod/init_container.go +++ b/pkg/webhook/mutation/pod/init_container.go @@ -45,6 +45,10 @@ func initContainerResources(dk dynakube.DynaKube) corev1.ResourceRequirements { } if !dk.OneAgent().IsCSIAvailable() { + if dk.MetadataEnrichmentEnabled() && !dk.OneAgent().IsAppInjectionNeeded() { + return defaultInitContainerResources() + } + return corev1.ResourceRequirements{} } diff --git a/pkg/webhook/mutation/pod/init_container_test.go b/pkg/webhook/mutation/pod/init_container_test.go index 7b240c39bb..f58424c55b 100644 --- a/pkg/webhook/mutation/pod/init_container_test.go +++ b/pkg/webhook/mutation/pod/init_container_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" @@ -238,4 +239,35 @@ func TestInitContainerResources(t *testing.T) { require.Empty(t, initResources) }) + + t.Run("should have default if metadata enrichment is enabled", func(t *testing.T) { + dk := getTestDynakubeDefaultAppMon() + dk.Spec.MetadataEnrichment.Enabled = ptr.To(true) + + initResources := initContainerResources(*dk) + + assert.Equal(t, defaultInitContainerResources(), initResources) + }) + t.Run("should have default if only metadata enrichment is enabled and csi is disabled", func(t *testing.T) { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + + dk := getTestDynakubeDefaultAppMon() + dk.Spec.MetadataEnrichment.Enabled = ptr.To(true) + dk.Spec.OneAgent.ApplicationMonitoring = nil + initResources := initContainerResources(*dk) + + assert.Equal(t, defaultInitContainerResources(), initResources) + }) + t.Run("should have no limit if OA is enabled and csi is disabled", func(t *testing.T) { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + + dk := getTestDynakubeDefaultAppMon() + + dk.Spec.MetadataEnrichment.Enabled = ptr.To(true) + dk.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} + + initResources := initContainerResources(*dk) + + require.Empty(t, initResources) + }) } From 5c4de1f7ebc8018f65c622e2b5508222a210b280 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Mon, 20 Jan 2025 17:05:16 +0100 Subject: [PATCH 122/426] ignore redundant target platform (#4311) --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index cd5d9e448e..ea95bdbee8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,4 @@ +# check=skip=RedundantTargetPlatform # setup build image FROM --platform=$BUILDPLATFORM golang:1.23.5@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 AS operator-build From 18d82600feb9476a5967691ef004a2bdcacf83a4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 08:55:35 +0000 Subject: [PATCH 123/426] chore(deps): update actions/setup-go action to v5.3.0 (main) (#4318) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- .github/actions/run-e2e/action.yaml | 2 +- .github/workflows/ci.yaml | 6 +++--- .github/workflows/release.yaml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index b3ca2d55d6..37f1167ae5 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -18,7 +18,7 @@ runs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 - name: Set up Golang - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Prepare build parameters diff --git a/.github/actions/run-e2e/action.yaml b/.github/actions/run-e2e/action.yaml index d72d3db996..d835b4a326 100644 --- a/.github/actions/run-e2e/action.yaml +++ b/.github/actions/run-e2e/action.yaml @@ -50,7 +50,7 @@ runs: - name: Set up kubectl uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f # v4.0.0 - name: Set up go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version-file: "${{ github.workspace }}/target/go.mod" - name: Set up helm diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 55b9a0a603..1e4701f251 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -54,7 +54,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Golang - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run Unit tests and Integration tests @@ -82,7 +82,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint @@ -102,7 +102,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Set up Helm diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8e9f9d058a..b4db24e25a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -285,7 +285,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Golang - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Generate release notes From 0b7cdbd700851a013be3377ac0790dcf2be201f1 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Tue, 21 Jan 2025 10:29:31 +0100 Subject: [PATCH 124/426] Remove command descriptions in case the whole application is failing (#4290) --- cmd/csi/init/cmd.go | 5 +++-- cmd/csi/provisioner/cmd.go | 5 +++-- cmd/csi/server/cmd.go | 5 +++-- cmd/operator/builder.go | 5 +++-- cmd/standalone/standalone.go | 5 +++-- cmd/webhook/builder.go | 5 +++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/cmd/csi/init/cmd.go b/cmd/csi/init/cmd.go index 04f8436b67..3d97d07ca7 100644 --- a/cmd/csi/init/cmd.go +++ b/cmd/csi/init/cmd.go @@ -25,8 +25,9 @@ var nodeId, endpoint string func New() *cobra.Command { cmd := &cobra.Command{ - Use: use, - RunE: run(), + Use: use, + RunE: run(), + SilenceUsage: true, } return cmd diff --git a/cmd/csi/provisioner/cmd.go b/cmd/csi/provisioner/cmd.go index ab9cad5602..3330336f55 100644 --- a/cmd/csi/provisioner/cmd.go +++ b/cmd/csi/provisioner/cmd.go @@ -35,8 +35,9 @@ var probeAddress string func New() *cobra.Command { cmd := &cobra.Command{ - Use: use, - RunE: run(), + Use: use, + RunE: run(), + SilenceUsage: true, } addFlags(cmd) diff --git a/cmd/csi/server/cmd.go b/cmd/csi/server/cmd.go index 5ac83bedf5..1d7e6f731f 100644 --- a/cmd/csi/server/cmd.go +++ b/cmd/csi/server/cmd.go @@ -31,8 +31,9 @@ var nodeId, endpoint string func New() *cobra.Command { cmd := &cobra.Command{ - Use: use, - RunE: run(), + Use: use, + RunE: run(), + SilenceUsage: true, } addFlags(cmd) diff --git a/cmd/operator/builder.go b/cmd/operator/builder.go index f6b3ae1b0e..195c97629e 100644 --- a/cmd/operator/builder.go +++ b/cmd/operator/builder.go @@ -104,8 +104,9 @@ func (builder *CommandBuilder) getSignalHandler() context.Context { func (builder CommandBuilder) Build() *cobra.Command { return &cobra.Command{ - Use: use, - RunE: builder.buildRun(), + Use: use, + RunE: builder.buildRun(), + SilenceUsage: true, } } diff --git a/cmd/standalone/standalone.go b/cmd/standalone/standalone.go index 6c87bd5e33..4ba18ae6c6 100644 --- a/cmd/standalone/standalone.go +++ b/cmd/standalone/standalone.go @@ -14,8 +14,9 @@ const ( func NewStandaloneCommand() *cobra.Command { return &cobra.Command{ - Use: use, - RunE: startStandAloneInit, + Use: use, + RunE: startStandAloneInit, + SilenceUsage: true, } } diff --git a/cmd/webhook/builder.go b/cmd/webhook/builder.go index 9ca9d7eb93..b0a07d1669 100644 --- a/cmd/webhook/builder.go +++ b/cmd/webhook/builder.go @@ -84,8 +84,9 @@ func (builder CommandBuilder) SetPodName(podName string) CommandBuilder { func (builder CommandBuilder) Build() *cobra.Command { cmd := &cobra.Command{ - Use: use, - RunE: builder.buildRun(), + Use: use, + RunE: builder.buildRun(), + SilenceUsage: true, } addFlags(cmd) From 903296406d648566a2d43aeb13bfe23c672b6827 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 01:09:37 +0000 Subject: [PATCH 125/426] chore(deps): update github/codeql-action action to v3.28.2 (main) (#4327) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index cd1cdcf466..8acfb7fee1 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 + uses: github/codeql-action/init@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 + uses: github/codeql-action/autobuild@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 + uses: github/codeql-action/analyze@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 06b169da80..a86c88b803 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 + uses: github/codeql-action/upload-sarif@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 with: sarif_file: results.sarif From 6b510cf651daaf5750ff95047ca945889451568b Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Wed, 22 Jan 2025 13:42:50 +0100 Subject: [PATCH 126/426] Open signal feature (#4313) This change brings 3 PRs from feature branch to main related to Open Signal Epic: * Activate AG capabilities required by OtlpIngest feature #4066 * Mount persistent volume to ActiveGate pod #4084 * Add telemetryService field to the DynakubeSpec #4236 --- config/crd/bases/dynatrace.com_dynakubes.yaml | 443 +++++++++++++--- .../crd/bases/dynatrace.com_edgeconnects.yaml | 40 +- .../Common/crd/dynatrace-operator-crd.yaml | 483 ++++++++++++++---- doc/api/dynakube-api-ref.md | 49 +- hack/make/manifests/config.mk | 2 +- pkg/api/v1beta3/dynakube/activegate/props.go | 4 + pkg/api/v1beta3/dynakube/activegate/spec.go | 13 +- .../activegate/zz_generated.deepcopy.go | 7 +- pkg/api/v1beta3/dynakube/activegate_props.go | 1 + pkg/api/v1beta3/dynakube/dynakube_types.go | 7 + pkg/api/v1beta3/dynakube/otlp_props.go | 5 + .../dynakube/telemetryservice/props.go | 40 ++ .../v1beta3/dynakube/telemetryservice/spec.go | 18 + .../telemetryservice/zz_generated.deepcopy.go | 41 ++ .../dynakube/telemetryservice_props.go | 11 + .../v1beta3/dynakube/zz_generated.deepcopy.go | 6 + pkg/api/validation/dynakube/activegate.go | 16 + .../validation/dynakube/activegate_test.go | 43 ++ .../validation/dynakube/telemetryservice.go | 84 +++ .../dynakube/telemetryservice_test.go | 132 +++++ pkg/api/validation/dynakube/validation.go | 4 + .../activegate/capability/capability.go | 5 + .../activegate/capability/capability_test.go | 101 +++- .../statefulset/builder/modifiers/readonly.go | 11 - .../internal/statefulset/statefulset.go | 107 +++- .../internal/statefulset/statefulset_test.go | 123 +++++ 26 files changed, 1575 insertions(+), 221 deletions(-) create mode 100644 pkg/api/v1beta3/dynakube/otlp_props.go create mode 100644 pkg/api/v1beta3/dynakube/telemetryservice/props.go create mode 100644 pkg/api/v1beta3/dynakube/telemetryservice/spec.go create mode 100644 pkg/api/v1beta3/dynakube/telemetryservice/zz_generated.deepcopy.go create mode 100644 pkg/api/v1beta3/dynakube/telemetryservice_props.go create mode 100644 pkg/api/validation/dynakube/telemetryservice.go create mode 100644 pkg/api/validation/dynakube/telemetryservice_test.go diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index 18800eeba0..778cf1c6c1 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -100,7 +100,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -283,7 +284,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: @@ -320,7 +321,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -389,7 +391,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -413,7 +418,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -429,12 +434,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -495,7 +504,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -673,7 +683,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: @@ -704,7 +714,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -773,7 +784,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -797,7 +811,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -813,12 +827,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -951,7 +969,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object useCSIDriver: @@ -978,6 +996,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -1007,7 +1026,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -1181,7 +1201,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -1218,7 +1238,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -1248,6 +1269,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -1281,7 +1303,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -1443,7 +1466,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: @@ -1516,7 +1539,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -1553,7 +1576,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -1585,6 +1609,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -1614,7 +1639,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -1788,7 +1814,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -1825,7 +1851,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -1889,7 +1916,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -2067,7 +2095,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: @@ -2098,7 +2126,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -2167,7 +2196,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -2191,7 +2223,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -2207,12 +2239,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -2338,6 +2374,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ @@ -2514,7 +2551,8 @@ spec: values:\n\t- `routing` enables OneAgent routing.\n\t- `kubernetes-monitoring` enables Kubernetes API monitoring.\n\t- `metrics-ingest` opens the metrics ingest endpoint on the DynaKube ActiveGate and redirects - all pods to it." + all pods to it.\n\t- `dynatrace-api` enables calling the Dynatrace + API via ActiveGate." items: type: string type: array @@ -2550,7 +2588,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -2737,7 +2776,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: @@ -2774,7 +2813,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -2843,7 +2883,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -2867,7 +2910,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -2883,12 +2926,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -2902,7 +2949,7 @@ spec: Dynatrace `apiUrl`, including the `/api` path at the end. - For SaaS, set `YOUR_ENVIRONMENT_ID` to your environment ID. - For Managed, change the `apiUrl` address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www. + For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. type: string customPullSecret: description: |- @@ -3052,7 +3099,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: @@ -3128,6 +3175,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -3158,7 +3206,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -3333,7 +3382,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -3374,7 +3423,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -3406,6 +3456,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -3440,7 +3491,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -3602,7 +3654,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: @@ -3724,7 +3776,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -3765,7 +3817,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -3802,6 +3855,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -3832,7 +3886,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -4007,7 +4062,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -4048,7 +4103,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -4197,6 +4253,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ @@ -4427,7 +4484,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -4544,6 +4602,171 @@ spec: type: string description: Node selector to control the selection of nodes type: object + persistentVolumeClaim: + description: Defines storage device + properties: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified data source. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + More info: https://kubernetes. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is a label query over volumes to consider + for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. + type: string + volumeMode: + description: |- + volumeMode defines what type of volume is required by the claim. + Value of Filesystem is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. + type: string + type: object priorityClassName: description: |- If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that @@ -4610,7 +4833,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: @@ -4647,7 +4870,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -4716,7 +4940,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -4740,7 +4967,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -4756,12 +4983,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -4769,6 +5000,9 @@ spec: - whenUnsatisfiable type: object type: array + useEphemeralVolume: + description: UseEphemeralVolume + type: boolean type: object apiUrl: description: |- @@ -4944,7 +5178,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: @@ -5015,6 +5249,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -5044,7 +5279,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -5218,7 +5454,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -5259,7 +5495,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -5290,6 +5527,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -5323,7 +5561,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -5485,7 +5724,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: @@ -5606,7 +5845,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -5647,7 +5886,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -5680,6 +5920,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -5709,7 +5950,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -5883,7 +6125,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -5924,7 +6166,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -5959,6 +6202,19 @@ spec: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. Set to true if you want to skip certification validation checks. type: boolean + telemetryService: + description: When a TelemetryServiceSpec is provided, the OTEL collector + is deployed by the operator. + properties: + protocols: + items: + type: string + type: array + serviceName: + type: string + tlsRefName: + type: string + type: object templates: properties: extensionExecutionController: @@ -6008,7 +6264,10 @@ spec: dataSource: description: |- dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s. + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified data source. properties: apiGroup: description: |- @@ -6060,6 +6319,7 @@ spec: If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. + More info: https://kubernetes. properties: limits: additionalProperties: @@ -6083,7 +6343,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object selector: @@ -6142,7 +6402,8 @@ spec: description: |- volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. type: string volumeMode: description: |- @@ -6211,7 +6472,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: @@ -6245,7 +6506,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -6314,7 +6576,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -6338,7 +6603,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -6354,12 +6619,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -6401,7 +6670,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -6560,6 +6830,7 @@ spec: the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6593,6 +6864,7 @@ spec: the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6621,7 +6893,8 @@ spec: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. properties: nodeSelectorTerms: description: Required. A list of node selector terms. @@ -6655,6 +6928,7 @@ spec: the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6688,6 +6962,7 @@ spec: the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6775,7 +7050,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: @@ -6807,7 +7082,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -6834,6 +7110,7 @@ spec: can have an updated DaemonSet pod during during an update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. + Absolute number is calculated from percentage by rounding up to a minimum of 1. x-kubernetes-int-or-string: true maxUnavailable: anyOf: @@ -6844,6 +7121,8 @@ spec: update. Value can be an absolute number (ex: 5) or a percentage of total number of DaemonSet pods at the start of the update (ex: 10%). Absolute number is calculated from percentage by rounding up. + This cannot be 0 if MaxSurge is 0 + Default value is 1. x-kubernetes-int-or-string: true type: object type: @@ -6954,7 +7233,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object secCompProfile: @@ -6990,7 +7269,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -7087,7 +7367,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: @@ -7120,7 +7400,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -7189,7 +7470,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -7213,7 +7497,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -7229,12 +7513,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -7356,6 +7644,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ diff --git a/config/crd/bases/dynatrace.com_edgeconnects.yaml b/config/crd/bases/dynatrace.com_edgeconnects.yaml index b531a0abb3..c13b78df53 100644 --- a/config/crd/bases/dynatrace.com_edgeconnects.yaml +++ b/config/crd/bases/dynatrace.com_edgeconnects.yaml @@ -90,7 +90,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. Cannot @@ -338,7 +339,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object serviceAccountName: @@ -374,7 +375,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -443,7 +445,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -467,7 +472,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -483,12 +488,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -536,6 +545,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ @@ -669,7 +679,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. Cannot @@ -918,7 +929,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object serviceAccountName: @@ -953,7 +964,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -1022,7 +1034,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -1046,7 +1061,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -1062,12 +1077,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -1115,6 +1134,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 11250e0ea1..53775b3e53 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -112,7 +112,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -295,7 +296,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: @@ -332,7 +333,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -401,7 +403,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -425,7 +430,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -441,12 +446,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -507,7 +516,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -685,7 +695,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: @@ -716,7 +726,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -785,7 +796,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -809,7 +823,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -825,12 +839,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -963,7 +981,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object useCSIDriver: @@ -990,6 +1008,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -1019,7 +1038,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -1193,7 +1213,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -1230,7 +1250,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -1260,6 +1281,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -1293,7 +1315,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -1455,7 +1478,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: @@ -1528,7 +1551,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -1565,7 +1588,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -1597,6 +1621,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -1626,7 +1651,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -1800,7 +1826,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -1837,7 +1863,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -1901,7 +1928,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -2079,7 +2107,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: @@ -2110,7 +2138,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -2179,7 +2208,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -2203,7 +2235,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -2219,12 +2251,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -2350,6 +2386,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ @@ -2526,7 +2563,8 @@ spec: values:\n\t- `routing` enables OneAgent routing.\n\t- `kubernetes-monitoring` enables Kubernetes API monitoring.\n\t- `metrics-ingest` opens the metrics ingest endpoint on the DynaKube ActiveGate and redirects - all pods to it." + all pods to it.\n\t- `dynatrace-api` enables calling the Dynatrace + API via ActiveGate." items: type: string type: array @@ -2562,7 +2600,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -2749,7 +2788,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: @@ -2786,7 +2825,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -2855,7 +2895,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -2879,7 +2922,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -2895,12 +2938,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -2914,7 +2961,7 @@ spec: Dynatrace `apiUrl`, including the `/api` path at the end. - For SaaS, set `YOUR_ENVIRONMENT_ID` to your environment ID. - For Managed, change the `apiUrl` address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www. + For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. type: string customPullSecret: description: |- @@ -3064,7 +3111,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: @@ -3140,6 +3187,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -3170,7 +3218,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -3345,7 +3394,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -3386,7 +3435,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -3418,6 +3468,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -3452,7 +3503,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -3614,7 +3666,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: @@ -3736,7 +3788,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -3777,7 +3829,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -3814,6 +3867,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -3844,7 +3898,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -4019,7 +4074,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -4060,7 +4115,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -4209,6 +4265,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ @@ -4439,7 +4496,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -4556,6 +4614,171 @@ spec: type: string description: Node selector to control the selection of nodes type: object + persistentVolumeClaim: + description: Defines storage device + properties: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified data source. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + More info: https://kubernetes. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is a label query over volumes to consider + for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. + type: string + volumeMode: + description: |- + volumeMode defines what type of volume is required by the claim. + Value of Filesystem is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. + type: string + type: object priorityClassName: description: |- If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that @@ -4622,7 +4845,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: @@ -4659,7 +4882,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -4728,7 +4952,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -4752,7 +4979,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -4768,12 +4995,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -4781,6 +5012,9 @@ spec: - whenUnsatisfiable type: object type: array + useEphemeralVolume: + description: UseEphemeralVolume + type: boolean type: object apiUrl: description: |- @@ -4956,7 +5190,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: @@ -5027,6 +5261,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -5056,7 +5291,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -5230,7 +5466,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -5271,7 +5507,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -5302,6 +5539,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -5335,7 +5573,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -5497,7 +5736,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: @@ -5618,7 +5857,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -5659,7 +5898,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -5692,6 +5932,7 @@ spec: description: |- Set additional arguments to the OneAgent installer. For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array @@ -5721,7 +5962,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -5895,7 +6137,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: @@ -5936,7 +6178,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -5971,6 +6214,19 @@ spec: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. Set to true if you want to skip certification validation checks. type: boolean + telemetryService: + description: When a TelemetryServiceSpec is provided, the OTEL collector + is deployed by the operator. + properties: + protocols: + items: + type: string + type: array + serviceName: + type: string + tlsRefName: + type: string + type: object templates: properties: extensionExecutionController: @@ -6020,7 +6276,10 @@ spec: dataSource: description: |- dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s. + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified data source. properties: apiGroup: description: |- @@ -6072,6 +6331,7 @@ spec: If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. + More info: https://kubernetes. properties: limits: additionalProperties: @@ -6095,7 +6355,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object selector: @@ -6154,7 +6414,8 @@ spec: description: |- volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. type: string volumeMode: description: |- @@ -6223,7 +6484,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: @@ -6257,7 +6518,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -6326,7 +6588,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -6350,7 +6615,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -6366,12 +6631,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -6413,7 +6682,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. @@ -6572,6 +6842,7 @@ spec: the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6605,6 +6876,7 @@ spec: the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6633,7 +6905,8 @@ spec: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. properties: nodeSelectorTerms: description: Required. A list of node selector terms. @@ -6667,6 +6940,7 @@ spec: the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6700,6 +6974,7 @@ spec: the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6787,7 +7062,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: @@ -6819,7 +7094,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -6846,6 +7122,7 @@ spec: can have an updated DaemonSet pod during during an update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. + Absolute number is calculated from percentage by rounding up to a minimum of 1. x-kubernetes-int-or-string: true maxUnavailable: anyOf: @@ -6856,6 +7133,8 @@ spec: update. Value can be an absolute number (ex: 5) or a percentage of total number of DaemonSet pods at the start of the update (ex: 10%). Absolute number is calculated from percentage by rounding up. + This cannot be 0 if MaxSurge is 0 + Default value is 1. x-kubernetes-int-or-string: true type: object type: @@ -6966,7 +7245,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object secCompProfile: @@ -7002,7 +7281,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -7099,7 +7379,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: @@ -7132,7 +7412,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -7201,7 +7482,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -7225,7 +7509,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -7241,12 +7525,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -7368,6 +7656,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ @@ -7630,7 +7919,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. Cannot @@ -7878,7 +8168,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object serviceAccountName: @@ -7914,7 +8204,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -7983,7 +8274,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -8007,7 +8301,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -8023,12 +8317,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -8076,6 +8374,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ @@ -8209,7 +8508,8 @@ spec: Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: description: Source for the environment variable's value. Cannot @@ -8458,7 +8758,7 @@ spec: Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object serviceAccountName: @@ -8493,7 +8793,8 @@ spec: description: |- TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: @@ -8562,7 +8863,10 @@ spec: matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. items: type: string type: array @@ -8586,7 +8890,7 @@ spec: NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: description: |- @@ -8602,12 +8906,16 @@ spec: and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. + We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: description: |- WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. type: string required: - maxSkew @@ -8655,6 +8963,7 @@ spec: Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. + This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ diff --git a/doc/api/dynakube-api-ref.md b/doc/api/dynakube-api-ref.md index 9a28cdcdfe..4adedce267 100644 --- a/doc/api/dynakube-api-ref.md +++ b/doc/api/dynakube-api-ref.md @@ -41,6 +41,7 @@ |`tlsSecretName`|The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used.
server.p12: certificate+key pair in pkcs12 format
password: passphrase to read server.p12|-|string| |`tolerations`|Set tolerations for the ActiveGate pods|-|array| |`topologySpreadConstraints`|Adds TopologySpreadConstraints for the ActiveGate pods|-|array| +|`useEphemeralVolume`|UseEphemeralVolume|-|boolean| ### .spec.logMonitoring @@ -48,6 +49,14 @@ |:-|:-|:-|:-| |`ingestRuleMatchers`||-|array| +### .spec.telemetryService + +|Parameter|Description|Default value|Data type| +|:-|:-|:-|:-| +|`protocols`||-|array| +|`serviceName`||-|string| +|`tlsRefName`||-|string| + ### .spec.metadataEnrichment |Parameter|Description|Default value|Data type| @@ -60,7 +69,7 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| |`annotations`|Add custom OneAgent annotations.|-|object| -|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().|-|array| +|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().
For the list of limitations, see Limitations ().
Enabled by default.|-|boolean| |`dnsPolicy`|Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy ().|-|string| |`env`|Set additional environment variables for the OneAgent pods.|-|array| @@ -92,7 +101,7 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| |`annotations`|Add custom OneAgent annotations.|-|object| -|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().|-|array| +|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().
For the list of limitations, see Limitations ().
Enabled by default.|-|boolean| |`dnsPolicy`|Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy ().|-|string| |`env`|Set additional environment variables for the OneAgent pods.|-|array| @@ -110,7 +119,7 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| |`annotations`|Add custom OneAgent annotations.|-|object| -|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().|-|array| +|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().
For the list of limitations, see Limitations ().
Enabled by default.|-|boolean| |`codeModulesImage`|Use a custom OneAgent CodeModule image to download binaries.|-|string| |`dnsPolicy`|Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy ().|-|string| @@ -135,6 +144,19 @@ |`namespaceSelector`|Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject.
For more information, see Configure monitoring for namespaces and pods (More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1|-|array| +|`dataSource`|dataSource field can be used to specify either:
* An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)
* An existing PVC (PersistentVolumeClaim)
If the provisioner or an external controller can support the specified data source,
it will create a new volume based on the contents of the specified data source.|-|object| +|`resources`|resources represents the minimum resources the volume should have.
If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.|-|object| +|`selector`|selector is a label query over volumes to consider for binding.|-|object| +|`storageClassName`|storageClassName is the name of the StorageClass required by the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1|-|string| +|`volumeAttributesClassName`|volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
it can be changed after the claim is created.|-|string| +|`volumeMode`|volumeMode defines what type of volume is required by the claim.
Value of Filesystem is implied when not included in claim spec.|-|string| +|`volumeName`|volumeName is the binding reference to the PersistentVolume backing this claim.|-|string| + ### .spec.templates.logMonitoring.imageRef |Parameter|Description|Default value|Data type| @@ -188,6 +210,15 @@ |`repository`|Custom image repository|-|string| |`tag`|Indicates a tag of the image to use|-|string| +### .spec.activeGate.persistentVolumeClaim.dataSourceRef + +|Parameter|Description|Default value|Data type| +|:-|:-|:-|:-| +|`apiGroup`|APIGroup is the group for the resource being referenced.
If APIGroup is not specified, the specified Kind must be in the core API group.
For any other third-party types, APIGroup is required.|-|string| +|`kind`|Kind is the type of resource being referenced|-|string| +|`name`|Name is the name of resource being referenced|-|string| +|`namespace`|Namespace is the namespace of resource being referenced
Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.|-|string| + ### .spec.templates.extensionExecutionController.imageRef |Parameter|Description|Default value|Data type| @@ -207,7 +238,7 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| |`preferredDuringSchedulingIgnoredDuringExecution`|The scheduler will prefer to schedule pods to nodes that satisfy
the affinity expressions specified by this field, but it may choose
a node that violates one or more of the expressions. The node that is
most preferred is the one with the greatest sum of weights, i.e.|-|array| -|`requiredDuringSchedulingIgnoredDuringExecution`|If the affinity requirements specified by this field are not met at
scheduling time, the pod will not be scheduled onto the node.
If the affinity requirements specified by this field cease to be met
at some point during pod execution (e.g.|-|object| +|`requiredDuringSchedulingIgnoredDuringExecution`|If the affinity requirements specified by this field are not met at
scheduling time, the pod will not be scheduled onto the node.
If the affinity requirements specified by this field cease to be met
at some point during pod execution (e.g. due to an update), the system
may or may not try to eventually evict the pod from its node.|-|object| ### .spec.templates.kspmNodeConfigurationCollector.updateStrategy @@ -220,11 +251,11 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| |`accessModes`|accessModes contains the desired access modes the volume should have.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1|-|array| -|`dataSource`|dataSource field can be used to specify either:
* An existing VolumeSnapshot object (snapshot.storage.k8s.|-|object| -|`resources`|resources represents the minimum resources the volume should have.
If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.|-|object| +|`dataSource`|dataSource field can be used to specify either:
* An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)
* An existing PVC (PersistentVolumeClaim)
If the provisioner or an external controller can support the specified data source,
it will create a new volume based on the contents of the specified data source.|-|object| +|`resources`|resources represents the minimum resources the volume should have.
If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.|-|object| |`selector`|selector is a label query over volumes to consider for binding.|-|object| |`storageClassName`|storageClassName is the name of the StorageClass required by the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1|-|string| -|`volumeAttributesClassName`|volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass.|-|string| +|`volumeAttributesClassName`|volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
it can be changed after the claim is created.|-|string| |`volumeMode`|volumeMode defines what type of volume is required by the claim.
Value of Filesystem is implied when not included in claim spec.|-|string| |`volumeName`|volumeName is the binding reference to the PersistentVolume backing this claim.|-|string| @@ -232,8 +263,8 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`maxSurge`|The maximum number of nodes with an existing available DaemonSet pod that
can have an updated DaemonSet pod during during an update.
Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
This can not be 0 if MaxUnavailable is 0.|-|integer or string| -|`maxUnavailable`|The maximum number of DaemonSet pods that can be unavailable during the
update. Value can be an absolute number (ex: 5) or a percentage of total
number of DaemonSet pods at the start of the update (ex: 10%). Absolute
number is calculated from percentage by rounding up.|-|integer or string| +|`maxSurge`|The maximum number of nodes with an existing available DaemonSet pod that
can have an updated DaemonSet pod during during an update.
Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
This can not be 0 if MaxUnavailable is 0.
Absolute number is calculated from percentage by rounding up to a minimum of 1.|-|integer or string| +|`maxUnavailable`|The maximum number of DaemonSet pods that can be unavailable during the
update. Value can be an absolute number (ex: 5) or a percentage of total
number of DaemonSet pods at the start of the update (ex: 10%). Absolute
number is calculated from percentage by rounding up.
This cannot be 0 if MaxSurge is 0
Default value is 1.|-|integer or string| ### .spec.templates.extensionExecutionController.persistentVolumeClaim.dataSourceRef diff --git a/hack/make/manifests/config.mk b/hack/make/manifests/config.mk index f148f61315..c45721f4bd 100644 --- a/hack/make/manifests/config.mk +++ b/hack/make/manifests/config.mk @@ -1,4 +1,4 @@ -CRD_OPTIONS ?= "crd:crdVersions=v1,maxDescLen=300,ignoreUnexportedFields=true" +CRD_OPTIONS ?= "crd:crdVersions=v1,maxDescLen=350,ignoreUnexportedFields=true" OLM ?= false diff --git a/pkg/api/v1beta3/dynakube/activegate/props.go b/pkg/api/v1beta3/dynakube/activegate/props.go index 0bb8daf157..a7e9e70120 100644 --- a/pkg/api/v1beta3/dynakube/activegate/props.go +++ b/pkg/api/v1beta3/dynakube/activegate/props.go @@ -27,6 +27,10 @@ func (ag *Spec) SetExtensionsDependency(isEnabled bool) { ag.enabledDependencies.extensions = isEnabled } +func (ag *Spec) SetOTLPingestDependency(isEnabled bool) { + ag.enabledDependencies.otlpIngest = isEnabled +} + func (ag *Spec) apiUrlHost() string { parsedUrl, err := url.Parse(ag.apiUrl) if err != nil { diff --git a/pkg/api/v1beta3/dynakube/activegate/spec.go b/pkg/api/v1beta3/dynakube/activegate/spec.go index e58f866682..992072897a 100644 --- a/pkg/api/v1beta3/dynakube/activegate/spec.go +++ b/pkg/api/v1beta3/dynakube/activegate/spec.go @@ -60,22 +60,26 @@ type ActiveGate struct { // dependencies is a collection of possible other feature/components that need an ActiveGate, but is not directly configured in the ActiveGate section. type dependencies struct { extensions bool + otlpIngest bool } func (d dependencies) Any() bool { - return d.extensions // kspm is a dependency too, but blocked by validation webhook to not run standalone + return d.extensions || d.otlpIngest // kspm is a dependency too, but blocked by validation webhook to not run standalone } // +kubebuilder:object:generate=true type Spec struct { - CapabilityProperties `json:",inline"` // Adds additional annotations to the ActiveGate pods // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Annotations",order=27,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} Annotations map[string]string `json:"annotations,omitempty"` + // Defines storage device + // +kubebuilder:validation:Optional + PersistentVolumeClaim *corev1.PersistentVolumeClaimSpec `json:"persistentVolumeClaim,omitempty"` + name string apiUrl string @@ -97,10 +101,15 @@ type Spec struct { // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Priority Class name",order=23,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:io.kubernetes:PriorityClass"} PriorityClassName string `json:"priorityClassName,omitempty"` + CapabilityProperties `json:",inline"` + // Activegate capabilities enabled (routing, kubernetes-monitoring, metrics-ingest, dynatrace-api) Capabilities []CapabilityDisplayName `json:"capabilities,omitempty"` enabledDependencies dependencies + + // UseEphemeralVolume + UseEphemeralVolume bool `json:"useEphemeralVolume,omitempty"` } // +kubebuilder:object:generate=true diff --git a/pkg/api/v1beta3/dynakube/activegate/zz_generated.deepcopy.go b/pkg/api/v1beta3/dynakube/activegate/zz_generated.deepcopy.go index ee12d4da18..910cebcf43 100644 --- a/pkg/api/v1beta3/dynakube/activegate/zz_generated.deepcopy.go +++ b/pkg/api/v1beta3/dynakube/activegate/zz_generated.deepcopy.go @@ -87,7 +87,6 @@ func (in *CapabilityProperties) DeepCopy() *CapabilityProperties { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Spec) DeepCopyInto(out *Spec) { *out = *in - in.CapabilityProperties.DeepCopyInto(&out.CapabilityProperties) if in.Annotations != nil { in, out := &in.Annotations, &out.Annotations *out = make(map[string]string, len(*in)) @@ -95,6 +94,12 @@ func (in *Spec) DeepCopyInto(out *Spec) { (*out)[key] = val } } + if in.PersistentVolumeClaim != nil { + in, out := &in.PersistentVolumeClaim, &out.PersistentVolumeClaim + *out = new(v1.PersistentVolumeClaimSpec) + (*in).DeepCopyInto(*out) + } + in.CapabilityProperties.DeepCopyInto(&out.CapabilityProperties) if in.Capabilities != nil { in, out := &in.Capabilities, &out.Capabilities *out = make([]CapabilityDisplayName, len(*in)) diff --git a/pkg/api/v1beta3/dynakube/activegate_props.go b/pkg/api/v1beta3/dynakube/activegate_props.go index d7573c5f1d..4c9bdc2234 100644 --- a/pkg/api/v1beta3/dynakube/activegate_props.go +++ b/pkg/api/v1beta3/dynakube/activegate_props.go @@ -8,6 +8,7 @@ func (dk *DynaKube) ActiveGate() *activegate.ActiveGate { dk.Spec.ActiveGate.SetApiUrl(dk.ApiUrl()) dk.Spec.ActiveGate.SetName(dk.Name) dk.Spec.ActiveGate.SetExtensionsDependency(dk.IsExtensionsEnabled()) + dk.Spec.ActiveGate.SetOTLPingestDependency(dk.IsOTLPingestEnabled()) return &activegate.ActiveGate{ Spec: &dk.Spec.ActiveGate, diff --git a/pkg/api/v1beta3/dynakube/dynakube_types.go b/pkg/api/v1beta3/dynakube/dynakube_types.go index 6db9fe3c6f..3ceca7f9ef 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_types.go +++ b/pkg/api/v1beta3/dynakube/dynakube_types.go @@ -10,6 +10,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -92,6 +93,10 @@ type DynaKubeSpec struct { //nolint:revive // +kubebuilder:validation:Optional Extensions *ExtensionsSpec `json:"extensions,omitempty"` + // When a TelemetryServiceSpec is provided, the OTEL collector is deployed by the operator. + // +kubebuilder:validation:Optional + TelemetryService *telemetryservice.Spec `json:"telemetryService,omitempty"` + // General configuration about OneAgent instances. // You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text" @@ -146,6 +151,8 @@ type DynaKubeSpec struct { //nolint:revive // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Enable Istio automatic management",order=9,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} EnableIstio bool `json:"enableIstio,omitempty"` + + EnableOTLPingest bool `json:"-"` } type TemplatesSpec struct { diff --git a/pkg/api/v1beta3/dynakube/otlp_props.go b/pkg/api/v1beta3/dynakube/otlp_props.go new file mode 100644 index 0000000000..3504d7e038 --- /dev/null +++ b/pkg/api/v1beta3/dynakube/otlp_props.go @@ -0,0 +1,5 @@ +package dynakube + +func (dk *DynaKube) IsOTLPingestEnabled() bool { + return dk.Spec.EnableOTLPingest +} diff --git a/pkg/api/v1beta3/dynakube/telemetryservice/props.go b/pkg/api/v1beta3/dynakube/telemetryservice/props.go new file mode 100644 index 0000000000..1282ce4bfb --- /dev/null +++ b/pkg/api/v1beta3/dynakube/telemetryservice/props.go @@ -0,0 +1,40 @@ +package telemetryservice + +type Protocol string + +const ( + OtlpProtocol Protocol = "otlp" + ZipkinProtocol Protocol = "zipkin" + JaegerProtocol Protocol = "jaeger" + StatsdProtocol Protocol = "statsd" +) + +func KnownProtocols() []Protocol { + return []Protocol{ + OtlpProtocol, + ZipkinProtocol, + JaegerProtocol, + StatsdProtocol, + } +} + +func (spec *Spec) GetProtocols() []Protocol { + if spec == nil { + return []Protocol{} + } + + if len(spec.Protocols) == 0 { + return KnownProtocols() + } + + protocols := make([]Protocol, len(spec.Protocols)) + for i, proto := range spec.Protocols { + protocols[i] = Protocol(proto) + } + + return protocols +} + +func (ts *TelemetryService) IsEnabled() bool { + return ts.Spec != nil +} diff --git a/pkg/api/v1beta3/dynakube/telemetryservice/spec.go b/pkg/api/v1beta3/dynakube/telemetryservice/spec.go new file mode 100644 index 0000000000..e166985e1f --- /dev/null +++ b/pkg/api/v1beta3/dynakube/telemetryservice/spec.go @@ -0,0 +1,18 @@ +package telemetryservice + +type TelemetryService struct { + *Spec +} + +// +kubebuilder:object:generate=true + +type Spec struct { + // +kubebuilder:validation:Optional + ServiceName string `json:"serviceName,omitempty"` + + // +kubebuilder:validation:Optional + TlsRefName string `json:"tlsRefName,omitempty"` + + // +kubebuilder:validation:Optional + Protocols []string `json:"protocols,omitempty"` +} diff --git a/pkg/api/v1beta3/dynakube/telemetryservice/zz_generated.deepcopy.go b/pkg/api/v1beta3/dynakube/telemetryservice/zz_generated.deepcopy.go new file mode 100644 index 0000000000..a30d50258a --- /dev/null +++ b/pkg/api/v1beta3/dynakube/telemetryservice/zz_generated.deepcopy.go @@ -0,0 +1,41 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package telemetryservice + +import () + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Spec) DeepCopyInto(out *Spec) { + *out = *in + if in.Protocols != nil { + in, out := &in.Protocols, &out.Protocols + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. +func (in *Spec) DeepCopy() *Spec { + if in == nil { + return nil + } + out := new(Spec) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/api/v1beta3/dynakube/telemetryservice_props.go b/pkg/api/v1beta3/dynakube/telemetryservice_props.go new file mode 100644 index 0000000000..4a332e08f1 --- /dev/null +++ b/pkg/api/v1beta3/dynakube/telemetryservice_props.go @@ -0,0 +1,11 @@ +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" +) + +func (dk *DynaKube) TelemetryService() *telemetryservice.TelemetryService { + return &telemetryservice.TelemetryService{ + Spec: dk.Spec.TelemetryService, + } +} diff --git a/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go b/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go index f9813d44b4..11dcedeccf 100644 --- a/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go +++ b/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go @@ -22,6 +22,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -115,6 +116,11 @@ func (in *DynaKubeSpec) DeepCopyInto(out *DynaKubeSpec) { *out = new(ExtensionsSpec) **out = **in } + if in.TelemetryService != nil { + in, out := &in.TelemetryService, &out.TelemetryService + *out = new(telemetryservice.Spec) + (*in).DeepCopyInto(*out) + } in.OneAgent.DeepCopyInto(&out.OneAgent) in.Templates.DeepCopyInto(&out.Templates) in.ActiveGate.DeepCopyInto(&out.ActiveGate) diff --git a/pkg/api/validation/dynakube/activegate.go b/pkg/api/validation/dynakube/activegate.go index da6c0c72c2..5c421403bf 100644 --- a/pkg/api/validation/dynakube/activegate.go +++ b/pkg/api/validation/dynakube/activegate.go @@ -17,6 +17,8 @@ Make sure you correctly specify the ActiveGate capabilities in your custom resou errorDuplicateActiveGateCapability = `The DynaKube's specification tries to specify duplicate capabilities in the ActiveGate section, duplicate capability=%s. Make sure you don't duplicate an Activegate capability in your custom resource. ` + errorActiveGateInvalidPVCConfiguration = ` DynaKube specifies a PVC for the ActiveGate while ephemeral volume is also enabled. These settings are mutually exclusive, please choose only one.` + warningMissingActiveGateMemoryLimit = `ActiveGate specification missing memory limits. Can cause excess memory usage.` ) @@ -66,3 +68,17 @@ func missingActiveGateMemoryLimit(_ context.Context, _ *Validator, dk *dynakube. func memoryLimitSet(resources corev1.ResourceRequirements) bool { return resources.Limits != nil && resources.Limits.Memory() != nil } + +func activeGateMutuallyExclusivePVCSettings(dk *dynakube.DynaKube) bool { + return dk.Spec.ActiveGate.UseEphemeralVolume && dk.Spec.ActiveGate.PersistentVolumeClaim != nil +} + +func mutuallyExclusiveActiveGatePVsettings(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if activeGateMutuallyExclusivePVCSettings(dk) { + log.Info("requested dynakube specifies mutually exclusive PersistentVolumeClaim settings for ActiveGate.", "name", dk.Name, "namespace", dk.Namespace) + + return errorActiveGateInvalidPVCConfiguration + } + + return "" +} diff --git a/pkg/api/validation/dynakube/activegate_test.go b/pkg/api/validation/dynakube/activegate_test.go index e2cafff1d3..e39347700a 100644 --- a/pkg/api/validation/dynakube/activegate_test.go +++ b/pkg/api/validation/dynakube/activegate_test.go @@ -87,3 +87,46 @@ func TestMissingActiveGateMemoryLimit(t *testing.T) { }) }) } + +func TestActiveGatePVCSettings(t *testing.T) { + t.Run(`EphemeralVolume disabled and PVC specified`, func(t *testing.T) { + assertAllowed(t, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + ActiveGate: activegate.Spec{ + UseEphemeralVolume: false, + PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{}, + }, + }, + }) + }) + t.Run(`EphemeralVolume enabled and no PVC specified`, func(t *testing.T) { + assertAllowed(t, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + ActiveGate: activegate.Spec{ + UseEphemeralVolume: true, + }, + }, + }) + }) + t.Run(`EphemeralVolume enabled and PVC specified`, func(t *testing.T) { + assertDenied(t, + []string{errorActiveGateInvalidPVCConfiguration}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + Extensions: &dynakube.ExtensionsSpec{}, + ActiveGate: activegate.Spec{ + UseEphemeralVolume: true, + PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{}, + }, + }, + }) + }) +} diff --git a/pkg/api/validation/dynakube/telemetryservice.go b/pkg/api/validation/dynakube/telemetryservice.go new file mode 100644 index 0000000000..36ac8ec51f --- /dev/null +++ b/pkg/api/validation/dynakube/telemetryservice.go @@ -0,0 +1,84 @@ +package validation + +import ( + "context" + "slices" + "strings" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" +) + +const ( + errorTelemetryServiceNotEnoughProtocols = `DynaKube's specification enables the TelemetryService feature, at least one Protocol has to be specified.` + errorTelemetryServiceUnknownProtocols = `DynaKube's specification enables the TelemetryService feature, unsupported protocols found on the Protocols list.` + errorTelemetryServiceDuplicatedProtocols = `DynaKube's specification enables the TelemetryService feature, duplicated protocols found on the Protocols list.` +) + +func emptyTelemetryServiceProtocolsList(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryService().IsEnabled() { + return "" + } + + if len(dk.TelemetryService().GetProtocols()) == 0 { + log.Info("requested dynakube specify empty list of Protocols") + + return errorTelemetryServiceNotEnoughProtocols + } + + return "" +} + +func unknownTelemetryServiceProtocols(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryService().IsEnabled() { + return "" + } + + var unknownProtocols []string + + for _, protocol := range dk.TelemetryService().GetProtocols() { + if !slices.Contains(telemetryservice.KnownProtocols(), protocol) { + unknownProtocols = append(unknownProtocols, string(protocol)) + } + } + + if len(unknownProtocols) > 0 { + log.Info("requested dynakube specify unknown TelemetryService protocol(s)", "protocols", strings.Join(unknownProtocols, ",")) + + return errorTelemetryServiceUnknownProtocols + } + + return "" +} + +func duplicatedTelemetryServiceProtocols(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryService().IsEnabled() { + return "" + } + + protocolsOccurrences := map[telemetryservice.Protocol]int{} + + for _, protocol := range dk.TelemetryService().GetProtocols() { + if _, ok := protocolsOccurrences[protocol]; !ok { + protocolsOccurrences[protocol] = 1 + } else { + protocolsOccurrences[protocol] += 1 + } + } + + var duplicatedProtocols []string + + for protocol, count := range protocolsOccurrences { + if count > 1 { + duplicatedProtocols = append(duplicatedProtocols, string(protocol)) + } + } + + if len(duplicatedProtocols) > 0 { + log.Info("requested dynakube specify duplicated TelemetryService protocol(s)", "protocols", strings.Join(duplicatedProtocols, ",")) + + return errorTelemetryServiceDuplicatedProtocols + } + + return "" +} diff --git a/pkg/api/validation/dynakube/telemetryservice_test.go b/pkg/api/validation/dynakube/telemetryservice_test.go new file mode 100644 index 0000000000..1afa421a61 --- /dev/null +++ b/pkg/api/validation/dynakube/telemetryservice_test.go @@ -0,0 +1,132 @@ +package validation + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" +) + +func TestTelemetryServiceProtocols(t *testing.T) { + t.Run(`no list of protocols`, func(t *testing.T) { + assertAllowed(t, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryService: &telemetryservice.Spec{ + Protocols: nil, + }, + }, + }) + }) + + t.Run(`empty list of protocols`, func(t *testing.T) { + assertAllowed(t, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryService: &telemetryservice.Spec{ + Protocols: []string{}, + }, + }, + }) + }) + + t.Run(`unknown protocol`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryServiceUnknownProtocols}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryService: &telemetryservice.Spec{ + Protocols: []string{ + string(telemetryservice.ZipkinProtocol), + string(telemetryservice.OtlpProtocol), + "unknown", + }, + }, + }, + }) + }) + + t.Run(`unknown protocols`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryServiceUnknownProtocols}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryService: &telemetryservice.Spec{ + Protocols: []string{ + string(telemetryservice.ZipkinProtocol), + string(telemetryservice.OtlpProtocol), + "unknown1", + "unknown2", + }, + }, + }, + }) + }) + + t.Run(`duplicated protocol`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryServiceDuplicatedProtocols}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryService: &telemetryservice.Spec{ + Protocols: []string{ + string(telemetryservice.ZipkinProtocol), + string(telemetryservice.OtlpProtocol), + string(telemetryservice.OtlpProtocol), + }, + }, + }, + }) + }) + + t.Run(`duplicated protocols`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryServiceDuplicatedProtocols}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryService: &telemetryservice.Spec{ + Protocols: []string{ + string(telemetryservice.ZipkinProtocol), + string(telemetryservice.ZipkinProtocol), + string(telemetryservice.OtlpProtocol), + string(telemetryservice.OtlpProtocol), + string(telemetryservice.JaegerProtocol), + }, + }, + }, + }) + }) + + t.Run(`default config`, func(t *testing.T) { + assertAllowed(t, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryService: &telemetryservice.Spec{}, + }, + }) + }) + + t.Run(`no telemetry service`, func(t *testing.T) { + assertAllowed(t, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + }, + }) + }) +} diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 837a7fd76f..51c44c0222 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -36,6 +36,7 @@ var ( disabledCSIForReadonlyCSIVolume, invalidActiveGateCapabilities, duplicateActiveGateCapabilities, + mutuallyExclusiveActiveGatePVsettings, invalidActiveGateProxyUrl, conflictingOneAgentConfiguration, conflictingOneAgentNodeSelector, @@ -53,6 +54,9 @@ var ( missingKSPMDependency, missingKSPMImage, missingLogMonitoringImage, + emptyTelemetryServiceProtocolsList, + unknownTelemetryServiceProtocols, + duplicatedTelemetryServiceProtocols, } validatorWarningFuncs = []validatorFunc{ missingActiveGateMemoryLimit, diff --git a/pkg/controllers/dynakube/activegate/capability/capability.go b/pkg/controllers/dynakube/activegate/capability/capability.go index 01259a7dbe..2d34468f3c 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability.go +++ b/pkg/controllers/dynakube/activegate/capability/capability.go @@ -102,6 +102,11 @@ func NewMultiCapability(dk *dynakube.DynaKube) Capability { capabilityDisplayNames = append(capabilityDisplayNames, "extension_controller") } + if dk.IsOTLPingestEnabled() || dk.TelemetryService().IsEnabled() { + capabilityNames = append(capabilityNames, "log_analytics_collector", "generic_ingest_enabled", "otlp_ingest") + capabilityDisplayNames = append(capabilityDisplayNames, "log_analytics_collector", "generic_ingest_enabled", "otlp_ingest") + } + mc.argName = strings.Join(capabilityNames, ",") mc.displayName = strings.Join(capabilityDisplayNames, ", ") diff --git a/pkg/controllers/dynakube/activegate/capability/capability_test.go b/pkg/controllers/dynakube/activegate/capability/capability_test.go index adb75d156f..c05bb186d9 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability_test.go +++ b/pkg/controllers/dynakube/activegate/capability/capability_test.go @@ -5,6 +5,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -12,13 +13,17 @@ import ( ) const ( - testNamespace = "test-namespace" - testName = "test-name" - testApiUrl = "https://demo.dev.dynatracelabs.com/api" - expectedShortName = "activegate" - expectedArgName = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface" - expectedArgNameWithExtensions = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller" - expectedArgNameWithExtensionsOnly = "extension_controller" + testNamespace = "test-namespace" + testName = "test-name" + testApiUrl = "https://demo.dev.dynatracelabs.com/api" + expectedShortName = "activegate" + expectedArgName = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface" + expectedArgNameWithExtensions = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller" + expectedArgNameWithExtensionsOnly = "extension_controller" + expectedArgNameWithOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest_enabled,otlp_ingest" + expectedArgNameWithOTLPingestOnly = "log_analytics_collector,generic_ingest_enabled,otlp_ingest" + expectedArgNameWithExtensionsAndOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller,log_analytics_collector,generic_ingest_enabled,otlp_ingest" + expectedArgNameWithTelemetryService = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest_enabled,otlp_ingest" ) var capabilities = []activegate.CapabilityDisplayName{ @@ -28,12 +33,17 @@ var capabilities = []activegate.CapabilityDisplayName{ activegate.DynatraceApiCapability.DisplayName, } -func buildDynakube(capabilities []activegate.CapabilityDisplayName, enableExtensions bool) *dynakube.DynaKube { +func buildDynakube(capabilities []activegate.CapabilityDisplayName, enableExtensions bool, enableOTLPingest bool, enableTelemetryService bool) *dynakube.DynaKube { extensionsSpec := &dynakube.ExtensionsSpec{} if !enableExtensions { extensionsSpec = nil } + telemetryServiceSpec := &telemetryservice.Spec{} + if !enableTelemetryService { + telemetryServiceSpec = nil + } + return &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Namespace: testNamespace, Name: testName, @@ -43,7 +53,9 @@ func buildDynakube(capabilities []activegate.CapabilityDisplayName, enableExtens ActiveGate: activegate.Spec{ Capabilities: capabilities, }, - Extensions: extensionsSpec, + Extensions: extensionsSpec, + EnableOTLPingest: enableOTLPingest, + TelemetryService: telemetryServiceSpec, }, } } @@ -68,7 +80,7 @@ func TestBuildServiceName(t *testing.T) { func TestNewMultiCapability(t *testing.T) { t.Run(`creates new multicapability`, func(t *testing.T) { - dk := buildDynakube(capabilities, false) + dk := buildDynakube(capabilities, false, false, false) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.True(t, mc.Enabled()) @@ -77,7 +89,7 @@ func TestNewMultiCapability(t *testing.T) { }) t.Run(`creates new multicapability without capabilities set in dynakube`, func(t *testing.T) { var emptyCapabilites []activegate.CapabilityDisplayName - dk := buildDynakube(emptyCapabilites, false) + dk := buildDynakube(emptyCapabilites, false, false, false) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.False(t, mc.Enabled()) @@ -88,7 +100,7 @@ func TestNewMultiCapability(t *testing.T) { func TestNewMultiCapabilityWithExtensions(t *testing.T) { t.Run(`creates new multicapability with Extensions enabled`, func(t *testing.T) { - dk := buildDynakube(capabilities, true) + dk := buildDynakube(capabilities, true, false, false) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.True(t, mc.Enabled()) @@ -97,7 +109,7 @@ func TestNewMultiCapabilityWithExtensions(t *testing.T) { }) t.Run(`creates new multicapability without capabilities set in dynakube and Extensions enabled`, func(t *testing.T) { var emptyCapabilites []activegate.CapabilityDisplayName - dk := buildDynakube(emptyCapabilites, true) + dk := buildDynakube(emptyCapabilites, true, false, false) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.True(t, mc.Enabled()) @@ -106,6 +118,69 @@ func TestNewMultiCapabilityWithExtensions(t *testing.T) { }) } +func TestNewMultiCapabilityWithOTLPingest(t *testing.T) { + t.Run(`creates new multicapability with OTLPingest enabled`, func(t *testing.T) { + dk := buildDynakube(capabilities, false, true, false) + mc := NewMultiCapability(dk) + require.NotNil(t, mc) + assert.True(t, mc.Enabled()) + assert.Equal(t, expectedShortName, mc.ShortName()) + assert.Equal(t, expectedArgNameWithOTLPingest, mc.ArgName()) + }) + t.Run(`creates new multicapability without capabilities set in dynakube and OTLPingest enabled`, func(t *testing.T) { + var emptyCapabilites []activegate.CapabilityDisplayName + dk := buildDynakube(emptyCapabilites, false, true, false) + mc := NewMultiCapability(dk) + require.NotNil(t, mc) + assert.True(t, mc.Enabled()) + assert.Equal(t, expectedShortName, mc.ShortName()) + assert.Equal(t, expectedArgNameWithOTLPingestOnly, mc.ArgName()) + }) +} + +func TestNewMultiCapabilityWithExtensionsAndOTLPingest(t *testing.T) { + t.Run(`creates new multicapability with Extensions and OTLPingest enabled`, func(t *testing.T) { + dk := buildDynakube(capabilities, true, true, false) + mc := NewMultiCapability(dk) + require.NotNil(t, mc) + assert.True(t, mc.Enabled()) + assert.Equal(t, expectedShortName, mc.ShortName()) + assert.Equal(t, expectedArgNameWithExtensionsAndOTLPingest, mc.ArgName()) + }) +} + +func TestNewMultiCapabilityWithTelemetryService(t *testing.T) { + t.Run(`creates new multicapability with TelemetryService enabled`, func(t *testing.T) { + dk := buildDynakube(capabilities, false, false, true) + mc := NewMultiCapability(dk) + require.NotNil(t, mc) + assert.True(t, mc.Enabled()) + assert.Equal(t, expectedShortName, mc.ShortName()) + assert.Equal(t, expectedArgNameWithTelemetryService, mc.ArgName()) + }) + t.Run(`creates new multicapability without capabilities set in dynakube and TelemetryService enabled`, func(t *testing.T) { + var emptyCapabilites []activegate.CapabilityDisplayName + dk := buildDynakube(emptyCapabilites, false, false, true) + mc := NewMultiCapability(dk) + require.NotNil(t, mc) + assert.False(t, mc.Enabled()) + assert.Equal(t, expectedShortName, mc.ShortName()) + assert.Empty(t, mc.ArgName()) + }) +} + +func TestNewMultiCapabilityWithOTLPingestAndTelemetryService(t *testing.T) { + t.Run(`creates new multicapability without capabilities set in dynakube and with OTLPingest and TelemetryService enabled`, func(t *testing.T) { + var emptyCapabilites []activegate.CapabilityDisplayName + dk := buildDynakube(emptyCapabilites, false, true, true) + mc := NewMultiCapability(dk) + require.NotNil(t, mc) + assert.True(t, mc.Enabled()) + assert.Equal(t, expectedShortName, mc.ShortName()) + assert.Equal(t, expectedArgNameWithOTLPingestOnly, mc.ArgName()) + }) +} + func TestBuildServiceDomainNameForDNSEntryPoint(t *testing.T) { actual := buildServiceDomainName("test-name", "test-namespace", "test-component-feature") assert.NotEmpty(t, actual) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go index 99d3db9e30..15ced80792 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go @@ -62,12 +62,6 @@ func (mod ReadOnlyModifier) getVolumes() []corev1.Volume { EmptyDir: &corev1.EmptyDirVolumeSource{}, }, }, - { - Name: consts.GatewayTmpVolumeName, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, { Name: consts.GatewayConfigVolumeName, VolumeSource: corev1.VolumeSource{ @@ -94,11 +88,6 @@ func (mod ReadOnlyModifier) getVolumeMounts() []corev1.VolumeMount { Name: consts.GatewayLogVolumeName, MountPath: consts.GatewayLogMountPoint, }, - { - ReadOnly: false, - Name: consts.GatewayTmpVolumeName, - MountPath: consts.GatewayTmpMountPoint, - }, { ReadOnly: false, Name: consts.GatewayConfigVolumeName, diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index ea99b3caf5..1ad00e44bf 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -16,14 +16,17 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/util/prioritymap" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" ) -const defaultEnvPriority = prioritymap.DefaultPriority -const customEnvPriority = prioritymap.HighPriority +const ( + defaultEnvPriority = prioritymap.DefaultPriority + customEnvPriority = prioritymap.HighPriority +) type Builder struct { capability capability.Capability @@ -64,6 +67,7 @@ func (statefulSetBuilder Builder) getBase() appsv1.StatefulSet { statefulSetBuilder.addUserAnnotations(&sts) statefulSetBuilder.addLabels(&sts) statefulSetBuilder.addTemplateSpec(&sts) + statefulSetBuilder.addPersistentVolumeClaim(&sts) if statefulSetBuilder.dynakube.FeatureActiveGateAppArmor() { sts.Spec.Template.ObjectMeta.Annotations[consts.AnnotationActiveGateContainerAppArmor] = "runtime/default" @@ -119,16 +123,13 @@ func (statefulSetBuilder Builder) addTemplateSpec(sts *appsv1.StatefulSet) { ServiceAccountName: statefulSetBuilder.dynakube.ActiveGate().GetServiceAccountName(), Affinity: statefulSetBuilder.nodeAffinity(), Tolerations: statefulSetBuilder.capability.Properties().Tolerations, - SecurityContext: &corev1.PodSecurityContext{ - SeccompProfile: &corev1.SeccompProfile{ - Type: corev1.SeccompProfileTypeRuntimeDefault, - }, - }, - ImagePullSecrets: statefulSetBuilder.dynakube.ImagePullSecretReferences(), - PriorityClassName: statefulSetBuilder.dynakube.Spec.ActiveGate.PriorityClassName, - DNSPolicy: statefulSetBuilder.dynakube.Spec.ActiveGate.DNSPolicy, + SecurityContext: statefulSetBuilder.buildPodSecurityContext(), + ImagePullSecrets: statefulSetBuilder.dynakube.ImagePullSecretReferences(), + PriorityClassName: statefulSetBuilder.dynakube.Spec.ActiveGate.PriorityClassName, + DNSPolicy: statefulSetBuilder.dynakube.Spec.ActiveGate.DNSPolicy, TopologySpreadConstraints: statefulSetBuilder.buildTopologySpreadConstraints(statefulSetBuilder.capability), + Volumes: statefulSetBuilder.buildVolumes(), } sts.Spec.Template.Spec = podSpec } @@ -141,6 +142,45 @@ func (statefulSetBuilder Builder) buildTopologySpreadConstraints(capability capa return statefulSetBuilder.defaultTopologyConstraints() } +func (statefulSetBuilder Builder) buildVolumes() []corev1.Volume { + volumes := []corev1.Volume{} + if !(statefulSetBuilder.dynakube.IsOTLPingestEnabled() || statefulSetBuilder.dynakube.TelemetryService().IsEnabled()) || statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume { + volumes = append(volumes, corev1.Volume{ + Name: consts.GatewayTmpVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }) + } + + return volumes +} + +func (statefulSetBuilder Builder) buildVolumeMounts() []corev1.VolumeMount { + var volumeMounts []corev1.VolumeMount + + volumeMounts = append(volumeMounts, corev1.VolumeMount{ + Name: consts.GatewayTmpVolumeName, + MountPath: consts.GatewayTmpMountPoint, + }) + + return volumeMounts +} + +func (statefulSetBuilder Builder) buildPodSecurityContext() *corev1.PodSecurityContext { + sc := corev1.PodSecurityContext{ + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + } + + if !statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume { + sc.FSGroup = ptr.To(consts.DockerImageGroup) + } + + return &sc +} + func (statefulSetBuilder Builder) defaultTopologyConstraints() []corev1.TopologySpreadConstraint { appLabels := statefulSetBuilder.buildAppLabels() @@ -181,6 +221,7 @@ func (statefulSetBuilder Builder) buildBaseContainer() []corev1.Container { TimeoutSeconds: 2, }, SecurityContext: modifiers.GetSecurityContext(false), + VolumeMounts: statefulSetBuilder.buildVolumeMounts(), } return []corev1.Container{container} @@ -230,3 +271,49 @@ func (statefulSetBuilder Builder) nodeAffinity() *corev1.Affinity { return &affinity } + +func (statefulSetBuilder Builder) addPersistentVolumeClaim(sts *appsv1.StatefulSet) { + if (statefulSetBuilder.dynakube.IsOTLPingestEnabled() || statefulSetBuilder.dynakube.TelemetryService().IsEnabled()) && !statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume { + if statefulSetBuilder.dynakube.Spec.ActiveGate.PersistentVolumeClaim == nil { + sts.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: consts.GatewayTmpVolumeName, + }, + Spec: defaultPVCSpec(), + }, + } + } else { + sts.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: consts.GatewayTmpVolumeName, + }, + Spec: *statefulSetBuilder.dynakube.Spec.ActiveGate.PersistentVolumeClaim, + }, + } + } + + sts.Spec.PersistentVolumeClaimRetentionPolicy = defaultPVCRetentionPolicy() + } +} + +func defaultPVCSpec() corev1.PersistentVolumeClaimSpec { + return corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{ + corev1.ReadWriteOnce, + }, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + } +} + +func defaultPVCRetentionPolicy() *appsv1.StatefulSetPersistentVolumeClaimRetentionPolicy { + return &appsv1.StatefulSetPersistentVolumeClaimRetentionPolicy{ + WhenDeleted: appsv1.DeletePersistentVolumeClaimRetentionPolicyType, + WhenScaled: appsv1.DeletePersistentVolumeClaimRetentionPolicyType, + } +} diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index fb3720e2f7..00d85a8e24 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" @@ -480,3 +481,125 @@ func TestSecurityContexts(t *testing.T) { require.Truef(t, reflect.DeepEqual(sts.Spec.Template.Spec.InitContainers[0].SecurityContext, sts.Spec.Template.Spec.Containers[0].SecurityContext), "InitContainer and Container have different SecurityContexts") }) } + +func TestVolumes(t *testing.T) { + t.Run("empty dir volume exists when PersistentVolumeClaim = nil and UseEphemeralVolume = true", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.EnableOTLPingest = true + dk.Spec.ActiveGate.PersistentVolumeClaim = nil + dk.Spec.ActiveGate.UseEphemeralVolume = true + multiCapability := capability.NewMultiCapability(&dk) + statefulsetBuilder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) + sts, _ := statefulsetBuilder.CreateStatefulSet([]builder.Modifier{ + modifiers.NewKubernetesMonitoringModifier(dk, multiCapability), + modifiers.NewReadOnlyModifier(dk), + }) + + require.NotEmpty(t, sts) + + expectedVolume := corev1.Volume{ + Name: consts.GatewayTmpVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + } + require.Contains(t, sts.Spec.Template.Spec.Volumes, expectedVolume) + }) + + t.Run("empty dir volume doesn't exists when UseEphemeralVolume = false", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.EnableOTLPingest = true + dk.Spec.ActiveGate.UseEphemeralVolume = false + multiCapability := capability.NewMultiCapability(&dk) + statefulsetBuilder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) + sts, _ := statefulsetBuilder.CreateStatefulSet([]builder.Modifier{ + modifiers.NewKubernetesMonitoringModifier(dk, multiCapability), + modifiers.NewReadOnlyModifier(dk), + }) + + require.NotEmpty(t, sts) + + expectedVolume := corev1.Volume{ + Name: consts.GatewayTmpVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + } + require.NotContains(t, sts.Spec.Template.Spec.Volumes, expectedVolume) + }) +} + +func TestVolumeMounts(t *testing.T) { + t.Run("volume mount is presented in Container volumeMount list", func(t *testing.T) { + dk := getTestDynakube() + multiCapability := capability.NewMultiCapability(&dk) + statefulsetBuilder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) + sts, _ := statefulsetBuilder.CreateStatefulSet([]builder.Modifier{ + modifiers.NewKubernetesMonitoringModifier(dk, multiCapability), + modifiers.NewReadOnlyModifier(dk), + }) + + require.NotEmpty(t, sts) + + expectedVolumeMount := corev1.VolumeMount{ + Name: consts.GatewayTmpVolumeName, + MountPath: consts.GatewayTmpMountPoint, + } + require.Contains(t, sts.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + }) +} + +func TestPVC(t *testing.T) { + test := func(dk dynakube.DynaKube, multiCapability capability.Capability, pvcSpec corev1.PersistentVolumeClaimSpec) { + statefulsetBuilder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) + sts, _ := statefulsetBuilder.CreateStatefulSet([]builder.Modifier{ + modifiers.NewKubernetesMonitoringModifier(dk, multiCapability), + modifiers.NewReadOnlyModifier(dk), + }) + + require.NotEmpty(t, sts) + + require.Equal(t, pvcSpec, sts.Spec.VolumeClaimTemplates[0].Spec) + require.Equal(t, consts.GatewayTmpVolumeName, sts.Spec.VolumeClaimTemplates[0].Name) + require.Equal(t, defaultPVCRetentionPolicy(), sts.Spec.PersistentVolumeClaimRetentionPolicy) + } + + t.Run("use custom PVC with OTLPingest", func(t *testing.T) { + dk := getTestDynakube() + multiCapability := capability.NewMultiCapability(&dk) + myPVCspec := corev1.PersistentVolumeClaimSpec{ + StorageClassName: ptr.To("test"), + VolumeName: "foo-pv", + } + dk.Spec.EnableOTLPingest = true + dk.Spec.ActiveGate.PersistentVolumeClaim = &myPVCspec + + test(dk, multiCapability, myPVCspec) + }) + t.Run("use custom PVC with TelemetryService", func(t *testing.T) { + dk := getTestDynakube() + multiCapability := capability.NewMultiCapability(&dk) + myPVCspec := corev1.PersistentVolumeClaimSpec{ + StorageClassName: ptr.To("test"), + VolumeName: "foo-pv", + } + dk.Spec.TelemetryService = &telemetryservice.Spec{} + dk.Spec.ActiveGate.PersistentVolumeClaim = &myPVCspec + + test(dk, multiCapability, myPVCspec) + }) + t.Run("use default PVC with OTLPingest", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.EnableOTLPingest = true + multiCapability := capability.NewMultiCapability(&dk) + + test(dk, multiCapability, defaultPVCSpec()) + }) + t.Run("use default PVC with TelemetryService", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.TelemetryService = &telemetryservice.Spec{} + multiCapability := capability.NewMultiCapability(&dk) + + test(dk, multiCapability, defaultPVCSpec()) + }) +} From e7537e8ec9af90f8ce7017536008260881161f48 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Wed, 22 Jan 2025 14:37:22 +0100 Subject: [PATCH 127/426] [cherry-pick] Make Log agent host path static (#4323) (#4328) --- .../logmonitoring/daemonset/container.go | 8 ++--- .../logmonitoring/daemonset/container_test.go | 18 +++++++---- .../logmonitoring/daemonset/reconciler.go | 6 ++-- .../logmonitoring/daemonset/volumes.go | 32 +++++++++++-------- .../logmonitoring/daemonset/volumes_test.go | 7 ++-- 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go index 6f0b0658e1..fad2bd5394 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go @@ -27,7 +27,7 @@ var ( } ) -func getContainer(dk dynakube.DynaKube) corev1.Container { +func getContainer(dk dynakube.DynaKube, tenantUUID string) corev1.Container { securityContext := getBaseSecurityContext(dk) securityContext.Capabilities.Add = neededCapabilities @@ -35,7 +35,7 @@ func getContainer(dk dynakube.DynaKube) corev1.Container { Name: containerName, Image: dk.LogMonitoring().Template().ImageRef.StringWithDefaults(defaultImageRepo, defaultImageTag), ImagePullPolicy: corev1.PullAlways, - VolumeMounts: getVolumeMounts(), + VolumeMounts: getVolumeMounts(tenantUUID), Env: getEnvs(), SecurityContext: &securityContext, } @@ -43,7 +43,7 @@ func getContainer(dk dynakube.DynaKube) corev1.Container { return container } -func getInitContainer(dk dynakube.DynaKube) corev1.Container { +func getInitContainer(dk dynakube.DynaKube, tenantUUID string) corev1.Container { securityContext := getBaseSecurityContext(dk) securityContext.Capabilities.Add = neededInitCapabilities @@ -51,7 +51,7 @@ func getInitContainer(dk dynakube.DynaKube) corev1.Container { Name: initContainerName, Image: dk.LogMonitoring().Template().ImageRef.StringWithDefaults(defaultImageRepo, defaultImageTag), ImagePullPolicy: corev1.PullAlways, - VolumeMounts: getDTVolumeMounts(), + VolumeMounts: getDTVolumeMounts(tenantUUID), Command: []string{bootstrapCommand}, Env: getInitEnvs(dk), Args: getInitArgs(dk), diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go index 2c7018b638..1a432fd966 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go @@ -11,9 +11,11 @@ import ( ) func TestGetContainer(t *testing.T) { + tenantUUID := "test-uuid" + t.Run("get main container", func(t *testing.T) { dk := dynakube.DynaKube{} - mainContainer := getContainer(dk) + mainContainer := getContainer(dk, tenantUUID) require.NotEmpty(t, mainContainer) @@ -37,7 +39,7 @@ func TestGetContainer(t *testing.T) { Tag: expectedTag, }, } - mainContainer := getContainer(dk) + mainContainer := getContainer(dk, tenantUUID) require.NotEmpty(t, mainContainer) assert.NotEmpty(t, mainContainer.Image) @@ -46,9 +48,11 @@ func TestGetContainer(t *testing.T) { } func TestGetInitContainer(t *testing.T) { + tenantUUID := "test-uuid" + t.Run("get main container", func(t *testing.T) { dk := dynakube.DynaKube{} - initContainer := getInitContainer(dk) + initContainer := getInitContainer(dk, tenantUUID) require.NotEmpty(t, initContainer) @@ -75,7 +79,7 @@ func TestGetInitContainer(t *testing.T) { Tag: expectedTag, }, } - initContainer := getContainer(dk) + initContainer := getContainer(dk, tenantUUID) require.NotEmpty(t, initContainer) assert.NotEmpty(t, initContainer.Image) @@ -84,6 +88,8 @@ func TestGetInitContainer(t *testing.T) { } func TestSecurityContext(t *testing.T) { + tenantUUID := "test-uuid" + t.Run("get base securityContext", func(t *testing.T) { dk := dynakube.DynaKube{} sc := getBaseSecurityContext(dk) @@ -118,8 +124,8 @@ func TestSecurityContext(t *testing.T) { t.Run("main and init container securityContext differ only in capabilities", func(t *testing.T) { dk := dynakube.DynaKube{} - initContainer := getInitContainer(dk) - mainContainer := getContainer(dk) + initContainer := getInitContainer(dk, tenantUUID) + mainContainer := getContainer(dk, tenantUUID) require.NotNil(t, initContainer) require.NotNil(t, mainContainer) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go index f6f556cba1..182aa0e523 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go @@ -89,8 +89,8 @@ func (r *Reconciler) generateDaemonSet() (*appsv1.DaemonSet, error) { maxUnavailable := intstr.FromInt(r.dk.FeatureOneAgentMaxUnavailable()) - ds, err := daemonset.Build(r.dk, r.dk.LogMonitoring().GetDaemonSetName(), getContainer(*r.dk), - daemonset.SetInitContainer(getInitContainer(*r.dk)), + ds, err := daemonset.Build(r.dk, r.dk.LogMonitoring().GetDaemonSetName(), getContainer(*r.dk, tenantUUID), + daemonset.SetInitContainer(getInitContainer(*r.dk, tenantUUID)), daemonset.SetAllLabels(labels.BuildLabels(), labels.BuildMatchLabels(), labels.BuildLabels(), r.dk.LogMonitoring().Template().Labels), daemonset.SetAllAnnotations(nil, r.dk.LogMonitoring().Template().Annotations), daemonset.SetServiceAccount(serviceAccountName), @@ -104,7 +104,7 @@ func (r *Reconciler) generateDaemonSet() (*appsv1.DaemonSet, error) { MaxUnavailable: &maxUnavailable, }, }), - daemonset.SetVolumes(getVolumes(r.dk.Name, tenantUUID)), + daemonset.SetVolumes(getVolumes(r.dk.Name)), ) if err != nil { return nil, err diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go index 755bd19340..d4f84b4b80 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go @@ -5,6 +5,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/configsecret" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) const ( @@ -13,11 +14,12 @@ const ( configVolumeMountPath = "/var/lib/dynatrace/oneagent/agent/config/deployment.conf" // for the logmonitoring to read/write - dtLibVolumeName = "dynatrace-lib" - dtLibVolumeMountPath = "/var/lib/dynatrace" - dtLibVolumePathTemplate = "/tmp/dynatrace-logmonitoring-%s" - dtLogVolumeName = "dynatrace-logs" - dtLogVolumeMountPath = "/var/log/dynatrace" + dtLibVolumeName = "dynatrace-lib" + dtLibVolumeMountPath = "/var/lib/dynatrace" + dtSubPathTemplate = "logmonitoring-%s" + dtLibVolumePath = "/tmp/dynatrace" + dtLogVolumeName = "dynatrace-logs" + dtLogVolumeMountPath = "/var/log/dynatrace" // for the logs that the logmonitoring will ingest podLogsVolumeName = "var-log-pods" @@ -50,10 +52,11 @@ func getConfigVolume(dkName string) corev1.Volume { } // getDTVolumeMounts provides the VolumeMounts for the dynatrace specific folders -func getDTVolumeMounts() []corev1.VolumeMount { +func getDTVolumeMounts(tenantUUID string) []corev1.VolumeMount { return []corev1.VolumeMount{ { Name: dtLibVolumeName, + SubPath: fmt.Sprintf(dtSubPathTemplate, tenantUUID), MountPath: dtLibVolumeMountPath, }, { @@ -64,13 +67,14 @@ func getDTVolumeMounts() []corev1.VolumeMount { } // getDTVolumes provides the Volumes for the dynatrace specific folders -func getDTVolumes(tenantUUID string) []corev1.Volume { +func getDTVolumes() []corev1.Volume { return []corev1.Volume{ { Name: dtLibVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: fmt.Sprintf(dtLibVolumePathTemplate, tenantUUID), + Path: dtLibVolumePath, + Type: ptr.To(corev1.HostPathDirectoryOrCreate), }, }, }, @@ -132,19 +136,19 @@ func getIngestVolumes() []corev1.Volume { } } -func getVolumeMounts() []corev1.VolumeMount { - mounts := []corev1.VolumeMount{} +func getVolumeMounts(tenantUUID string) []corev1.VolumeMount { + var mounts []corev1.VolumeMount mounts = append(mounts, getConfigVolumeMount()) - mounts = append(mounts, getDTVolumeMounts()...) + mounts = append(mounts, getDTVolumeMounts(tenantUUID)...) mounts = append(mounts, getIngestVolumeMounts()...) return mounts } -func getVolumes(dkName, tenantUUID string) []corev1.Volume { - volumes := []corev1.Volume{} +func getVolumes(dkName string) []corev1.Volume { + var volumes []corev1.Volume volumes = append(volumes, getConfigVolume(dkName)) - volumes = append(volumes, getDTVolumes(tenantUUID)...) + volumes = append(volumes, getDTVolumes()...) volumes = append(volumes, getIngestVolumes()...) return volumes diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go index 3df9cff563..9c8dcdfbcf 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go @@ -10,12 +10,12 @@ import ( const ( expectedMountLen = 6 expectedInitMountLen = 2 - expectedVolumeLen = 6 ) func TestGetVolumeMounts(t *testing.T) { + tenantUUID := "test-uuid" t.Run("get volume mounts", func(t *testing.T) { - mounts := getVolumeMounts() + mounts := getVolumeMounts(tenantUUID) require.NotEmpty(t, mounts) assert.Len(t, mounts, expectedMountLen) @@ -29,10 +29,9 @@ func TestGetVolumeMounts(t *testing.T) { func TestGetVolumes(t *testing.T) { dkName := "test-dk" - tenantUUID := "test-uuid" t.Run("get volumes", func(t *testing.T) { - volumes := getVolumes(dkName, tenantUUID) + volumes := getVolumes(dkName) require.NotEmpty(t, volumes) assert.Len(t, volumes, expectedMountLen) From fa0d56a8bccc307467c64ced074fe59816ef7cb8 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Wed, 22 Jan 2025 14:41:45 +0100 Subject: [PATCH 128/426] [cherry-pick] Log agent args must not contain dynamic strings (#4324) (#4329) --- pkg/controllers/dynakube/logmonitoring/daemonset/args.go | 4 ++-- pkg/controllers/dynakube/logmonitoring/daemonset/env.go | 5 +++++ pkg/controllers/dynakube/logmonitoring/daemonset/env_test.go | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/args.go b/pkg/controllers/dynakube/logmonitoring/daemonset/args.go index 3681205c97..68d28fd9bd 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/args.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/args.go @@ -14,8 +14,8 @@ func getInitArgs(dk dynakube.DynaKube) []string { fmt.Sprintf("-p dt.entity.kubernetes_cluster=$(%s)", entityEnv), fmt.Sprintf("-c k8s_fullpodname $(%s)", podNameEnv), fmt.Sprintf("-c k8s_poduid $(%s)", podUIDEnv), - fmt.Sprintf("-c k8s_containername %s", containerName), //nolint:perfsprint - fmt.Sprintf("-c k8s_basepodname %s", dk.LogMonitoring().GetDaemonSetName()), //nolint:perfsprint + fmt.Sprintf("-c k8s_containername %s", containerName), //nolint:perfsprint + fmt.Sprintf("-c k8s_basepodname $(%s)", basePodNameEnv), fmt.Sprintf("-c k8s_namespace $(%s)", namespaceNameEnv), fmt.Sprintf("-c k8s_node_name $(%s)", nodeNameEnv), fmt.Sprintf("-c k8s_cluster_id $(%s)", clusterUIDEnv), diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/env.go b/pkg/controllers/dynakube/logmonitoring/daemonset/env.go index b716b887c7..655ce1a2b1 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/env.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/env.go @@ -14,6 +14,7 @@ const ( namespaceNameEnv = "K8S_NAMESPACE_NAME" clusterUIDEnv = "K8S_CLUSTER_UID" clusterNameEnv = "K8S_CLUSTER_NAME" + basePodNameEnv = "K8S_BASEPODNAME" entityEnv = "DT_ENTITY_KUBERNETES_CLUSTER" // main container envs @@ -72,6 +73,10 @@ func getInitEnvs(dk dynakube.DynaKube) []corev1.EnvVar { Name: entityEnv, Value: dk.Status.KubernetesClusterMEID, }, + { + Name: basePodNameEnv, + Value: dk.LogMonitoring().GetDaemonSetName(), + }, } } diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/env_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/env_test.go index 90ee153df3..df88721976 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/env_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/env_test.go @@ -10,7 +10,7 @@ import ( ) const ( - expectedBaseInitEnvLen = 7 + expectedBaseInitEnvLen = 8 expectedBaseEnvLen = 4 ) From b0dc15ab9b63c4a58e1b82e19cd14e5582684824 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Wed, 22 Jan 2025 15:11:15 +0100 Subject: [PATCH 129/426] Update logMonitoring DynaKube sample (#4330) --- assets/samples/dynakube/v1beta3/logMonitoring.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/samples/dynakube/v1beta3/logMonitoring.yaml b/assets/samples/dynakube/v1beta3/logMonitoring.yaml index 671c744492..bb505e36b5 100644 --- a/assets/samples/dynakube/v1beta3/logMonitoring.yaml +++ b/assets/samples/dynakube/v1beta3/logMonitoring.yaml @@ -14,6 +14,10 @@ spec: logMonitoring: {} + activeGate: + capabilities: + - kubernetes-monitoring + templates: {} # Required in combination with logMonitoring enabled. # As there is no image available in public registry yet, this field is required if you want to run logMonitoring. From 0a30b9daa57c7f54fddad0e990c722dfbc3116a7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 20:25:16 +0000 Subject: [PATCH 130/426] chore(deps): update codecov/codecov-action action to v5.2.0 (main) (#4336) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1e4701f251..563c3885df 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -67,7 +67,7 @@ jobs: run: | make go/check-coverage - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 # v5.1.2 + uses: codecov/codecov-action@5a605bd92782ce0810fa3b8acc235c921b497052 # v5.2.0 with: fail_ci_if_error: true verbose: true From af10fe4eb09b9e1bf39a1a1cf702daa6aabf5b15 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 00:56:08 +0000 Subject: [PATCH 131/426] chore(deps): update github/codeql-action action to v3.28.3 (main) (#4337) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 8acfb7fee1..b4ea1e1b27 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 + uses: github/codeql-action/init@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 + uses: github/codeql-action/autobuild@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 + uses: github/codeql-action/analyze@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index a86c88b803..6e866f41ae 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 + uses: github/codeql-action/upload-sarif@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 with: sarif_file: results.sarif From 6983e6bf588fc7e2f0d8655e0e7402de927d7327 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 05:14:40 +0000 Subject: [PATCH 132/426] fix(deps): update module github.com/docker/cli to v27.5.1+incompatible (main) (#4338) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 37a531b599..98ba0215b0 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.3 require ( github.com/container-storage-interface/spec v1.11.0 - github.com/docker/cli v27.5.0+incompatible + github.com/docker/cli v27.5.1+incompatible github.com/evanphx/json-patch v5.9.0+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.3 diff --git a/go.sum b/go.sum index 4a30d7d365..887f486790 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM= -github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.5.1+incompatible h1:JB9cieUT9YNiMITtIsguaN55PLOHhBSz3LKVc6cqWaY= +github.com/docker/cli v27.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= From 60b7a5cef3319ef814aef4f2811fda11f63f8785 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Thu, 23 Jan 2025 09:05:56 +0100 Subject: [PATCH 133/426] Ensure that automatic-kubernetes-api-monitoring is not disabled if KSPM is enabled (#4335) --- pkg/api/validation/dynakube/kspm.go | 3 +- pkg/api/validation/dynakube/kspm_test.go | 51 ++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/pkg/api/validation/dynakube/kspm.go b/pkg/api/validation/dynakube/kspm.go index a3610ec416..1dc653a765 100644 --- a/pkg/api/validation/dynakube/kspm.go +++ b/pkg/api/validation/dynakube/kspm.go @@ -21,8 +21,7 @@ func tooManyAGReplicas(_ context.Context, _ *Validator, dk *dynakube.DynaKube) s } func missingKSPMDependency(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - if dk.KSPM().IsEnabled() && - !dk.ActiveGate().IsKubernetesMonitoringEnabled() { + if dk.KSPM().IsEnabled() && (!dk.ActiveGate().IsKubernetesMonitoringEnabled() || !dk.FeatureAutomaticKubernetesApiMonitoring()) { return errorKSPMMissingKubemon } diff --git a/pkg/api/validation/dynakube/kspm_test.go b/pkg/api/validation/dynakube/kspm_test.go index 39d8943bf2..df4ee9c2fe 100644 --- a/pkg/api/validation/dynakube/kspm_test.go +++ b/pkg/api/validation/dynakube/kspm_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestTooManyAGReplicas(t *testing.T) { @@ -101,6 +102,56 @@ func TestMissingKSPMDependency(t *testing.T) { }, }) }) + + t.Run("both kspm and kubemon enabled, automatic k8s monitoring disabled", func(t *testing.T) { + assertDenied(t, + []string{errorKSPMMissingKubemon}, + &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Annotations: map[string]string{ + dynakube.AnnotationFeatureAutomaticK8sApiMonitoring: "false", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + Kspm: &kspm.Spec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, + Templates: dynakube.TemplatesSpec{ + KspmNodeConfigurationCollector: kspm.NodeConfigurationCollectorSpec{ + ImageRef: image.Ref{ + Repository: "repo/image", + Tag: "version", + }, + }, + }, + }, + }) + }) + + t.Run("missing kubemon, automatic k8s monitoring disabled, but kspm enabled", func(t *testing.T) { + assertDenied(t, + []string{errorKSPMMissingKubemon}, + &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Annotations: map[string]string{ + dynakube.AnnotationFeatureAutomaticK8sApiMonitoring: "false", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + Kspm: &kspm.Spec{}, + ActiveGate: activegate.Spec{}, + }, + }) + }) } func TestMissingKSPMImage(t *testing.T) { From 111fac0c25547dbce41575255c17827a0f999185 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Thu, 23 Jan 2025 09:17:03 +0100 Subject: [PATCH 134/426] Require Kubernetes API monitoring config for extensions (#4334) --- pkg/api/validation/dynakube/eec_test.go | 40 ++++++++++- pkg/api/validation/dynakube/extensions.go | 19 +++++ .../validation/dynakube/extensions_test.go | 71 +++++++++++++++++++ pkg/api/validation/dynakube/validation.go | 1 + 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 pkg/api/validation/dynakube/extensions.go create mode 100644 pkg/api/validation/dynakube/extensions_test.go diff --git a/pkg/api/validation/dynakube/eec_test.go b/pkg/api/validation/dynakube/eec_test.go index 638aa99d42..22c3dc375a 100644 --- a/pkg/api/validation/dynakube/eec_test.go +++ b/pkg/api/validation/dynakube/eec_test.go @@ -20,7 +20,12 @@ func TestExtensionExecutionControllerImage(t *testing.T) { &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ - APIURL: testApiUrl, + APIURL: testApiUrl, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, Extensions: &dynakube.ExtensionsSpec{}, Templates: dynakube.TemplatesSpec{ ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ @@ -42,6 +47,11 @@ func TestExtensionExecutionControllerImage(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, Extensions: &dynakube.ExtensionsSpec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, Templates: dynakube.TemplatesSpec{ ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ ImageRef: image.Ref{ @@ -61,6 +71,11 @@ func TestExtensionExecutionControllerImage(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, Extensions: &dynakube.ExtensionsSpec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, Templates: dynakube.TemplatesSpec{ ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ ImageRef: image.Ref{ @@ -80,6 +95,11 @@ func TestExtensionExecutionControllerImage(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, Extensions: &dynakube.ExtensionsSpec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, }, }) }) @@ -93,6 +113,11 @@ func TestExtensionExecutionControllerPVCSettings(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, Extensions: &dynakube.ExtensionsSpec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, Templates: dynakube.TemplatesSpec{ ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ ImageRef: image.Ref{ @@ -113,6 +138,11 @@ func TestExtensionExecutionControllerPVCSettings(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, Extensions: &dynakube.ExtensionsSpec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, Templates: dynakube.TemplatesSpec{ ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ ImageRef: image.Ref{ @@ -133,6 +163,11 @@ func TestExtensionExecutionControllerPVCSettings(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, Extensions: &dynakube.ExtensionsSpec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, Templates: dynakube.TemplatesSpec{ ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ ImageRef: image.Ref{ @@ -155,6 +190,9 @@ func TestWarnIfmultiplyDKwithExtensionsEnabled(t *testing.T) { } // we want to exclude AG resources warning. agSpec := activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, CapabilityProperties: activegate.CapabilityProperties{ Resources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ diff --git a/pkg/api/validation/dynakube/extensions.go b/pkg/api/validation/dynakube/extensions.go new file mode 100644 index 0000000000..730b6de61e --- /dev/null +++ b/pkg/api/validation/dynakube/extensions.go @@ -0,0 +1,19 @@ +package validation + +import ( + "context" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" +) + +const ( + errorExtensionsWithoutK8SMonitoring = "The Dynakube's specification enables extensions without an ActiveGate which has Kubernetes monitoring enabled. This is not feasible, as the cluster will not be visible in Dynatrace without the Kubernetes monitoring feature." +) + +func extensionsWithoutK8SMonitoring(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { + if dk.IsExtensionsEnabled() && (!dk.ActiveGate().IsKubernetesMonitoringEnabled() || !dk.FeatureAutomaticKubernetesApiMonitoring()) { + return errorExtensionsWithoutK8SMonitoring + } + + return "" +} diff --git a/pkg/api/validation/dynakube/extensions_test.go b/pkg/api/validation/dynakube/extensions_test.go new file mode 100644 index 0000000000..a07a411309 --- /dev/null +++ b/pkg/api/validation/dynakube/extensions_test.go @@ -0,0 +1,71 @@ +package validation + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const testDynakubeName = "dynakube" + +func TestExtensionsWithoutK8SMonitoring(t *testing.T) { + t.Run("no error if extensions are enabled with activegate with k8s-monitoring", func(t *testing.T) { + dk := createStandaloneExtensionsDynakube(testDynakubeName, testApiUrl) + dk.Spec.ActiveGate = activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + } + assertAllowed(t, dk) + }) + t.Run("error if extensions are enabled without activegate with k8s-monitoring", func(t *testing.T) { + assertDenied(t, + []string{errorExtensionsWithoutK8SMonitoring}, + createStandaloneExtensionsDynakube(testDynakubeName, testApiUrl)) + }) + t.Run("error if extensions are enabled with activegate with k8s-monitoring but automatic Kuberenetes API monitoring is disabled", func(t *testing.T) { + dk := createStandaloneExtensionsDynakube(testDynakubeName, testApiUrl) + dk.ObjectMeta.Annotations = map[string]string{ + dynakube.AnnotationFeatureAutomaticK8sApiMonitoring: "false", + } + dk.Spec.ActiveGate = activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + } + assertDenied(t, []string{errorExtensionsWithoutK8SMonitoring}, dk) + }) + t.Run("error if extensions are enabled but automatic Kuberenetes API monitoring is disabled and without activgate k8s-monitoring", func(t *testing.T) { + dk := createStandaloneExtensionsDynakube(testDynakubeName, testApiUrl) + dk.ObjectMeta.Annotations = map[string]string{ + dynakube.AnnotationFeatureAutomaticK8sApiMonitoring: "false", + } + assertDenied(t, []string{errorExtensionsWithoutK8SMonitoring}, dk) + }) +} + +func createStandaloneExtensionsDynakube(name, apiUrl string) *dynakube.DynaKube { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: apiUrl, + Extensions: &dynakube.ExtensionsSpec{}, + Templates: dynakube.TemplatesSpec{ + ExtensionExecutionController: dynakube.ExtensionExecutionControllerSpec{ + ImageRef: image.Ref{ + Repository: "repo/image", + Tag: "version", + }, + }, + }, + }, + } + + return dk +} diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 51c44c0222..5029808401 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -57,6 +57,7 @@ var ( emptyTelemetryServiceProtocolsList, unknownTelemetryServiceProtocols, duplicatedTelemetryServiceProtocols, + extensionsWithoutK8SMonitoring, } validatorWarningFuncs = []validatorFunc{ missingActiveGateMemoryLimit, From b9150f505cb9931bb89ce46a4de882aefc400a29 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:37:52 +0100 Subject: [PATCH 135/426] Fix Log monitoring handling without Kubernetes settings available (#4309) --- pkg/api/validation/dynakube/logmonitoring.go | 13 ++- .../validation/dynakube/logmonitoring_test.go | 95 ++++++++++++++++++- pkg/api/validation/dynakube/oneagent_test.go | 2 +- pkg/api/validation/dynakube/validation.go | 1 + pkg/controllers/dynakube/controller.go | 5 +- .../logmonitoring/daemonset/reconciler.go | 6 +- .../logmonsettings/reconciler.go | 5 +- 7 files changed, 117 insertions(+), 10 deletions(-) diff --git a/pkg/api/validation/dynakube/logmonitoring.go b/pkg/api/validation/dynakube/logmonitoring.go index d0615cda37..e7fb0d0e28 100644 --- a/pkg/api/validation/dynakube/logmonitoring.go +++ b/pkg/api/validation/dynakube/logmonitoring.go @@ -7,10 +7,19 @@ import ( ) const ( - warningLogMonitoringIgnoredTemplate = "The Dynakube's `spec.templates.logMonitoring` section is skipped as the `spec.oneagent` section is also configured." - errorLogMonitoringMissingImage = `The Dynakube's specification specifies standalone Log monitoring, but no image repository/tag is configured.` + warningLogMonitoringIgnoredTemplate = "The Dynakube's `spec.templates.logMonitoring` section is skipped as the `spec.oneagent` section is also configured." + errorLogMonitoringMissingImage = `The Dynakube's specification specifies standalone Log monitoring, but no image repository/tag is configured.` + errorLogMonitoringWithoutK8SMonitoring = "The Dynakube's specification specifies Log monitoring without an ActiveGate with kubernetes-monitoring enabled or the automatic-kubernetes-monitoring feature flag. This is not allowed as Kubernetes settings are needed for Log monitoring." ) +func logMonitoringWithoutK8SMonitoring(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { + if dk.LogMonitoring().IsEnabled() && (!dk.ActiveGate().IsKubernetesMonitoringEnabled() || !dk.FeatureAutomaticKubernetesApiMonitoring()) { + return errorLogMonitoringWithoutK8SMonitoring + } + + return "" +} + func ignoredLogMonitoringTemplate(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { if dk.LogMonitoring().IsStandalone() { return "" diff --git a/pkg/api/validation/dynakube/logmonitoring_test.go b/pkg/api/validation/dynakube/logmonitoring_test.go index 7bf9a11050..b6ac286888 100644 --- a/pkg/api/validation/dynakube/logmonitoring_test.go +++ b/pkg/api/validation/dynakube/logmonitoring_test.go @@ -5,22 +5,103 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func TestLogMonitoringWithoutK8SMonitoring(t *testing.T) { + t.Run("no error if logMonitoring is enabled with activegate with k8s-monitoring", func(t *testing.T) { + dk := &dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, + }, + APIURL: testApiUrl, + LogMonitoring: &logmonitoring.Spec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, + }, + } + assertAllowed(t, dk) + }) + t.Run("error if logMonitoring is enabled with automatic k8s monitoring feature flag but no activegate with k8s-monitoring", func(t *testing.T) { + dk := &dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, + }, + APIURL: testApiUrl, + LogMonitoring: &logmonitoring.Spec{}, + }, + } + assertDenied(t, []string{errorLogMonitoringWithoutK8SMonitoring}, dk) + }) + t.Run("error if logMonitoring is enabled with activegate with k8s-monitoring but automatic-kubernetes-monitoring disables", func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + dynakube.AnnotationFeatureAutomaticK8sApiMonitoring: "false", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + LogMonitoring: &logmonitoring.Spec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, + Templates: dynakube.TemplatesSpec{ + LogMonitoring: &logmonitoring.TemplateSpec{ + ImageRef: image.Ref{ + Repository: "repo/image", + Tag: "version", + }, + }, + }, + }, + } + assertDenied(t, []string{errorLogMonitoringWithoutK8SMonitoring}, dk) + }) + t.Run("error if logMonitoring is enabled without activegate with k8s-monitoring and automatic-kubernetes-monitoring disabled", func(t *testing.T) { + assertDenied(t, []string{errorLogMonitoringWithoutK8SMonitoring}, &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + dynakube.AnnotationFeatureAutomaticK8sApiMonitoring: "false", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + LogMonitoring: &logmonitoring.Spec{}, + Templates: dynakube.TemplatesSpec{ + LogMonitoring: &logmonitoring.TemplateSpec{ + ImageRef: image.Ref{ + Repository: "repo/image", + Tag: "version", + }, + }, + }, + }, + }) + }) +} + func TestIgnoredLogMonitoringTemplate(t *testing.T) { t.Run("no warning if logMonitoring template section is empty", func(t *testing.T) { dk := createStandaloneLogMonitoringDynakube(testName, testApiUrl, "") dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} dk.Spec.Templates.LogMonitoring = nil - assertAllowedWithoutWarnings(t, dk) + assertAllowedWithWarnings(t, 1, dk) }) t.Run("warning if logMonitoring template section is not empty", func(t *testing.T) { dk := createStandaloneLogMonitoringDynakube(testName, testApiUrl, "something") dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} - assertAllowedWithWarnings(t, 1, dk) + assertAllowedWithWarnings(t, 2, dk) }) } @@ -33,6 +114,11 @@ func createStandaloneLogMonitoringDynakube(name, apiUrl, nodeSelector string) *d Spec: dynakube.DynaKubeSpec{ APIURL: apiUrl, LogMonitoring: &logmonitoring.Spec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, Templates: dynakube.TemplatesSpec{ LogMonitoring: &logmonitoring.TemplateSpec{ ImageRef: image.Ref{ @@ -63,6 +149,11 @@ func TestMissingLogMonitoringImage(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, LogMonitoring: &logmonitoring.Spec{}, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, Templates: dynakube.TemplatesSpec{ LogMonitoring: &logmonitoring.TemplateSpec{ ImageRef: image.Ref{ diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index 29d4e56254..0eb60c6084 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -181,7 +181,7 @@ func TestConflictingNodeSelector(t *testing.T) { t.Run("valid dynakube specs - 2 log-monitoring DK, different tenant, same nodes", func(t *testing.T) { api1 := "https://f1.q.d.n/api" api2 := "https://f2.q.d.n/api" - assertAllowedWithoutWarnings(t, createStandaloneLogMonitoringDynakube("dk1", api1, "1"), + assertAllowedWithWarnings(t, 1, createStandaloneLogMonitoringDynakube("dk1", api1, "1"), createStandaloneLogMonitoringDynakube("dk-lm", api2, "1")) }) diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 5029808401..e359d0ffea 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -54,6 +54,7 @@ var ( missingKSPMDependency, missingKSPMImage, missingLogMonitoringImage, + logMonitoringWithoutK8SMonitoring, emptyTelemetryServiceProtocolsList, unknownTelemetryServiceProtocols, duplicatedTelemetryServiceProtocols, diff --git a/pkg/controllers/dynakube/controller.go b/pkg/controllers/dynakube/controller.go index 3c38cafd20..ff9e4df9ad 100644 --- a/pkg/controllers/dynakube/controller.go +++ b/pkg/controllers/dynakube/controller.go @@ -20,6 +20,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/istio" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring" + logmondaemonset "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/daemonset" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" @@ -352,9 +353,7 @@ func (controller *Controller) reconcileComponents(ctx context.Context, dynatrace err = logMonitoringReconciler.Reconcile(ctx) if err != nil { - if errors.Is(err, oaconnectioninfo.NoOneAgentCommunicationHostsError) { - // missing communication hosts is not an error per se, just make sure next the reconciliation is happening ASAP - // this situation will clear itself after AG has been started + if errors.Is(err, oaconnectioninfo.NoOneAgentCommunicationHostsError) || errors.Is(err, logmondaemonset.KubernetesSettingsNotAvailableError) { controller.setRequeueAfterIfNewIsShorter(fastUpdateInterval) return goerrors.Join(componentErrors...) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go index 182aa0e523..ca04f33ff1 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go @@ -37,6 +37,8 @@ func NewReconciler(clt client.Client, } } +var KubernetesSettingsNotAvailableError = errors.New("the status of the DynaKube is missing information about the kubernetes monitored-entity, skipping LogMonitoring deployment until it is ready") + func (r *Reconciler) Reconcile(ctx context.Context) error { if !r.dk.LogMonitoring().IsStandalone() { if meta.FindStatusCondition(*r.dk.Conditions(), conditionType) == nil { @@ -56,7 +58,9 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { } if !r.isMEConfigured() { - return errors.New("the status of the DynaKube is missing information about the kubernetes monitored-entity, skipping LogMonitoring deployment") + log.Info("Kubernetes settings are not yet available, which are needed for LogMonitoring, will requeue") + + return KubernetesSettingsNotAvailableError } ds, err := r.generateDaemonSet() diff --git a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go index 06ecab05af..3cefb1f94e 100644 --- a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/daemonset" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "github.com/pkg/errors" @@ -42,7 +43,9 @@ func (r *reconciler) Reconcile(ctx context.Context) error { return nil } else if r.dk.Status.KubernetesClusterMEID == "" { - return errors.New("the status of the DynaKube is missing information about the kubernetes monitored-entity, skipping LogMonitoring deployment") + log.Info("Kubernetes settings are not yet available, which are needed for LogMonitoring, will requeue") + + return daemonset.KubernetesSettingsNotAvailableError } err := r.checkLogMonitoringSettings(ctx) From 99214d3159e65ef6554fbab14e1c80e37badb77c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 17:45:22 +0000 Subject: [PATCH 136/426] chore(deps): update github/codeql-action action to v3.28.4 (main) (#4342) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index b4ea1e1b27..77ed9bf640 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 + uses: github/codeql-action/init@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 + uses: github/codeql-action/autobuild@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 + uses: github/codeql-action/analyze@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 6e866f41ae..856d32c1e1 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 + uses: github/codeql-action/upload-sarif@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4 with: sarif_file: results.sarif From 48ddaaeaf10159f21fd99b57aebe59bf0e857ad7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 21:30:12 +0000 Subject: [PATCH 137/426] fix(deps): update module sigs.k8s.io/controller-runtime to v0.20.1 (main) (#4343) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 98ba0215b0..fcc091bdf6 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( k8s.io/client-go v0.32.1 k8s.io/mount-utils v0.32.1 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - sigs.k8s.io/controller-runtime v0.20.0 + sigs.k8s.io/controller-runtime v0.20.1 sigs.k8s.io/e2e-framework v0.3.0 sigs.k8s.io/yaml v1.4.0 ) diff --git a/go.sum b/go.sum index 887f486790..28df8bb4d3 100644 --- a/go.sum +++ b/go.sum @@ -264,8 +264,8 @@ k8s.io/mount-utils v0.32.1 h1:RJOD6xXzEJT/OOJoG1KstfVa8ZXJJPlHb+t2MoulPHM= k8s.io/mount-utils v0.32.1/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.20.0 h1:jjkMo29xEXH+02Md9qaVXfEIaMESSpy3TBWPrsfQkQs= -sigs.k8s.io/controller-runtime v0.20.0/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= +sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE= +sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= From 97534af5fe955cf57edec81ce2f55766e4eacc8e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 23:21:59 +0000 Subject: [PATCH 138/426] chore(deps): update codecov/codecov-action action to v5.3.0 (main) (#4344) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 563c3885df..559b6f5988 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -67,7 +67,7 @@ jobs: run: | make go/check-coverage - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@5a605bd92782ce0810fa3b8acc235c921b497052 # v5.2.0 + uses: codecov/codecov-action@0da7aa657d958d32c117fc47e1f977e7524753c7 # v5.3.0 with: fail_ci_if_error: true verbose: true From c22f671741afc8330e89eeeb64e91f7e1cb0b332 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 23:31:59 +0000 Subject: [PATCH 139/426] fix(deps): update module google.golang.org/grpc to v1.70.0 (main) (#4345) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index fcc091bdf6..4c9afe09d6 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( golang.org/x/net v0.34.0 golang.org/x/oauth2 v0.25.0 golang.org/x/sys v0.29.0 - google.golang.org/grpc v1.69.4 + google.golang.org/grpc v1.70.0 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.2 istio.io/client-go v1.24.2 diff --git a/go.sum b/go.sum index 28df8bb4d3..1c0418e6f7 100644 --- a/go.sum +++ b/go.sum @@ -166,8 +166,8 @@ go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5W go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -228,8 +228,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1: google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From bfab71ea33cdd3fbd8926974e2c33c1f8d275013 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Fri, 24 Jan 2025 12:57:31 +0100 Subject: [PATCH 140/426] Add flag and permissions to enable pod provisioning (#4341) --- .../default/templates/Common/csi/role-csi.yaml | 6 ++++-- .../default/tests/Common/csi/role-csi_test.yaml | 6 ++++-- doc/api/feature-flags.md | 12 +++++++----- pkg/api/v1beta3/dynakube/feature_flags.go | 14 ++++++++++---- .../logmonitoring/daemonset/volumes_test.go | 1 + 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/config/helm/chart/default/templates/Common/csi/role-csi.yaml b/config/helm/chart/default/templates/Common/csi/role-csi.yaml index 654ab04e13..9002ff6885 100644 --- a/config/helm/chart/default/templates/Common/csi/role-csi.yaml +++ b/config/helm/chart/default/templates/Common/csi/role-csi.yaml @@ -32,6 +32,7 @@ rules: - "" resources: - secrets + - configmaps verbs: - get - list @@ -39,11 +40,12 @@ rules: - apiGroups: - "" resources: - - configmaps + - jobs verbs: - get - list - - watch + - create + - delete - apiGroups: - "" resources: diff --git a/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml b/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml index a245d4905d..2e81785642 100644 --- a/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml @@ -47,6 +47,7 @@ tests: - "" resources: - secrets + - configmaps verbs: - get - list @@ -54,11 +55,12 @@ tests: - apiGroups: - "" resources: - - configmaps + - jobs verbs: - get - list - - watch + - create + - delete - apiGroups: - "" resources: diff --git a/doc/api/feature-flags.md b/doc/api/feature-flags.md index ebdd9d87cb..2e1b81ad51 100644 --- a/doc/api/feature-flags.md +++ b/doc/api/feature-flags.md @@ -17,7 +17,8 @@ import "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/tmp" ```go const ( - AnnotationFeaturePrefix = "feature.dynatrace.com/" + AnnotationFeaturePrefix = "feature.dynatrace.com/" + AnnotationFeatureCodeModulesPrefix = "codemodules.oneagent.dynatrace.com/" // General. AnnotationFeaturePublicRegistry = AnnotationFeaturePrefix + "public-registry" @@ -53,9 +54,10 @@ const ( AnnotationFeatureEnforcementMode = AnnotationFeaturePrefix + "enforcement-mode" // CSI. - AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" - AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" - AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" + AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" + AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" + AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" + AnnotationFeatureCodeModulesRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remoteImageDownload" ) ``` @@ -72,7 +74,7 @@ const ( -## func [MountAttemptsToTimeout]() +## func [MountAttemptsToTimeout]() ```go func MountAttemptsToTimeout(maxAttempts int) string diff --git a/pkg/api/v1beta3/dynakube/feature_flags.go b/pkg/api/v1beta3/dynakube/feature_flags.go index d02560d492..c3eb2e0b51 100644 --- a/pkg/api/v1beta3/dynakube/feature_flags.go +++ b/pkg/api/v1beta3/dynakube/feature_flags.go @@ -27,7 +27,8 @@ import ( ) const ( - AnnotationFeaturePrefix = "feature.dynatrace.com/" + AnnotationFeaturePrefix = "feature.dynatrace.com/" + AnnotationFeatureCodeModulesPrefix = "codemodules.oneagent.dynatrace.com/" // General. AnnotationFeaturePublicRegistry = AnnotationFeaturePrefix + "public-registry" @@ -69,9 +70,10 @@ const ( AnnotationFeatureEnforcementMode = AnnotationFeaturePrefix + "enforcement-mode" // CSI. - AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" - AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" - AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" + AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" + AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" + AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" + AnnotationFeatureCodeModulesRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remoteImageDownload" falsePhrase = "false" truePhrase = "true" @@ -268,6 +270,10 @@ func (dk *DynaKube) FeatureReadOnlyCsiVolume() bool { return dk.getFeatureFlagRaw(AnnotationFeatureReadOnlyCsiVolume) == truePhrase } +func (dk *DynaKube) FeatureRemoteImageDownload() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureCodeModulesRemoteImageDownload) == truePhrase +} + func (dk *DynaKube) FeatureInjectionFailurePolicy() string { if dk.getFeatureFlagRaw(AnnotationInjectionFailurePolicy) == failPhrase { return failPhrase diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go index 9c8dcdfbcf..bdb8b7fe40 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go @@ -14,6 +14,7 @@ const ( func TestGetVolumeMounts(t *testing.T) { tenantUUID := "test-uuid" + t.Run("get volume mounts", func(t *testing.T) { mounts := getVolumeMounts(tenantUUID) From bfe6b0ea65c20b90f388a312c91bd412b259a323 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 12:53:59 +0000 Subject: [PATCH 141/426] chore(deps): update docker/build-push-action action to v6.13.0 (main) (#4348) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 37f1167ae5..f0a833b597 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -31,7 +31,7 @@ runs: run: | hack/build/ci/third-party-licenses.sh - name: Build target - uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 + uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 with: builder: ${{ steps.buildx.outputs.name }} build-args: | From f24a1c9f9488aa7b6ccc96bbd4f918c8e470a43a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 20:41:20 +0000 Subject: [PATCH 142/426] chore(deps): update codecov/codecov-action action to v5.3.1 (main) (#4350) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 559b6f5988..e738643888 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -67,7 +67,7 @@ jobs: run: | make go/check-coverage - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@0da7aa657d958d32c117fc47e1f977e7524753c7 # v5.3.0 + uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 with: fail_ci_if_error: true verbose: true From 2258f4071d055daf1737941de71ad6b2fba97ac0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Jan 2025 01:31:12 +0000 Subject: [PATCH 143/426] chore(deps): update github/codeql-action action to v3.28.5 (main) (#4351) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 77ed9bf640..e09147283f 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4 + uses: github/codeql-action/init@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4 + uses: github/codeql-action/autobuild@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4 + uses: github/codeql-action/analyze@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 856d32c1e1..2b8fdefc6b 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4 + uses: github/codeql-action/upload-sarif@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5 with: sarif_file: results.sarif From 17acd8c328baaf8549ed8a11885de3ecfe8730a9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Jan 2025 09:01:51 +0000 Subject: [PATCH 144/426] chore(deps): update module github.com/igorshubovych/markdownlint-cli to v0.44.0 (main) (#4352) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- hack/make/prerequisites.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e738643888..87f071557e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -151,7 +151,7 @@ jobs: with: config: .markdownlint.json # renovate depName=github.com/igorshubovych/markdownlint-cli - version: v0.43.0 + version: v0.44.0 prepare: name: Prepare properties diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 3419c81c86..fc1d61f743 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -11,7 +11,7 @@ golang_tools_version=v0.29.0 # renovate depName=github.com/vektra/mockery mockery_version=v2.51.1 # renovate depName=github.com/igorshubovych/markdownlint-cli -markdownlint_cli_version=v0.43.0 +markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest helmunittest_version=v0.7.1 # renovate depName=github.com/princjef/gomarkdoc From f00e14a06a6c72f33d7906ca07e441546802f412 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 10:06:26 +0000 Subject: [PATCH 145/426] chore(deps): update actions/setup-node action to v4.2.0 (main) (#4354) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 87f071557e..3111fa6d34 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -109,7 +109,7 @@ jobs: uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 with: token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 - name: Check deepcopy files are up-to-date id: deepcopy run: | From cef9690e1fc8ed60f1c98a16bd347495eebeac83 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Mon, 27 Jan 2025 16:39:55 +0100 Subject: [PATCH 146/426] =?UTF-8?q?[Helm]=20Move=20collector=20service=20a?= =?UTF-8?q?ccount=20template=20to=20separate=20collector=20=E2=80=A6=20(#4?= =?UTF-8?q?312)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clusterole-extensions-prometheus.yaml} | 6 +++--- .../role-extensions-controller.yaml | 0 .../serviceaccount-extensions-controller.yaml | 0 .../serviceaccount-opentelemetry-collector.yaml} | 4 ++-- config/helm/chart/default/templates/_labels.tpl | 4 ++-- .../clusterrole-extensions-prometheus_test.yaml} | 4 ++-- .../role-extensions-controller_test.yaml | 2 +- .../serviceaccount-extensions-controller_test.yaml | 2 +- .../serviceaccount-opentelemetry-collector_test.yaml} | 6 +++--- 9 files changed, 14 insertions(+), 14 deletions(-) rename config/helm/chart/default/templates/Common/{extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector.yaml => extensions/clusterole-extensions-prometheus.yaml} (88%) rename config/helm/chart/default/templates/Common/{extensions-controller => extensions}/role-extensions-controller.yaml (100%) rename config/helm/chart/default/templates/Common/{extensions-controller => extensions}/serviceaccount-extensions-controller.yaml (100%) rename config/helm/chart/default/templates/Common/{extensions-opentelemetry-collector/serviceaccount-extensions-opentelemetry-collector.yaml => opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml} (86%) rename config/helm/chart/default/tests/Common/{extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector_test.yaml => extensions/clusterrole-extensions-prometheus_test.yaml} (93%) rename config/helm/chart/default/tests/Common/{extensions-controller => extensions}/role-extensions-controller_test.yaml (94%) rename config/helm/chart/default/tests/Common/{extensions-controller => extensions}/serviceaccount-extensions-controller_test.yaml (91%) rename config/helm/chart/default/tests/Common/{extensions-opentelemetry-collector/serviceaccount-extensions-opentelemetry-collector_test.yaml => opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml} (67%) diff --git a/config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector.yaml b/config/helm/chart/default/templates/Common/extensions/clusterole-extensions-prometheus.yaml similarity index 88% rename from config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector.yaml rename to config/helm/chart/default/templates/Common/extensions/clusterole-extensions-prometheus.yaml index 3c685cee95..01e80e3849 100644 --- a/config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector.yaml +++ b/config/helm/chart/default/templates/Common/extensions/clusterole-extensions-prometheus.yaml @@ -18,7 +18,7 @@ metadata: name: dynatrace-extensions-prometheus namespace: {{ .Release.Namespace }} labels: - {{- include "dynatrace-operator.extensionsOpenTelemetryCollectorLabels" . | nindent 4 }} + {{- include "dynatrace-operator.openTelemetryCollectorLabels" . | nindent 4 }} rules: - apiGroups: - "" @@ -66,13 +66,13 @@ metadata: name: dynatrace-extensions-prometheus namespace: {{ .Release.Namespace }} labels: - {{- include "dynatrace-operator.extensionsOpenTelemetryCollectorLabels" . | nindent 4 }} + {{- include "dynatrace-operator.openTelemetryCollectorLabels" . | nindent 4 }} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: dynatrace-extensions-prometheus subjects: - kind: ServiceAccount - name: dynatrace-extensions-collector + name: dynatrace-opentelemetry-collector namespace: {{ .Release.Namespace }} {{ end }} diff --git a/config/helm/chart/default/templates/Common/extensions-controller/role-extensions-controller.yaml b/config/helm/chart/default/templates/Common/extensions/role-extensions-controller.yaml similarity index 100% rename from config/helm/chart/default/templates/Common/extensions-controller/role-extensions-controller.yaml rename to config/helm/chart/default/templates/Common/extensions/role-extensions-controller.yaml diff --git a/config/helm/chart/default/templates/Common/extensions-controller/serviceaccount-extensions-controller.yaml b/config/helm/chart/default/templates/Common/extensions/serviceaccount-extensions-controller.yaml similarity index 100% rename from config/helm/chart/default/templates/Common/extensions-controller/serviceaccount-extensions-controller.yaml rename to config/helm/chart/default/templates/Common/extensions/serviceaccount-extensions-controller.yaml diff --git a/config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/serviceaccount-extensions-opentelemetry-collector.yaml b/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml similarity index 86% rename from config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/serviceaccount-extensions-opentelemetry-collector.yaml rename to config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml index e12f0c6af9..3f59b77e3b 100644 --- a/config/helm/chart/default/templates/Common/extensions-opentelemetry-collector/serviceaccount-extensions-opentelemetry-collector.yaml +++ b/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml @@ -15,12 +15,12 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: dynatrace-extensions-collector + name: dynatrace-opentelemetry-collector namespace: {{ .Release.Namespace }} {{- if .Values.rbac.extensions.annotations }} annotations: {{- toYaml .Values.rbac.extensions.annotations | nindent 4 }} {{- end }} labels: - {{- include "dynatrace-operator.extensionsOpenTelemetryCollectorLabels" . | nindent 4 }} + {{- include "dynatrace-operator.openTelemetryCollectorLabels" . | nindent 4 }} {{ end }} diff --git a/config/helm/chart/default/templates/_labels.tpl b/config/helm/chart/default/templates/_labels.tpl index 87870e9d8d..7a293eff6f 100644 --- a/config/helm/chart/default/templates/_labels.tpl +++ b/config/helm/chart/default/templates/_labels.tpl @@ -110,9 +110,9 @@ app.kubernetes.io/component: dynatrace-extensions-controller {{- end -}} {{/* -Extensions OpenTelemetry Collector (OTelC) labels +OpenTelemetry Collector (OTelC) labels */}} -{{- define "dynatrace-operator.extensionsOpenTelemetryCollectorLabels" -}} +{{- define "dynatrace-operator.openTelemetryCollectorLabels" -}} {{ include "dynatrace-operator.commonLabels" . }} app.kubernetes.io/component: dynatrace-extensions-collector {{- end -}} diff --git a/config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector_test.yaml b/config/helm/chart/default/tests/Common/extensions/clusterrole-extensions-prometheus_test.yaml similarity index 93% rename from config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector_test.yaml rename to config/helm/chart/default/tests/Common/extensions/clusterrole-extensions-prometheus_test.yaml index 53d3121159..419927817b 100644 --- a/config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector_test.yaml +++ b/config/helm/chart/default/tests/Common/extensions/clusterrole-extensions-prometheus_test.yaml @@ -1,6 +1,6 @@ -suite: test clusterrole for the extensions OpenTelemetry collector +suite: test clusterrole for the dynatrace OpenTelemetry collector templates: - - Common/extensions-opentelemetry-collector/clusterrole-extensions-opentelemetry-collector.yaml + - Common/extensions/clusterole-extensions-prometheus.yaml tests: - it: ClusterRole and ClusterRoleBinding exists asserts: diff --git a/config/helm/chart/default/tests/Common/extensions-controller/role-extensions-controller_test.yaml b/config/helm/chart/default/tests/Common/extensions/role-extensions-controller_test.yaml similarity index 94% rename from config/helm/chart/default/tests/Common/extensions-controller/role-extensions-controller_test.yaml rename to config/helm/chart/default/tests/Common/extensions/role-extensions-controller_test.yaml index 6e347718df..9aef6a58b3 100644 --- a/config/helm/chart/default/tests/Common/extensions-controller/role-extensions-controller_test.yaml +++ b/config/helm/chart/default/tests/Common/extensions/role-extensions-controller_test.yaml @@ -1,6 +1,6 @@ suite: test role for the extensions controller templates: - - Common/extensions-controller/role-extensions-controller.yaml + - Common/extensions/role-extensions-controller.yaml tests: - it: should not exist by default asserts: diff --git a/config/helm/chart/default/tests/Common/extensions-controller/serviceaccount-extensions-controller_test.yaml b/config/helm/chart/default/tests/Common/extensions/serviceaccount-extensions-controller_test.yaml similarity index 91% rename from config/helm/chart/default/tests/Common/extensions-controller/serviceaccount-extensions-controller_test.yaml rename to config/helm/chart/default/tests/Common/extensions/serviceaccount-extensions-controller_test.yaml index 275f95ac7f..9b0ddcb024 100644 --- a/config/helm/chart/default/tests/Common/extensions-controller/serviceaccount-extensions-controller_test.yaml +++ b/config/helm/chart/default/tests/Common/extensions/serviceaccount-extensions-controller_test.yaml @@ -1,6 +1,6 @@ suite: test service account for extensions controller templates: - - Common/extensions-controller/serviceaccount-extensions-controller.yaml + - Common/extensions/serviceaccount-extensions-controller.yaml tests: - it: should exist set: diff --git a/config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/serviceaccount-extensions-opentelemetry-collector_test.yaml b/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml similarity index 67% rename from config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/serviceaccount-extensions-opentelemetry-collector_test.yaml rename to config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml index 5c977365e1..eb9736f84a 100644 --- a/config/helm/chart/default/tests/Common/extensions-opentelemetry-collector/serviceaccount-extensions-opentelemetry-collector_test.yaml +++ b/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml @@ -1,6 +1,6 @@ -suite: test service account for extensions OpenTelemetry collector +suite: test service account for dynatrace OpenTelemetry collector templates: - - Common/extensions-opentelemetry-collector/serviceaccount-extensions-opentelemetry-collector.yaml + - Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml tests: - it: should exist set: @@ -10,7 +10,7 @@ tests: of: ServiceAccount - equal: path: metadata.name - value: dynatrace-extensions-collector + value: dynatrace-opentelemetry-collector - equal: path: metadata.namespace value: NAMESPACE From accb0a52a9df1fff3ac8464b9c68425a1361c76a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 05:00:27 +0000 Subject: [PATCH 147/426] chore(deps): update aws-actions/configure-aws-credentials action to v4.0.3 (main) (#4362) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b4db24e25a..6965481544 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -93,7 +93,7 @@ jobs: password: ${{ secrets[matrix.password] }} - name: Configure aws credentials if: ${{ matrix.registry == 'amazon-ecr' }} - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 with: role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} aws-region: us-east-1 @@ -161,7 +161,7 @@ jobs: password: ${{ secrets[matrix.password] }} - name: Configure aws credentials if: ${{ matrix.registry == 'amazon-ecr' }} - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 with: role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} aws-region: us-east-1 @@ -221,7 +221,7 @@ jobs: password: ${{ secrets[matrix.password] }} - name: Configure aws credentials if: ${{ matrix.registry == 'amazon-ecr' }} - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 with: role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} aws-region: us-east-1 @@ -333,7 +333,7 @@ jobs: cosign-private-key: ${{ secrets.COSIGN_PRIVATE_KEY }} cosign-password: ${{ secrets.COSIGN_PASSWORD }} - name: Configure aws credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 with: role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} aws-region: us-east-1 From e321f28e62cb3f65fc3e91a81f97c039f24fbb52 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 07:31:27 +0000 Subject: [PATCH 148/426] chore(deps): update github/codeql-action action to v3.28.6 (main) (#4360) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index e09147283f..00f427fc1b 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5 + uses: github/codeql-action/init@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5 + uses: github/codeql-action/autobuild@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5 + uses: github/codeql-action/analyze@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 2b8fdefc6b..41d0eacaa1 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5 + uses: github/codeql-action/upload-sarif@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 with: sarif_file: results.sarif From c457ad07b6dd12f85fbb7774839cbff216be33e4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 07:39:29 +0000 Subject: [PATCH 149/426] chore(deps): update module github.com/helm-unittest/helm-unittest to v0.7.2 (main) (#4363) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index fc1d61f743..51dcda393e 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -13,7 +13,7 @@ mockery_version=v2.51.1 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest -helmunittest_version=v0.7.1 +helmunittest_version=v0.7.2 # renovate depName=github.com/princjef/gomarkdoc gomarkdoc_version=v1.1.0 From 75bb3671ed5ec6db63614d5de2492752e71d94bc Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Tue, 28 Jan 2025 08:45:16 +0100 Subject: [PATCH 150/426] fixup e2e tests: wrong check during codemodules getInstaller inside provisioner (#4347) Co-authored-by: Marcell Sevcsik --- .../csi/provisioner/controller_test.go | 3 +- pkg/controllers/csi/provisioner/install.go | 50 ++++++++----------- .../csi/provisioner/install_test.go | 15 +----- 3 files changed, 23 insertions(+), 45 deletions(-) diff --git a/pkg/controllers/csi/provisioner/controller_test.go b/pkg/controllers/csi/provisioner/controller_test.go index 3b0060aa0c..7fdd4ae88c 100644 --- a/pkg/controllers/csi/provisioner/controller_test.go +++ b/pkg/controllers/csi/provisioner/controller_test.go @@ -292,8 +292,7 @@ func createPMCSecret(t *testing.T, dk *dynakube.DynaKube) *corev1.Secret { func createPMCSourceFile(t *testing.T, prov OneAgentProvisioner, dk *dynakube.DynaKube) { t.Helper() - targetDir, err := prov.getTargetDir(*dk) - require.NoError(t, err) + targetDir := prov.getTargetDir(*dk) pmcPath := filepath.Join(targetDir, processmoduleconfig.RuxitAgentProcPath) pmcDir := filepath.Dir(pmcPath) diff --git a/pkg/controllers/csi/provisioner/install.go b/pkg/controllers/csi/provisioner/install.go index 5c2646e024..e980860a85 100644 --- a/pkg/controllers/csi/provisioner/install.go +++ b/pkg/controllers/csi/provisioner/install.go @@ -3,7 +3,6 @@ package csiprovisioner import ( "context" "encoding/base64" - "errors" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/arch" @@ -24,10 +23,7 @@ func (provisioner *OneAgentProvisioner) installAgent(ctx context.Context, dk dyn return err } - targetDir, err := provisioner.getTargetDir(dk) - if err != nil { - return err - } + targetDir := provisioner.getTargetDir(dk) _, err = agentInstaller.InstallAgent(ctx, targetDir) if err != nil { @@ -43,8 +39,21 @@ func (provisioner *OneAgentProvisioner) installAgent(ctx context.Context, dk dyn } func (provisioner *OneAgentProvisioner) getInstaller(ctx context.Context, dk dynakube.DynaKube) (installer.Installer, error) { - switch { - case dk.OneAgent().GetCodeModulesVersion() != "": + if dk.OneAgent().GetCustomCodeModulesImage() != "" { + props := &image.Properties{ + ImageUri: dk.OneAgent().GetCodeModulesImage(), + ApiReader: provisioner.apiReader, + Dynakube: &dk, + PathResolver: provisioner.path, + } + + imageInstaller, err := provisioner.imageInstallerBuilder(ctx, provisioner.fs, props) + if err != nil { + return nil, err + } + + return imageInstaller, nil + } else { dtc, err := buildDtc(provisioner, ctx, dk) if err != nil { return nil, err @@ -64,40 +73,21 @@ func (provisioner *OneAgentProvisioner) getInstaller(ctx context.Context, dk dyn urlInstaller := provisioner.urlInstallerBuilder(provisioner.fs, dtc, props) return urlInstaller, nil - case dk.OneAgent().GetCodeModulesImage() != "": - props := &image.Properties{ - ImageUri: dk.OneAgent().GetCodeModulesImage(), - ApiReader: provisioner.apiReader, - Dynakube: &dk, - PathResolver: provisioner.path, - } - - imageInstaller, err := provisioner.imageInstallerBuilder(ctx, provisioner.fs, props) - if err != nil { - return nil, err - } - - return imageInstaller, nil - default: - return nil, errors.New("missing version/image information to download CodeModule") } } -func (provisioner *OneAgentProvisioner) getTargetDir(dk dynakube.DynaKube) (string, error) { +func (provisioner *OneAgentProvisioner) getTargetDir(dk dynakube.DynaKube) string { var dirName string - switch { - case dk.OneAgent().GetCodeModulesImage() != "": + if dk.OneAgent().GetCustomCodeModulesImage() != "" { // An image URI often contains one or several slashes, which is problematic when trying to use it as a folder name. // Easiest to just base64 encode it dirName = base64.StdEncoding.EncodeToString([]byte(dk.OneAgent().GetCodeModulesImage())) - case dk.OneAgent().GetCodeModulesVersion() != "": + } else { dirName = dk.OneAgent().GetCodeModulesVersion() - default: - return "", errors.New("failed to determine the target directory for the CodeModule download") } - return provisioner.path.AgentSharedBinaryDirForAgent(dirName), nil + return provisioner.path.AgentSharedBinaryDirForAgent(dirName) } func (provisioner *OneAgentProvisioner) createLatestVersionSymlink(dk dynakube.DynaKube, targetDir string) error { diff --git a/pkg/controllers/csi/provisioner/install_test.go b/pkg/controllers/csi/provisioner/install_test.go index 5d239de3ef..0c46b4a71e 100644 --- a/pkg/controllers/csi/provisioner/install_test.go +++ b/pkg/controllers/csi/provisioner/install_test.go @@ -12,8 +12,7 @@ func TestGetTargetDir(t *testing.T) { prov := createProvisioner(t) dk := createDynaKubeWithVersion(t) - targetDir, err := prov.getTargetDir(*dk) - require.NoError(t, err) + targetDir := prov.getTargetDir(*dk) require.Contains(t, targetDir, dk.OneAgent().GetCodeModulesVersion()) }) @@ -22,17 +21,7 @@ func TestGetTargetDir(t *testing.T) { dk := createDynaKubeWithImage(t) expectedDir := base64.StdEncoding.EncodeToString([]byte(dk.OneAgent().GetCodeModulesImage())) - targetDir, err := prov.getTargetDir(*dk) - require.NoError(t, err) + targetDir := prov.getTargetDir(*dk) require.Contains(t, targetDir, expectedDir) }) - - t.Run("nothing set => error (shouldn't be possible in real life)", func(t *testing.T) { - prov := createProvisioner(t) - dk := createDynaKubeBase(t) - - targetDir, err := prov.getTargetDir(*dk) - require.Error(t, err) - require.Empty(t, targetDir) - }) } From dfba3bb02f0a5d6d13283edbe30a53e414880e0d Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Tue, 28 Jan 2025 08:51:15 +0100 Subject: [PATCH 151/426] Cherry-pick e2e tests extensions (#4359) Co-authored-by: Stefan Hauth --- test/features/extensions/extensions.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/features/extensions/extensions.go b/test/features/extensions/extensions.go index 5e7e43bd2a..ee00beb1e5 100644 --- a/test/features/extensions/extensions.go +++ b/test/features/extensions/extensions.go @@ -30,10 +30,11 @@ func Feature(t *testing.T) features.Feature { options := []componentDynakube.Option{ componentDynakube.WithApiUrl(secretConfig.ApiUrl), - componentDynakube.WithActiveGateTLSSecret(consts.AgSecretName), componentDynakube.WithCustomPullSecret(consts.DevRegistryPullSecretName), componentDynakube.WithExtensionsEnabledSpec(true), componentDynakube.WithExtensionsEECImageRefSpec(consts.EecImageRepo, consts.EecImageTag), + componentDynakube.WithActiveGate(), + componentDynakube.WithActiveGateTLSSecret(consts.AgSecretName), } testDynakube := *componentDynakube.New(options...) From bcecbd090b2656eaa75cc1e95c5df066dd9d609a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 09:25:22 +0000 Subject: [PATCH 152/426] fix(deps): update module github.com/evanphx/json-patch to v5.9.10+incompatible (main) (#4364) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4c9afe09d6..674a97bb4b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.3 require ( github.com/container-storage-interface/spec v1.11.0 github.com/docker/cli v27.5.1+incompatible - github.com/evanphx/json-patch v5.9.0+incompatible + github.com/evanphx/json-patch v5.9.10+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.3 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 1c0418e6f7..f926eea413 100644 --- a/go.sum +++ b/go.sum @@ -22,8 +22,8 @@ github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZ github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= -github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.9.10+incompatible h1:f9RK4b5sgikwA7D5BkGR9oz69KM7riR/0qaNoBzmJso= +github.com/evanphx/json-patch v5.9.10+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= From b214c719fadb51313ab90adbc3b9f23415b775bc Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Tue, 28 Jan 2025 12:06:26 +0100 Subject: [PATCH 153/426] Removes a log message that corrupts support_archive zip package (#4358) --- cmd/csi/init/cmd.go | 2 ++ cmd/csi/provisioner/cmd.go | 2 ++ cmd/csi/server/cmd.go | 2 ++ cmd/operator/builder.go | 2 ++ cmd/support_archive/builder.go | 2 ++ cmd/webhook/builder.go | 2 ++ pkg/api/v1beta1/dynakube/convert_from.go | 4 +--- pkg/api/v1beta1/dynakube/convert_from_test.go | 3 ++- pkg/api/v1beta2/dynakube/convert_from.go | 4 +--- pkg/api/v1beta2/dynakube/convert_from_test.go | 3 ++- pkg/util/installconfig/modules.go | 12 ++++++++++-- 11 files changed, 28 insertions(+), 10 deletions(-) diff --git a/cmd/csi/init/cmd.go b/cmd/csi/init/cmd.go index 3d97d07ca7..9efde049ed 100644 --- a/cmd/csi/init/cmd.go +++ b/cmd/csi/init/cmd.go @@ -8,6 +8,7 @@ import ( dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/version" "github.com/pkg/errors" @@ -36,6 +37,7 @@ func New() *cobra.Command { func run() func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { unix.Umask(dtcsi.UnixUmask) + installconfig.ReadModules() version.LogVersion() logd.LogBaseLoggerSettings() diff --git a/cmd/csi/provisioner/cmd.go b/cmd/csi/provisioner/cmd.go index 3330336f55..adb27fe796 100644 --- a/cmd/csi/provisioner/cmd.go +++ b/cmd/csi/provisioner/cmd.go @@ -8,6 +8,7 @@ import ( dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csiprovisioner "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/provisioner" "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/version" "github.com/pkg/errors" @@ -52,6 +53,7 @@ func addFlags(cmd *cobra.Command) { func run() func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { unix.Umask(dtcsi.UnixUmask) + installconfig.ReadModules() version.LogVersion() logd.LogBaseLoggerSettings() diff --git a/cmd/csi/server/cmd.go b/cmd/csi/server/cmd.go index 1d7e6f731f..ff780ea364 100644 --- a/cmd/csi/server/cmd.go +++ b/cmd/csi/server/cmd.go @@ -8,6 +8,7 @@ import ( dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csidriver "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver" "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/version" "github.com/pkg/errors" @@ -49,6 +50,7 @@ func addFlags(cmd *cobra.Command) { func run() func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { unix.Umask(dtcsi.UnixUmask) + installconfig.ReadModules() version.LogVersion() logd.LogBaseLoggerSettings() diff --git a/cmd/operator/builder.go b/cmd/operator/builder.go index 195c97629e..fc15a432c6 100644 --- a/cmd/operator/builder.go +++ b/cmd/operator/builder.go @@ -7,6 +7,7 @@ import ( cmdManager "github.com/Dynatrace/dynatrace-operator/cmd/manager" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/certificates" "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/pod" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubesystem" "github.com/Dynatrace/dynatrace-operator/pkg/version" @@ -125,6 +126,7 @@ func (builder CommandBuilder) setClientFromConfig(kubeCfg *rest.Config) (Command func (builder CommandBuilder) buildRun() func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { + installconfig.ReadModules() version.LogVersion() logd.LogBaseLoggerSettings() diff --git a/cmd/support_archive/builder.go b/cmd/support_archive/builder.go index 297e05de7b..d505df8453 100644 --- a/cmd/support_archive/builder.go +++ b/cmd/support_archive/builder.go @@ -11,6 +11,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/cmd/remote_command" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/version" @@ -97,6 +98,7 @@ func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { logBuffer := bytes.Buffer{} log := newSupportArchiveLogger(getLogOutput(archiveToStdoutFlagValue, &logBuffer)) + installconfig.ReadModulesToLogger(log) version.LogVersionToLogger(log) archiveTargetFile, err := createZipArchiveTargetFile(archiveToStdoutFlagValue, defaultSupportArchiveTargetDir) diff --git a/cmd/webhook/builder.go b/cmd/webhook/builder.go index b0a07d1669..39a0e74d54 100644 --- a/cmd/webhook/builder.go +++ b/cmd/webhook/builder.go @@ -14,6 +14,7 @@ import ( dynakubevalidation "github.com/Dynatrace/dynatrace-operator/pkg/api/validation/dynakube" edgeconnectvalidation "github.com/Dynatrace/dynatrace-operator/pkg/api/validation/edgeconnect" "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/pod" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubesystem" "github.com/Dynatrace/dynatrace-operator/pkg/version" @@ -121,6 +122,7 @@ func startCertificateWatcher(webhookManager manager.Manager, namespace string, p func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { + installconfig.ReadModules() version.LogVersion() logd.LogBaseLoggerSettings() diff --git a/pkg/api/v1beta1/dynakube/convert_from.go b/pkg/api/v1beta1/dynakube/convert_from.go index 34b695f990..529d2eeef4 100644 --- a/pkg/api/v1beta1/dynakube/convert_from.go +++ b/pkg/api/v1beta1/dynakube/convert_from.go @@ -10,8 +10,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/conversion" ) -var isEnabledModules = installconfig.GetModules() - // ConvertFrom converts v1beta3 to v1beta1. func (dst *DynaKube) ConvertFrom(srcRaw conversion.Hub) error { src := srcRaw.(*dynakube.DynaKube) @@ -61,7 +59,7 @@ func (dst *DynaKube) fromOneAgentSpec(src *dynakube.DynaKube) { dst.Spec.OneAgent.ApplicationMonitoring = &ApplicationMonitoringSpec{} dst.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec = *fromAppInjectSpec(src.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec) dst.Spec.OneAgent.ApplicationMonitoring.Version = src.Spec.OneAgent.ApplicationMonitoring.Version - dst.Spec.OneAgent.ApplicationMonitoring.UseCSIDriver = &isEnabledModules.CSIDriver + dst.Spec.OneAgent.ApplicationMonitoring.UseCSIDriver = ptr.To(installconfig.GetModules().CSIDriver) } } diff --git a/pkg/api/v1beta1/dynakube/convert_from_test.go b/pkg/api/v1beta1/dynakube/convert_from_test.go index b76aaacb51..3d17116192 100644 --- a/pkg/api/v1beta1/dynakube/convert_from_test.go +++ b/pkg/api/v1beta1/dynakube/convert_from_test.go @@ -9,6 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -176,7 +177,7 @@ func compareCloudNativeSpec(t *testing.T, oldSpec CloudNativeFullStackSpec, newS func compareApplicationMonitoringSpec(t *testing.T, oldSpec ApplicationMonitoringSpec, newSpec oneagent.ApplicationMonitoringSpec) { compareAppInjectionSpec(t, oldSpec.AppInjectionSpec, newSpec.AppInjectionSpec) - assert.Equal(t, *oldSpec.UseCSIDriver, isEnabledModules.CSIDriver) + assert.Equal(t, *oldSpec.UseCSIDriver, installconfig.GetModules().CSIDriver) assert.Equal(t, oldSpec.Version, newSpec.Version) } diff --git a/pkg/api/v1beta2/dynakube/convert_from.go b/pkg/api/v1beta2/dynakube/convert_from.go index 6147a99d3f..56839738c6 100644 --- a/pkg/api/v1beta2/dynakube/convert_from.go +++ b/pkg/api/v1beta2/dynakube/convert_from.go @@ -7,8 +7,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/conversion" ) -var isEnabledModules = installconfig.GetModules() - // ConvertFrom converts from the Hub version (v1beta3) to this version (v1beta3). func (dst *DynaKube) ConvertFrom(srcRaw conversion.Hub) error { src := srcRaw.(*dynakube.DynaKube) @@ -56,7 +54,7 @@ func (dst *DynaKube) fromOneAgentSpec(src *dynakube.DynaKube) { dst.Spec.OneAgent.ApplicationMonitoring = &ApplicationMonitoringSpec{} dst.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec = *fromAppInjectSpec(src.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec) dst.Spec.OneAgent.ApplicationMonitoring.Version = src.Spec.OneAgent.ApplicationMonitoring.Version - dst.Spec.OneAgent.ApplicationMonitoring.UseCSIDriver = isEnabledModules.CSIDriver + dst.Spec.OneAgent.ApplicationMonitoring.UseCSIDriver = installconfig.GetModules().CSIDriver } } diff --git a/pkg/api/v1beta2/dynakube/convert_from_test.go b/pkg/api/v1beta2/dynakube/convert_from_test.go index e353be01ec..11a63a961e 100644 --- a/pkg/api/v1beta2/dynakube/convert_from_test.go +++ b/pkg/api/v1beta2/dynakube/convert_from_test.go @@ -9,6 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -167,7 +168,7 @@ func compareCloudNativeSpec(t *testing.T, oldSpec CloudNativeFullStackSpec, newS func compareApplicationMonitoringSpec(t *testing.T, oldSpec ApplicationMonitoringSpec, newSpec oneagent.ApplicationMonitoringSpec) { compareAppInjectionSpec(t, oldSpec.AppInjectionSpec, newSpec.AppInjectionSpec) - assert.Equal(t, oldSpec.UseCSIDriver, isEnabledModules.CSIDriver) + assert.Equal(t, oldSpec.UseCSIDriver, installconfig.GetModules().CSIDriver) assert.Equal(t, oldSpec.Version, newSpec.Version) } diff --git a/pkg/util/installconfig/modules.go b/pkg/util/installconfig/modules.go index 312d415cdc..1e200c9eab 100644 --- a/pkg/util/installconfig/modules.go +++ b/pkg/util/installconfig/modules.go @@ -54,6 +54,16 @@ func GetModules() Modules { return *override } + ReadModules() + + return modules +} + +func ReadModules() { + ReadModulesToLogger(log) +} + +func ReadModulesToLogger(log logd.Logger) { once.Do(func() { modulesJson := os.Getenv(ModulesJsonEnv) if modulesJson == "" { @@ -71,8 +81,6 @@ func GetModules() Modules { log.Info("envvar content read and set", "envvar", ModulesJsonEnv, "value", modulesJson) }) - - return modules } // SetModulesOverride is a testing function, so you can easily unittest function using the GetModules() func From 8cccb6ae2c523291e4ddd9d87d38dd3960cb231f Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Tue, 28 Jan 2025 12:17:42 +0100 Subject: [PATCH 154/426] Automate creation of Otel collector Service (#4333) --- .../dynakube/telemetryservice/props.go | 10 + .../v1beta3/dynakube/telemetryservice/spec.go | 2 + .../dynakube/telemetryservice_props.go | 5 +- .../validation/dynakube/telemetryservice.go | 27 +++ .../dynakube/telemetryservice_test.go | 28 +++ pkg/api/validation/dynakube/validation.go | 1 + pkg/controllers/dynakube/extension/service.go | 14 +- pkg/controllers/dynakube/otelc/reconciler.go | 10 +- .../dynakube/otelc/service/conditions.go | 5 + .../dynakube/otelc/service/config.go | 7 + .../dynakube/otelc/service/reconciler.go | 188 ++++++++++++++++++ .../dynakube/otelc/service/reconciler_test.go | 159 +++++++++++++++ pkg/util/kubeobjects/labels/labels.go | 1 + pkg/util/kubeobjects/service/builder.go | 22 +- pkg/util/kubeobjects/service/builder_test.go | 5 +- 15 files changed, 454 insertions(+), 30 deletions(-) create mode 100644 pkg/controllers/dynakube/otelc/service/conditions.go create mode 100644 pkg/controllers/dynakube/otelc/service/config.go create mode 100644 pkg/controllers/dynakube/otelc/service/reconciler.go create mode 100644 pkg/controllers/dynakube/otelc/service/reconciler_test.go diff --git a/pkg/api/v1beta3/dynakube/telemetryservice/props.go b/pkg/api/v1beta3/dynakube/telemetryservice/props.go index 1282ce4bfb..b391039883 100644 --- a/pkg/api/v1beta3/dynakube/telemetryservice/props.go +++ b/pkg/api/v1beta3/dynakube/telemetryservice/props.go @@ -3,6 +3,8 @@ package telemetryservice type Protocol string const ( + nameSuffix = "-telemetry" + OtlpProtocol Protocol = "otlp" ZipkinProtocol Protocol = "zipkin" JaegerProtocol Protocol = "jaeger" @@ -35,6 +37,14 @@ func (spec *Spec) GetProtocols() []Protocol { return protocols } +func (ts *TelemetryService) SetName(name string) { + ts.name = name +} + +func (ts *TelemetryService) GetName() string { + return ts.name + nameSuffix +} + func (ts *TelemetryService) IsEnabled() bool { return ts.Spec != nil } diff --git a/pkg/api/v1beta3/dynakube/telemetryservice/spec.go b/pkg/api/v1beta3/dynakube/telemetryservice/spec.go index e166985e1f..81844ede76 100644 --- a/pkg/api/v1beta3/dynakube/telemetryservice/spec.go +++ b/pkg/api/v1beta3/dynakube/telemetryservice/spec.go @@ -2,6 +2,8 @@ package telemetryservice type TelemetryService struct { *Spec + + name string } // +kubebuilder:object:generate=true diff --git a/pkg/api/v1beta3/dynakube/telemetryservice_props.go b/pkg/api/v1beta3/dynakube/telemetryservice_props.go index 4a332e08f1..11fa60e724 100644 --- a/pkg/api/v1beta3/dynakube/telemetryservice_props.go +++ b/pkg/api/v1beta3/dynakube/telemetryservice_props.go @@ -5,7 +5,10 @@ import ( ) func (dk *DynaKube) TelemetryService() *telemetryservice.TelemetryService { - return &telemetryservice.TelemetryService{ + ts := &telemetryservice.TelemetryService{ Spec: dk.Spec.TelemetryService, } + ts.SetName(dk.Name) + + return ts } diff --git a/pkg/api/validation/dynakube/telemetryservice.go b/pkg/api/validation/dynakube/telemetryservice.go index 36ac8ec51f..45efd12bdd 100644 --- a/pkg/api/validation/dynakube/telemetryservice.go +++ b/pkg/api/validation/dynakube/telemetryservice.go @@ -2,17 +2,22 @@ package validation import ( "context" + "fmt" "slices" "strings" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "k8s.io/apimachinery/pkg/util/validation" ) const ( errorTelemetryServiceNotEnoughProtocols = `DynaKube's specification enables the TelemetryService feature, at least one Protocol has to be specified.` errorTelemetryServiceUnknownProtocols = `DynaKube's specification enables the TelemetryService feature, unsupported protocols found on the Protocols list.` errorTelemetryServiceDuplicatedProtocols = `DynaKube's specification enables the TelemetryService feature, duplicated protocols found on the Protocols list.` + errorTelemetryServiceNoDNS1053Label = `DynaKube's specification enables the TelemetryService feature, the telemetry service name violates DNS-1035. + [The length limit for the name is %d. Additionally a DNS-1035 name must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')] + ` ) func emptyTelemetryServiceProtocolsList(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { @@ -82,3 +87,25 @@ func duplicatedTelemetryServiceProtocols(_ context.Context, _ *Validator, dk *dy return "" } + +func invalidTelemetryServiceName(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryService().IsEnabled() { + return "" + } + + var errs []string + + if dk.TelemetryService().ServiceName != "" { + errs = validation.IsDNS1035Label(dk.Spec.TelemetryService.ServiceName) + } + + if len(errs) == 0 { + return "" + } + + return invalidTelemetryServiceNameErrorMessage() +} + +func invalidTelemetryServiceNameErrorMessage() string { + return fmt.Sprintf(errorTelemetryServiceNoDNS1053Label, validation.DNS1035LabelMaxLength) +} diff --git a/pkg/api/validation/dynakube/telemetryservice_test.go b/pkg/api/validation/dynakube/telemetryservice_test.go index 1afa421a61..894f39ea22 100644 --- a/pkg/api/validation/dynakube/telemetryservice_test.go +++ b/pkg/api/validation/dynakube/telemetryservice_test.go @@ -129,4 +129,32 @@ func TestTelemetryServiceProtocols(t *testing.T) { }, }) }) + + t.Run(`service name too long`, func(t *testing.T) { + assertDenied(t, + []string{invalidTelemetryServiceNameErrorMessage()}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryService: &telemetryservice.Spec{ + ServiceName: "a123456789012345678901234567890123456789012345678901234567890123", + }, + }, + }) + }) + + t.Run(`service name violates DNS-1035`, func(t *testing.T) { + assertDenied(t, + []string{invalidTelemetryServiceNameErrorMessage()}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryService: &telemetryservice.Spec{ + ServiceName: "0123", + }, + }, + }) + }) } diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index e359d0ffea..2497e846e8 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -58,6 +58,7 @@ var ( emptyTelemetryServiceProtocolsList, unknownTelemetryServiceProtocols, duplicatedTelemetryServiceProtocols, + invalidTelemetryServiceName, extensionsWithoutK8SMonitoring, } validatorWarningFuncs = []validatorFunc{ diff --git a/pkg/controllers/dynakube/extension/service.go b/pkg/controllers/dynakube/extension/service.go index 147229842a..1477465559 100644 --- a/pkg/controllers/dynakube/extension/service.go +++ b/pkg/controllers/dynakube/extension/service.go @@ -66,17 +66,19 @@ func (r *reconciler) buildService() (*corev1.Service, error) { // TODO: add proper version later on appLabels := labels.NewAppLabels(labels.ExtensionComponentLabel, r.dk.Name, labels.ExtensionComponentLabel, "") - svcPort := corev1.ServicePort{ - Name: r.dk.ExtensionsPortName(), - Port: consts.OtelCollectorComPort, - Protocol: corev1.ProtocolTCP, - TargetPort: intstr.IntOrString{Type: intstr.String, StrVal: consts.ExtensionsCollectorTargetPortName}, + svcPorts := []corev1.ServicePort{ + { + Name: r.dk.ExtensionsPortName(), + Port: consts.OtelCollectorComPort, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.IntOrString{Type: intstr.String, StrVal: consts.ExtensionsCollectorTargetPortName}, + }, } return service.Build(r.dk, r.dk.ExtensionsServiceName(), appLabels.BuildMatchLabels(), - svcPort, + svcPorts, service.SetLabels(coreLabels.BuildLabels()), service.SetType(corev1.ServiceTypeClusterIP), ) diff --git a/pkg/controllers/dynakube/otelc/reconciler.go b/pkg/controllers/dynakube/otelc/reconciler.go index 85d770bb10..4ae09df19a 100644 --- a/pkg/controllers/dynakube/otelc/reconciler.go +++ b/pkg/controllers/dynakube/otelc/reconciler.go @@ -5,6 +5,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/service" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/statefulset" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -14,6 +15,7 @@ type Reconciler struct { apiReader client.Reader dk *dynakube.DynaKube statefulsetReconciler controllers.Reconciler + serviceReconciler *service.Reconciler } type ReconcilerBuilder func(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) controllers.Reconciler @@ -24,11 +26,17 @@ func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.D apiReader: apiReader, dk: dk, statefulsetReconciler: statefulset.NewReconciler(client, apiReader, dk), + serviceReconciler: service.NewReconciler(client, apiReader, dk), } } func (r *Reconciler) Reconcile(ctx context.Context) error { - err := r.statefulsetReconciler.Reconcile(ctx) + err := r.serviceReconciler.Reconcile(ctx) + if err != nil { + return err + } + + err = r.statefulsetReconciler.Reconcile(ctx) if err != nil { log.Info("failed to reconcile Dynatrace OTELc statefulset") diff --git a/pkg/controllers/dynakube/otelc/service/conditions.go b/pkg/controllers/dynakube/otelc/service/conditions.go new file mode 100644 index 0000000000..c6a49c2d7a --- /dev/null +++ b/pkg/controllers/dynakube/otelc/service/conditions.go @@ -0,0 +1,5 @@ +package service + +const ( + serviceConditionType = "OTELCService" +) diff --git a/pkg/controllers/dynakube/otelc/service/config.go b/pkg/controllers/dynakube/otelc/service/config.go new file mode 100644 index 0000000000..16130d363b --- /dev/null +++ b/pkg/controllers/dynakube/otelc/service/config.go @@ -0,0 +1,7 @@ +package service + +import "github.com/Dynatrace/dynatrace-operator/pkg/logd" + +var ( + log = logd.Get().WithName("otelc-service") +) diff --git a/pkg/controllers/dynakube/otelc/service/reconciler.go b/pkg/controllers/dynakube/otelc/service/reconciler.go new file mode 100644 index 0000000000..f062718484 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/service/reconciler.go @@ -0,0 +1,188 @@ +package service + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/service" + "golang.org/x/net/context" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + portNameZipkin = "zipkin" + portNameOtlpGrpc = "otlp-grpc" + portNameOtlpHttp = "otlp-http" + portNameJaegerGrpc = "jaeger-grpc" + portNameJaegerThriftBinary = "jaeger-thrift-binary" + portNameJaegerThriftCompact = "jaeger-thrift-compact" + portNameJaegerThriftHttp = "jaeger-thrift-http" + portNameStatsd = "statsd" +) + +type Reconciler struct { + client client.Client + apiReader client.Reader + dk *dynakube.DynaKube +} + +type ReconcilerBuilder func(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler + +func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler { + return &Reconciler{ + client: client, + dk: dk, + apiReader: apiReader, + } +} + +func (r *Reconciler) Reconcile(ctx context.Context) error { + if !r.dk.TelemetryService().IsEnabled() { + return r.removeServiceOnce(ctx) + } + + if r.dk.TelemetryService().ServiceName != "" { + return r.removeServiceOnce(ctx) + } + + return r.createOrUpdateService(ctx) +} + +func (r *Reconciler) removeServiceOnce(ctx context.Context) error { + if meta.FindStatusCondition(*r.dk.Conditions(), serviceConditionType) == nil { + return nil + } + defer meta.RemoveStatusCondition(r.dk.Conditions(), serviceConditionType) + + svc, err := r.buildService() + if err != nil { + log.Error(err, "could not build service during cleanup") + + return err + } + + err = service.Query(r.client, r.apiReader, log).Delete(ctx, svc) + if err != nil { + log.Error(err, "failed to clean up extension service") + + return nil + } + + return nil +} + +func (r *Reconciler) createOrUpdateService(ctx context.Context) error { + newService, err := r.buildService() + if err != nil { + conditions.SetServiceGenFailed(r.dk.Conditions(), serviceConditionType, err) + + return err + } + + _, err = service.Query(r.client, r.apiReader, log).CreateOrUpdate(ctx, newService) + if err != nil { + log.Info("failed to create/update otelc service") + conditions.SetKubeApiError(r.dk.Conditions(), serviceConditionType, err) + + return err + } + + conditions.SetServiceCreated(r.dk.Conditions(), serviceConditionType, r.dk.TelemetryService().GetName()) + + return nil +} + +func (r *Reconciler) buildService() (*corev1.Service, error) { + coreLabels := labels.NewCoreLabels(r.dk.Name, labels.OtelCComponentLabel) + // TODO: add proper version later on + appLabels := labels.NewAppLabels(labels.OtelCComponentLabel, r.dk.Name, labels.OtelCComponentLabel, "") + + var svcPorts []corev1.ServicePort + if r.dk.TelemetryService().IsEnabled() && r.dk.Spec.TelemetryService.ServiceName == "" { + svcPorts = buildServicePortList(r.dk.TelemetryService().GetProtocols()) + } + + return service.Build(r.dk, + r.dk.TelemetryService().GetName(), + appLabels.BuildMatchLabels(), + svcPorts, + service.SetLabels(coreLabels.BuildLabels()), + service.SetType(corev1.ServiceTypeClusterIP), + ) +} + +func buildServicePortList(protocols []telemetryservice.Protocol) []corev1.ServicePort { + if len(protocols) == 0 { + return nil + } + + svcPorts := make([]corev1.ServicePort, 0) + + for _, protocol := range protocols { + switch protocol { + case telemetryservice.ZipkinProtocol: + svcPorts = append(svcPorts, corev1.ServicePort{ + Name: portNameZipkin, + Port: 9411, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromInt32(9411), + }) + case telemetryservice.OtlpProtocol: + svcPorts = append(svcPorts, + corev1.ServicePort{ + Name: portNameOtlpGrpc, + Port: 4317, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromInt32(4317), + }, + corev1.ServicePort{ + Name: portNameOtlpHttp, + Port: 4318, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromInt32(4318), + }) + case telemetryservice.JaegerProtocol: + svcPorts = append(svcPorts, + corev1.ServicePort{ + Name: portNameJaegerGrpc, + Port: 14250, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromInt32(14250), + }, + corev1.ServicePort{ + Name: portNameJaegerThriftBinary, + Port: 6832, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromInt32(6832), + }, + corev1.ServicePort{ + Name: portNameJaegerThriftCompact, + Port: 6831, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromInt32(6831), + }, + corev1.ServicePort{ + Name: portNameJaegerThriftHttp, + Port: 14268, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromInt32(14268), + }) + case telemetryservice.StatsdProtocol: + svcPorts = append(svcPorts, + corev1.ServicePort{ + Name: portNameStatsd, + Port: 8125, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromInt32(8125), + }) + default: + log.Info("unknown telemetry service protocol ignored", "protocol", protocol) + } + } + + return svcPorts +} diff --git a/pkg/controllers/dynakube/otelc/service/reconciler_test.go b/pkg/controllers/dynakube/otelc/service/reconciler_test.go new file mode 100644 index 0000000000..961f1c487a --- /dev/null +++ b/pkg/controllers/dynakube/otelc/service/reconciler_test.go @@ -0,0 +1,159 @@ +package service + +import ( + "context" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +const ( + testDynakubeName = "dynakube" + testNamespaceName = "dynatrace" + testServiceName = "test-service-name" +) + +func getTestDynakube(telemetryServiceSpec *telemetryservice.Spec) *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakubeName, + Namespace: testNamespaceName, + }, + Spec: dynakube.DynaKubeSpec{ + TelemetryService: telemetryServiceSpec, + }, + Status: dynakube.DynaKubeStatus{}, + } +} + +func TestService(t *testing.T) { + t.Run("create service if it does not exist", func(t *testing.T) { + mockK8sClient := fake.NewFakeClient() + dk := getTestDynakube(&telemetryservice.Spec{}) + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + service := &corev1.Service{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + require.NoError(t, err) + + require.Len(t, service.Spec.Ports, 8) + assert.Equal(t, portNameOtlpGrpc, service.Spec.Ports[0].Name) + assert.Equal(t, portNameOtlpHttp, service.Spec.Ports[1].Name) + assert.Equal(t, portNameZipkin, service.Spec.Ports[2].Name) + assert.Equal(t, portNameJaegerGrpc, service.Spec.Ports[3].Name) + assert.Equal(t, portNameJaegerThriftBinary, service.Spec.Ports[4].Name) + assert.Equal(t, portNameJaegerThriftCompact, service.Spec.Ports[5].Name) + assert.Equal(t, portNameJaegerThriftHttp, service.Spec.Ports[6].Name) + assert.Equal(t, portNameStatsd, service.Spec.Ports[7].Name) + + require.Len(t, dk.Status.Conditions, 1) + assert.Equal(t, serviceConditionType, dk.Status.Conditions[0].Type) + assert.Equal(t, conditions.ServiceCreatedReason, dk.Status.Conditions[0].Reason) + assert.Equal(t, metav1.ConditionTrue, dk.Status.Conditions[0].Status) + }) + t.Run("remove service if it is not needed", func(t *testing.T) { + dk := getTestDynakube(nil) + dk.Status.Conditions = []metav1.Condition{ + { + Type: serviceConditionType, + }, + } + + mockK8sClient := fake.NewFakeClient() + err := mockK8sClient.Create(context.Background(), &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: dk.TelemetryService().GetName(), + Namespace: dk.Namespace, + }, + }) + require.NoError(t, err) + + err = NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + service := &corev1.Service{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err)) + + require.Empty(t, dk.Status.Conditions) + }) + t.Run("create service for specified protocols", func(t *testing.T) { + mockK8sClient := fake.NewFakeClient() + dk := getTestDynakube(&telemetryservice.Spec{ + Protocols: []string{ + string(telemetryservice.ZipkinProtocol), + string(telemetryservice.StatsdProtocol), + }, + }) + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + service := &corev1.Service{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + require.NoError(t, err) + + require.Len(t, service.Spec.Ports, 2) + assert.Equal(t, portNameZipkin, service.Spec.Ports[0].Name) + assert.Equal(t, portNameStatsd, service.Spec.Ports[1].Name) + + require.Len(t, dk.Status.Conditions, 1) + assert.Equal(t, serviceConditionType, dk.Status.Conditions[0].Type) + assert.Equal(t, conditions.ServiceCreatedReason, dk.Status.Conditions[0].Reason) + assert.Equal(t, metav1.ConditionTrue, dk.Status.Conditions[0].Status) + }) + t.Run("custom service", func(t *testing.T) { + mockK8sClient := fake.NewFakeClient() + dk := getTestDynakube(&telemetryservice.Spec{ + ServiceName: testServiceName, + }) + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + service := &corev1.Service{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: testServiceName, Namespace: dk.Namespace}, service) + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err)) + + assert.Empty(t, dk.Status.Conditions) + }) + t.Run("update from default service to custom service", func(t *testing.T) { + mockK8sClient := fake.NewFakeClient() + dk := getTestDynakube(&telemetryservice.Spec{}) + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + service := &corev1.Service{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + require.NoError(t, err) + + require.Len(t, dk.Status.Conditions, 1) + assert.Equal(t, serviceConditionType, dk.Status.Conditions[0].Type) + assert.Equal(t, conditions.ServiceCreatedReason, dk.Status.Conditions[0].Reason) + assert.Equal(t, metav1.ConditionTrue, dk.Status.Conditions[0].Status) + + // update + dk.Spec.TelemetryService = &telemetryservice.Spec{ + ServiceName: testServiceName, + } + err = NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + service = &corev1.Service{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err)) + + assert.Empty(t, dk.Status.Conditions) + }) +} diff --git a/pkg/util/kubeobjects/labels/labels.go b/pkg/util/kubeobjects/labels/labels.go index 0ac2bee445..29e76e16f7 100644 --- a/pkg/util/kubeobjects/labels/labels.go +++ b/pkg/util/kubeobjects/labels/labels.go @@ -22,6 +22,7 @@ const ( EdgeConnectComponentLabel = "edgeconnect" ExtensionComponentLabel = "dynatrace-extensions-controller" CollectorComponentLabel = "dynatrace-extensions-collector" + OtelCComponentLabel = "dynatrace-otelc-controller" ) type AppMatchLabels struct { diff --git a/pkg/util/kubeobjects/service/builder.go b/pkg/util/kubeobjects/service/builder.go index 947d63beae..45785ab63c 100644 --- a/pkg/util/kubeobjects/service/builder.go +++ b/pkg/util/kubeobjects/service/builder.go @@ -15,7 +15,7 @@ var ( SetLabels = builder.SetLabels[*corev1.Service] ) -func Build(owner metav1.Object, name string, selectorLabels map[string]string, svcPort corev1.ServicePort, options ...builder.Option[*corev1.Service]) (*corev1.Service, error) { +func Build(owner metav1.Object, name string, selectorLabels map[string]string, svcPort []corev1.ServicePort, options ...builder.Option[*corev1.Service]) (*corev1.Service, error) { neededOpts := []builder.Option[*corev1.Service]{ setName(name), setPorts(svcPort), @@ -27,25 +27,9 @@ func Build(owner metav1.Object, name string, selectorLabels map[string]string, s return builder.Build(owner, &corev1.Service{}, neededOpts...) } -func setPorts(svcPort corev1.ServicePort) builder.Option[*corev1.Service] { +func setPorts(svcPorts []corev1.ServicePort) builder.Option[*corev1.Service] { return func(s *corev1.Service) { - targetIndex := 0 - for index := range s.Spec.Ports { - if s.Spec.Ports[targetIndex].Name == svcPort.Name { - targetIndex = index - - break - } - } - - if targetIndex == 0 { - s.Spec.Ports = make([]corev1.ServicePort, 1) - } - - s.Spec.Ports[targetIndex].Name = svcPort.Name - s.Spec.Ports[targetIndex].Port = svcPort.Port - s.Spec.Ports[targetIndex].Protocol = svcPort.Protocol - s.Spec.Ports[targetIndex].TargetPort = svcPort.TargetPort + s.Spec.Ports = svcPorts } } diff --git a/pkg/util/kubeobjects/service/builder_test.go b/pkg/util/kubeobjects/service/builder_test.go index 6d804d4fae..37e192b425 100644 --- a/pkg/util/kubeobjects/service/builder_test.go +++ b/pkg/util/kubeobjects/service/builder_test.go @@ -6,7 +6,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -35,7 +34,7 @@ func TestServiceBuilder(t *testing.T) { service, err := Build(createDeployment(), testServiceName, labels, - corev1.ServicePort{}, + nil, setNamespace(testNamespace)) require.NoError(t, err) require.Len(t, service.OwnerReferences, 1) @@ -47,7 +46,7 @@ func TestServiceBuilder(t *testing.T) { secret, err := Build(createDeployment(), testServiceName, labels, - corev1.ServicePort{}, + nil, SetLabels(labels), setNamespace(testNamespace), ) From f37dbdf0ec680fa0870e9f3d243b79cc6576f815 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 13:17:59 +0100 Subject: [PATCH 155/426] chore(deps): update actions/setup-python action to v5.4.0 (main) (#4365) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/self-update-on-new-release-version.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/self-update-on-new-release-version.yaml b/.github/workflows/self-update-on-new-release-version.yaml index ceb3d3f7d4..8cdae74ed0 100644 --- a/.github/workflows/self-update-on-new-release-version.yaml +++ b/.github/workflows/self-update-on-new-release-version.yaml @@ -17,7 +17,7 @@ jobs: with: ref: main - name: Install Python - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 with: python-version: '3.12' - name: Install python requirements From b43a149ffe8c5d35b8b2537b4bb37c29fdc37945 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Tue, 28 Jan 2025 13:36:08 +0100 Subject: [PATCH 156/426] Fix OneAgent command line arguments (#4357) (#4368) --- .../dynakube/oneagent/daemonset/arguments.go | 4 +- .../oneagent/daemonset/arguments_test.go | 33 +++-- .../oneagent/daemonset/daemonset_test.go | 5 +- pkg/util/prioritymap/map.go | 32 ++++- pkg/util/prioritymap/map_test.go | 129 ++++++++++++++++++ 5 files changed, 188 insertions(+), 15 deletions(-) diff --git a/pkg/controllers/dynakube/oneagent/daemonset/arguments.go b/pkg/controllers/dynakube/oneagent/daemonset/arguments.go index 11e11467a2..4971298b52 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/arguments.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/arguments.go @@ -18,7 +18,9 @@ func (b *builder) arguments() ([]string, error) { argMap := prioritymap.New( prioritymap.WithSeparator(prioritymap.DefaultSeparator), prioritymap.WithPriority(defaultArgumentPriority), - prioritymap.WithAllowDuplicates(), + prioritymap.WithAvoidDuplicates(), + prioritymap.WithAllowDuplicatesFor("--set-host-property"), + prioritymap.WithAllowDuplicatesFor("--set-host-tag"), ) isProxyAsEnvDeprecated, err := isProxyAsEnvVarDeprecated(b.dk.OneAgent().GetVersion()) diff --git a/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go b/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go index e74a69e525..677e3bf4bd 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go @@ -88,16 +88,29 @@ func TestArguments(t *testing.T) { } assert.Equal(t, expectedDefaultArguments, arguments) }) - t.Run("when injected arguments are provided then they come last", func(t *testing.T) { - args := []string{ + t.Run("when injected arguments are provided then they come last, only allowed duplicates and no duplicate key/value pairs", func(t *testing.T) { + custArgs := []string{ "--set-app-log-content-access=true", - "--set-host-id-source=lustiglustig", + "--set-host-id-source=fqdn", "--set-host-group=APP_LUSTIG_PETER", "--set-server=https://hyper.super.com:9999", + "--set-host-property=prop1", + "--set-host-property=prop1", + "--set-host-property=prop1", + "--set-host-property=prop2", + "--set-host-property=prop2", + "--set-host-property=prop3", + "--set-host-property=prop3", + "--set-host-property=prop3", + "--set-host-tag=tag1", + "--set-host-tag=tag2", + "--set-host-tag=tag2", + "--set-host-tag=tag2", + "--set-host-tag=tag3", } builder := builder{ - dk: &dynakube.DynaKube{}, - hostInjectSpec: &oneagent.HostInjectSpec{Args: args}, + dk: &dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{ClassicFullStack: &oneagent.HostInjectSpec{}}}}, + hostInjectSpec: &oneagent.HostInjectSpec{Args: custArgs}, } arguments, _ := builder.arguments() @@ -105,11 +118,16 @@ func TestArguments(t *testing.T) { expectedDefaultArguments := []string{ "--set-app-log-content-access=true", "--set-host-group=APP_LUSTIG_PETER", - "--set-host-id-source=lustiglustig", + "--set-host-id-source=fqdn", "--set-host-property=OperatorVersion=$(DT_OPERATOR_VERSION)", + "--set-host-property=prop1", + "--set-host-property=prop2", + "--set-host-property=prop3", + "--set-host-tag=tag1", + "--set-host-tag=tag2", + "--set-host-tag=tag3", "--set-no-proxy=", "--set-proxy=", - "--set-server={$(DT_SERVER)}", "--set-server=https://hyper.super.com:9999", "--set-tenant=$(DT_TENANT)", } @@ -217,7 +235,6 @@ func TestArguments(t *testing.T) { "--set-host-property=item2=value2", "--set-no-proxy=", "--set-proxy=", - "--set-server={$(DT_SERVER)}", "--set-server=https://hyper.super.com:9999", "--set-tenant=$(DT_TENANT)", } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go index 204a66c916..c9607cfa37 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go @@ -921,7 +921,7 @@ func TestOneAgentHostGroup(t *testing.T) { require.NoError(t, err) require.NotNil(t, daemonset) - assert.Equal(t, "--set-host-group=newgroup", daemonset.Spec.Template.Spec.Containers[0].Args[1]) + assert.Equal(t, "--set-host-group=newgroup", daemonset.Spec.Template.Spec.Containers[0].Args[0]) }) } @@ -965,12 +965,10 @@ func TestDefaultArguments(t *testing.T) { expectedDefaultArguments := []string{ "--set-app-log-content-access=true", "--set-host-group=APP_LUSTIG_PETER", - "--set-host-id-source=auto", "--set-host-id-source=fqdn", "--set-host-property=OperatorVersion=$(DT_OPERATOR_VERSION)", "--set-no-proxy=", "--set-proxy=", - "--set-server={$(DT_SERVER)}", "--set-server=https://hyper.super.com:9999", "--set-tenant=$(DT_TENANT)", } @@ -996,7 +994,6 @@ func TestDefaultArguments(t *testing.T) { "--set-host-property=OperatorVersion=$(DT_OPERATOR_VERSION)", "--set-no-proxy=", "--set-proxy=", - "--set-server={$(DT_SERVER)}", "--set-server=https://hyper.super.com:9999", "--set-tenant=$(DT_TENANT)", } diff --git a/pkg/util/prioritymap/map.go b/pkg/util/prioritymap/map.go index 484ccbb281..49fe92956f 100644 --- a/pkg/util/prioritymap/map.go +++ b/pkg/util/prioritymap/map.go @@ -1,6 +1,7 @@ package prioritymap import ( + "slices" "strings" corev1 "k8s.io/api/core/v1" @@ -18,6 +19,7 @@ type Map struct { type entry struct { value any + key string delimiter string priority int allowDuplicates bool @@ -37,13 +39,34 @@ func WithSeparator(separator string) Option { } } -// WithAllowDuplicatesForKey allows to add multiple values for the same key (covers all keys) func WithAllowDuplicates() Option { return func(a *entry) { a.allowDuplicates = true } } +func WithAvoidDuplicates() Option { + return func(a *entry) { + a.allowDuplicates = false + } +} + +func WithAvoidDuplicatesFor(key string) Option { + return func(a *entry) { + if a.key == key { + a.allowDuplicates = false + } + } +} + +func WithAllowDuplicatesFor(key string) Option { + return func(a *entry) { + if a.key == key { + a.allowDuplicates = true + } + } +} + func New(defaultOptions ...Option) *Map { m := &Map{ entries: make(map[string][]entry), @@ -59,6 +82,7 @@ func (m Map) Append(key string, value any, opts ...Option) { } newArg := entry{ + key: key, value: value, priority: DefaultPriority, allowDuplicates: false, @@ -79,7 +103,11 @@ func (m Map) Append(key string, value any, opts ...Option) { m.entries[key] = make([]entry, 0) } - m.entries[key] = append(m.entries[key], newArg) + if !slices.ContainsFunc(m.entries[key], func(e entry) bool { + return e.value == value + }) { + m.entries[key] = append(m.entries[key], newArg) + } } } diff --git a/pkg/util/prioritymap/map_test.go b/pkg/util/prioritymap/map_test.go index e26c94cea8..68e8780ce6 100644 --- a/pkg/util/prioritymap/map_test.go +++ b/pkg/util/prioritymap/map_test.go @@ -158,3 +158,132 @@ func TestArgumentSlice(t *testing.T) { assert.Equal(t, expectedArgs, argMap.AsKeyValueStrings()) } + +func TestDuplicateArguments(t *testing.T) { + defaultArgs := []string{ + "--set-proxy=127.0.0.1", + "--set-host-id-source=auto", + "--set-server=localhost", + "--set-host-property=prop1", + "--set-host-property=prop2", + "--set-host-property=prop3", + "--set-host-property=prop3", + "--set-host-property=prop3", + } + + customArgs := []string{ + "--set-host-id-source=fqdn", + "--set-server=foobar.com", + "--set-host-property=custom-prop1", + "--set-host-property=custom-prop2", + "--set-host-property=custom-prop3", + "--set-host-property=custom-prop3", + "--set-host-property=custom-prop3", + } + + var tests = []struct { + title string + expectedArgs []string + defaultArgPrio int + customArgsPrio int + mapOptions []Option + }{ + { + title: "Enter avoided duplicates with higher prio", + expectedArgs: []string{ + "--set-host-id-source=fqdn", + "--set-host-property=prop1", + "--set-host-property=prop2", + "--set-host-property=prop3", + "--set-host-property=custom-prop1", + "--set-host-property=custom-prop2", + "--set-host-property=custom-prop3", + "--set-proxy=127.0.0.1", + "--set-server=foobar.com", + }, + defaultArgPrio: DefaultPriority, + customArgsPrio: HighPriority, + mapOptions: []Option{ + WithSeparator("="), + WithAllowDuplicates(), + WithAvoidDuplicatesFor("--set-host-id-source"), + WithAvoidDuplicatesFor("--set-server"), + }, + }, + { + title: "Enter avoided duplicates with lower prio", + expectedArgs: []string{ + "--set-host-id-source=auto", + "--set-host-property=custom-prop1", + "--set-host-property=custom-prop2", + "--set-host-property=custom-prop3", + "--set-host-property=prop1", + "--set-host-property=prop2", + "--set-host-property=prop3", + "--set-proxy=127.0.0.1", + "--set-server=localhost", + }, + defaultArgPrio: HighPriority, + customArgsPrio: DefaultPriority, + mapOptions: []Option{ + WithSeparator("="), + WithAllowDuplicates(), + WithAvoidDuplicatesFor("--set-host-id-source"), + WithAvoidDuplicatesFor("--set-server"), + }, + }, + { + title: "Enter avoided duplicates with higher prio", + expectedArgs: []string{ + "--set-host-id-source=fqdn", + "--set-host-property=prop1", + "--set-host-property=prop2", + "--set-host-property=prop3", + "--set-host-property=custom-prop1", + "--set-host-property=custom-prop2", + "--set-host-property=custom-prop3", + "--set-proxy=127.0.0.1", + "--set-server=foobar.com", + }, + defaultArgPrio: DefaultPriority, + customArgsPrio: HighPriority, + mapOptions: []Option{ + WithSeparator("="), + WithAvoidDuplicates(), + WithAllowDuplicatesFor("--set-host-property"), + }, + }, + { + title: "Enter avoided duplicates with lower prio", + expectedArgs: []string{ + "--set-host-id-source=auto", + "--set-host-property=custom-prop1", + "--set-host-property=custom-prop2", + "--set-host-property=custom-prop3", + "--set-host-property=prop1", + "--set-host-property=prop2", + "--set-host-property=prop3", + "--set-proxy=127.0.0.1", + "--set-server=localhost", + }, + defaultArgPrio: HighPriority, + customArgsPrio: DefaultPriority, + mapOptions: []Option{ + WithSeparator("="), + WithAvoidDuplicates(), + WithAllowDuplicatesFor("--set-host-property"), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.title, func(t *testing.T) { + argMap := New(tt.mapOptions...) + + Append(argMap, defaultArgs, WithPriority(tt.defaultArgPrio)) + Append(argMap, customArgs, WithPriority(tt.customArgsPrio)) + + assert.Equal(t, tt.expectedArgs, argMap.AsKeyValueStrings()) + }) + } +} From 385b1cb3af96a31e3c985c79dc79052dd8f3ba33 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Jan 2025 00:35:28 +0000 Subject: [PATCH 157/426] fix(deps): update module github.com/evanphx/json-patch to v5.9.11+incompatible (main) (#4378) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 674a97bb4b..562ce81f52 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.3 require ( github.com/container-storage-interface/spec v1.11.0 github.com/docker/cli v27.5.1+incompatible - github.com/evanphx/json-patch v5.9.10+incompatible + github.com/evanphx/json-patch v5.9.11+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.3 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index f926eea413..b86e182005 100644 --- a/go.sum +++ b/go.sum @@ -22,8 +22,8 @@ github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZ github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch v5.9.10+incompatible h1:f9RK4b5sgikwA7D5BkGR9oz69KM7riR/0qaNoBzmJso= -github.com/evanphx/json-patch v5.9.10+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= +github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= From 5b6dcc009e5dbc98f5bb76befea3d4335b7cd959 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Wed, 29 Jan 2025 11:19:40 +0100 Subject: [PATCH 158/426] Fix resilience e2e test (#4383) --- test/features/cloudnative/network_problems/network_problems.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/features/cloudnative/network_problems/network_problems.go b/test/features/cloudnative/network_problems/network_problems.go index 15abd79ce6..146e329e78 100644 --- a/test/features/cloudnative/network_problems/network_problems.go +++ b/test/features/cloudnative/network_problems/network_problems.go @@ -56,7 +56,7 @@ func ResilienceFeature(t *testing.T) features.Feature { dynakube.WithApiUrl(secretConfig.ApiUrl), dynakube.WithCloudNativeSpec(cloudnative.DefaultCloudNativeSpec()), dynakube.WithAnnotations(map[string]string{ - "feature.dynatrace.com/max-csi-mount-attempts": "2", + "feature.dynatrace.com/max-csi-mount-timeout": "1m", }), ) From ad93f671e4302915802eed99d1ab66d5a35104c4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Jan 2025 14:50:46 +0000 Subject: [PATCH 159/426] chore(deps): update github/codeql-action action to v3.28.7 (main) (#4384) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 00f427fc1b..d01e4a7f41 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 + uses: github/codeql-action/init@6e5455904168f98c75d8e5ad848b4dc4ab3ae77e # v3.28.7 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 + uses: github/codeql-action/autobuild@6e5455904168f98c75d8e5ad848b4dc4ab3ae77e # v3.28.7 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 + uses: github/codeql-action/analyze@6e5455904168f98c75d8e5ad848b4dc4ab3ae77e # v3.28.7 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 41d0eacaa1..160a04ca8d 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 + uses: github/codeql-action/upload-sarif@6e5455904168f98c75d8e5ad848b4dc4ab3ae77e # v3.28.7 with: sarif_file: results.sarif From 470bf298ffd0a017c02b6715610961aaa5dc5724 Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Wed, 29 Jan 2025 18:47:15 +0100 Subject: [PATCH 160/426] Add debug messages to CSI identity services handlers (main branch) (#4355) Co-authored-by: Andrii Soldatenko --- pkg/controllers/csi/driver/server.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/controllers/csi/driver/server.go b/pkg/controllers/csi/driver/server.go index 38e0833d05..a43287a852 100644 --- a/pkg/controllers/csi/driver/server.go +++ b/pkg/controllers/csi/driver/server.go @@ -291,6 +291,8 @@ func grpcLimiter(maxGrpcRequests int32) grpc.UnaryServerInterceptor { methodName = "NodeUnpublishVolume" log.Info("GRPC call", "method", methodName, "volume-id", req.GetVolumeId()) default: + log.Debug("GRPC call", "full_method", info.FullMethod) + resp, err := handler(ctx, req) if err != nil { log.Error(err, "GRPC failed", "full_method", info.FullMethod) From 8e41e10d154802aec3501d7795650ec3d88ac773 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Jan 2025 01:58:59 +0000 Subject: [PATCH 161/426] chore(deps): update github/codeql-action action to v3.28.8 (main) (#4385) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index d01e4a7f41..b6e245f0e4 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@6e5455904168f98c75d8e5ad848b4dc4ab3ae77e # v3.28.7 + uses: github/codeql-action/init@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@6e5455904168f98c75d8e5ad848b4dc4ab3ae77e # v3.28.7 + uses: github/codeql-action/autobuild@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6e5455904168f98c75d8e5ad848b4dc4ab3ae77e # v3.28.7 + uses: github/codeql-action/analyze@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 160a04ca8d..1a8292d636 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@6e5455904168f98c75d8e5ad848b4dc4ab3ae77e # v3.28.7 + uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 with: sarif_file: results.sarif From 102ddf812f2e0ba607fdafe8fb41754a60615f56 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Fri, 31 Jan 2025 10:44:14 +0100 Subject: [PATCH 162/426] Add validations for OneAgent arguments (release-1.4) (#4377) (#4388) --- pkg/api/v1beta3/dynakube/oneagent/props.go | 37 +++- pkg/api/validation/dynakube/oneagent.go | 57 ++++++ pkg/api/validation/dynakube/oneagent_test.go | 181 +++++++++++++++++++ pkg/api/validation/dynakube/validation.go | 2 + 4 files changed, 269 insertions(+), 8 deletions(-) diff --git a/pkg/api/v1beta3/dynakube/oneagent/props.go b/pkg/api/v1beta3/dynakube/oneagent/props.go index 38bac7ca34..59b0037c99 100644 --- a/pkg/api/v1beta3/dynakube/oneagent/props.go +++ b/pkg/api/v1beta3/dynakube/oneagent/props.go @@ -222,20 +222,24 @@ func (oa *OneAgent) GetHostGroup() string { return oa.GetHostGroupAsParam() } -func (oa *OneAgent) GetHostGroupAsParam() string { - var hostGroup string - - var args []string - +func (oa *OneAgent) GetArguments() []string { switch { case oa.IsCloudNativeFullstackMode() && oa.CloudNativeFullStack.Args != nil: - args = oa.CloudNativeFullStack.Args + return oa.CloudNativeFullStack.Args case oa.IsClassicFullStackMode() && oa.ClassicFullStack.Args != nil: - args = oa.ClassicFullStack.Args + return oa.ClassicFullStack.Args case oa.IsHostMonitoringMode() && oa.HostMonitoring.Args != nil: - args = oa.HostMonitoring.Args + return oa.HostMonitoring.Args } + return []string{} +} + +func (oa *OneAgent) GetHostGroupAsParam() string { + var hostGroup string + + args := oa.GetArguments() + for _, arg := range args { key, value := splitArg(arg) if key == "--set-host-group" { @@ -310,3 +314,20 @@ func (oa *OneAgent) GetCodeModulesVersion() string { func (oa *OneAgent) GetCodeModulesImage() string { return oa.CodeModulesStatus.ImageID } + +func (oa *OneAgent) GetArgumentsMap() map[string][]string { + args := oa.GetArguments() + + argMap := make(map[string][]string) + + for _, arg := range args { + key, value := splitArg(arg) + if _, exists := argMap[key]; !exists { + argMap[key] = []string{value} + } else { + argMap[key] = append(argMap[key], value) + } + } + + return argMap +} diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index dda3acb6f5..8c67f0adfc 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "regexp" + "slices" "strings" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" @@ -30,6 +31,12 @@ Use a nodeSelector to avoid this conflict. Conflicting DynaKubes: %s` versionRegex = `^\d+.\d+.\d+.\d{8}-\d{6}$` versionInvalidMessage = "The OneAgent's version is only valid in the format 'major.minor.patch.timestamp', e.g. 1.0.0.20240101-000000" + + errorDuplicateOneAgentArgument = "%s has been provided multiple times. Only --set-host-property and --set-host-tag arguments may be provided multiple times." + + errorHostIdSourceArgumentInCloudNative = "Setting --set-host-id-source in CloudNativFullstack mode is not allowed." + + errorSameHostTagMultipleTimes = "Providing the same tag(s) (%s) multiple times with --set-host-tag is not allowed." ) func conflictingOneAgentConfiguration(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { @@ -193,3 +200,53 @@ func isOneAgentVersionValid(_ context.Context, _ *Validator, dk *dynakube.DynaKu return "" } + +func duplicateOneAgentArguments(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + args := dk.OneAgent().GetArgumentsMap() + if args == nil { + return "" + } + + for key, values := range args { + if key != "--set-host-property" && key != "--set-host-tag" && len(values) > 1 { + return fmt.Sprintf(errorDuplicateOneAgentArgument, key) + } else if key == "--set-host-tag" { + if duplicatedTags := findDuplicates(values); len(duplicatedTags) > 0 { + return fmt.Sprintf(errorSameHostTagMultipleTimes, duplicatedTags) + } + } + } + + return "" +} + +func forbiddenHostIdSourceArgument(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + args := dk.OneAgent().GetArgumentsMap() + if args == nil { + return "" + } + + for key := range args { + if dk.OneAgent().IsCloudNativeFullstackMode() && key == "--set-host-id-source" { + return errorHostIdSourceArgumentInCloudNative + } + } + + return "" +} + +func findDuplicates[S ~[]E, E comparable](s S) []E { + seen := make(map[E]bool) + + duplicates := make([]E, 0) + + for _, val := range s { + if _, ok := seen[val]; !ok { + seen[val] = true + } else if !slices.Contains(duplicates, val) { + duplicates = append(duplicates, val) + } + } + + return duplicates +} diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index 0eb60c6084..47057cbac2 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -491,3 +491,184 @@ func TestIsOneAgentVersionValid(t *testing.T) { }) } } + +func TestOneAgentArguments(t *testing.T) { + type oneAgentArgumentTest struct { + testName string + arguments []string + expectedError string + } + + testcases := []oneAgentArgumentTest{ + { + testName: "duplicate arguments are rejected", + arguments: []string{ + "--set-server=foo", + "--set-server=bar", + }, + expectedError: fmt.Sprintf(errorDuplicateOneAgentArgument, "--set-server"), + }, + { + testName: "duplicate arguments with same value are rejected", + arguments: []string{ + "--set-server=foo", + "--set-server=foo", + }, + expectedError: fmt.Sprintf(errorDuplicateOneAgentArgument, "--set-server"), + }, + { + testName: "no duplicate arguments", + arguments: []string{ + "--set-server=foo", + "--set-host-source-id=bar", + }, + expectedError: "", + }, + { + testName: "duplicate host property", + arguments: []string{ + "--set-server=foo", + "--set-host-property=foo", + "--set-host-property=bar", + "--set-host-property=dow", + }, + expectedError: "", + }, + { + testName: "duplicate host tag", + arguments: []string{ + "--set-server=foo", + "--set-host-tag=foo", + "--set-host-tag=bar", + "--set-host-tag=dow", + }, + expectedError: "", + }, + { + testName: "duplicate host tag with same value", + arguments: []string{ + "--set-host-tag=foo", + "--set-host-tag=bar", + "--set-host-tag=foo", + "--set-host-tag=bar", + "--set-host-tag=doh", + "--set-host-tag=bar", + "--set-host-tag=foo", + }, + expectedError: fmt.Sprintf(errorSameHostTagMultipleTimes, "[foo bar]"), + }, + } + + for _, tc := range testcases { + t.Run(tc.testName, func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dynakube", + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ + Args: tc.arguments, + }, + }, + }, + }, + } + if tc.expectedError == "" { + assertAllowedWithoutWarnings(t, dk) + } else { + assertDenied(t, []string{tc.expectedError}, dk) + } + }) + } +} + +func TestNoHostIdSourceArgument(t *testing.T) { + type oneAgentArgumentTest struct { + testName string + dk dynakube.DynaKube + expectedError string + } + + testcases := []oneAgentArgumentTest{ + { + testName: "host id source argument in cloud native full stack", + dk: dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dynakube", + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ + Args: []string{ + "--set-server=foo", + "--set-host-id-source=foo", + }, + }, + }, + }, + }, + }, + expectedError: errorHostIdSourceArgumentInCloudNative, + }, + { + testName: "no host id source argument in cloud native full stack", + dk: dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dynakube", + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + HostInjectSpec: oneagent.HostInjectSpec{ + Args: []string{ + "--set-server=foo", + }, + }, + }, + }, + }, + }, + expectedError: "", + }, + { + testName: "host id source argument in host monitoring stack", + dk: dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dynakube", + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ + Args: []string{ + "--set-server=foo", + "--set-host-id-source=foo", + }, + }, + }, + }, + }, + expectedError: "", + }, + } + + for _, tc := range testcases { + t.Run(tc.testName, func(t *testing.T) { + if tc.expectedError == "" { + assertAllowedWithoutWarnings(t, &tc.dk) + } else { + assertDenied(t, []string{tc.expectedError}, &tc.dk) + } + }) + } +} diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 2497e846e8..bd2d3201e0 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -30,6 +30,8 @@ var ( isKSPMDisabled, isOneAgentModuleDisabled, isOneAgentVersionValid, + duplicateOneAgentArguments, + forbiddenHostIdSourceArgument, NoApiUrl, IsInvalidApiUrl, IsThirdGenAPIUrl, From 3426257ced8f24c114aa4c52cb40b54f78cd5237 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Fri, 31 Jan 2025 10:54:52 +0100 Subject: [PATCH 163/426] follow up: rename SA for extensions to dynatrace-opentelemetry-collector (#4387) --- pkg/controllers/dynakube/otelc/statefulset/reconciler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go index 720dee14aa..273e6ee6be 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go @@ -20,7 +20,7 @@ import ( ) const ( - serviceAccountName = "dynatrace-extensions-collector" + serviceAccountName = "dynatrace-opentelemetry-collector" ) type Reconciler struct { From c7eda801df44fab5ff2dc16408dd105222863042 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Feb 2025 04:52:51 +0000 Subject: [PATCH 164/426] chore(deps): update module github.com/vektra/mockery to v2.52.1 (main) (#4389) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 51dcda393e..e2613ec20b 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.29.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.51.1 +mockery_version=v2.52.1 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest From db6a50e77ea1ed8a71987a7d74aff3e3bfdcf669 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Mon, 3 Feb 2025 15:24:50 +0100 Subject: [PATCH 165/426] misleading declaration of healthz port between server and liveness-probe (#4390) --- .../helm/chart/default/templates/Common/csi/daemonset.yaml | 5 +++-- .../helm/chart/default/tests/Common/csi/daemonset_test.yaml | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/config/helm/chart/default/templates/Common/csi/daemonset.yaml b/config/helm/chart/default/templates/Common/csi/daemonset.yaml index 7ec83f1f02..605b0ffb27 100644 --- a/config/helm/chart/default/templates/Common/csi/daemonset.yaml +++ b/config/helm/chart/default/templates/Common/csi/daemonset.yaml @@ -120,8 +120,6 @@ spec: timeoutSeconds: 4 {{- end }} ports: - - containerPort: 9808 - name: healthz - containerPort: 8080 name: metrics resources: @@ -246,6 +244,9 @@ spec: - --probe-timeout=4s command: - livenessprobe + ports: + - name: healthz + containerPort: 9808 resources: {{- if .Values.csidriver.livenessprobe.resources }} {{- toYaml .Values.csidriver.livenessprobe.resources | nindent 10 }} diff --git a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml index 35c0205547..7e7572186c 100644 --- a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml @@ -193,8 +193,6 @@ tests: timeoutSeconds: 4 name: server ports: - - containerPort: 9808 - name: healthz - containerPort: 8080 name: metrics resources: @@ -339,6 +337,9 @@ tests: - "--probe-timeout=4s" command: - livenessprobe + ports: + - containerPort: 9808 + name: healthz image: image-name imagePullPolicy: Always name: liveness-probe From f65822d4650f50e785663ba036c92a8a4ca582eb Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:48:00 +0100 Subject: [PATCH 166/426] Create new ActiveGate and Proxy custom TLS certificates (#4391) --- test/testdata/custom-cas/README.md | 35 ++++++++++++++ test/testdata/custom-cas/ag.ext | 7 +++ test/testdata/custom-cas/agcrt.pem | 66 +++++++++++++------------- test/testdata/custom-cas/agcrtkey.p12 | Bin 3555 -> 3571 bytes test/testdata/custom-cas/custom.pem | 47 +++++++++++------- test/testdata/network/proxy-ssl.yaml | 2 +- 6 files changed, 105 insertions(+), 52 deletions(-) create mode 100644 test/testdata/custom-cas/README.md create mode 100644 test/testdata/custom-cas/ag.ext diff --git a/test/testdata/custom-cas/README.md b/test/testdata/custom-cas/README.md new file mode 100644 index 0000000000..03975c19f0 --- /dev/null +++ b/test/testdata/custom-cas/README.md @@ -0,0 +1,35 @@ +## Create Squid proxy certificate + +> openssl req -nodes -x509 -newkey rsa:4096 -keyout spkey.pem -out custom.pem -days 365 -subj "/CN=squid.proxy" -addext="subjectAltName=DNS:squid.proxy,DNS:squid.proxy.svc,DNS:squid.proxy.svc.cluster.local" -addext="basicConstraints=CA:TRUE" +> +> cat custom.pem spkey.pem | base64 -w0 + +(!) Copy encoded files to proxy-ssl.yaml:squid-ca-cert.pem field. + +## Create ActiveGate TLS certificate + +create a private key +> openssl genrsa -out agkey.pem 2048 + +create a certificate signing request +> openssl req -key agkey.pem -new -out ag.csr -subj '/CN=dynakube-activegate.dynatrace' + +create a self-signed root CA +> openssl req -x509 -nodes -sha256 -days 1825 -newkey rsa:2048 -keyout root.pem -out root.crt -subj '/CN=dynakube-activegate.issuer' + +sign certificate signing request with root CA +> openssl x509 -req -CA root.crt -CAkey root.pem -in ag.csr -out agcrt.pem -days 365 -CAcreateserial -extfile ag.ext + +convert to p12 +> openssl pkcs12 -export -out agcrtkey.p12 -inkey agkey.pem -in agcrt.pem -certfile root.crt + +append root certificate to agcrt.pem +> cat root.crt >> agcrt.pem + +(!) Use empty password. + +## Print the certificate in text form + +> openssl x509 -text -noout -in agcrt.pem +> +> openssl pkcs12 -info -in agcrtkey.p12 -nodes diff --git a/test/testdata/custom-cas/ag.ext b/test/testdata/custom-cas/ag.ext new file mode 100644 index 0000000000..36a87ec5c7 --- /dev/null +++ b/test/testdata/custom-cas/ag.ext @@ -0,0 +1,7 @@ +authorityKeyIdentifier=keyid,issuer +basicConstraints=CA:FALSE +subjectAltName = @alt_names +[alt_names] +DNS.1 = dynakube-activegate.dynatrace +DNS.2 = dynakube-activegate.dynatrace.svc +DNS.3 = dynakube-activegate.dynatrace.svc.cluster.local diff --git a/test/testdata/custom-cas/agcrt.pem b/test/testdata/custom-cas/agcrt.pem index 2e5bf5676b..66bc0c2b0b 100644 --- a/test/testdata/custom-cas/agcrt.pem +++ b/test/testdata/custom-cas/agcrt.pem @@ -1,41 +1,41 @@ -----BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIUTrMdIL1V6mZCfDVzJB36N9Kb/vowDQYJKoZIhvcNAQEL -BQAwJTEjMCEGA1UEAwwaZHluYWt1YmUtYWN0aXZlZ2F0ZS5pc3N1ZXIwHhcNMjQw -MjAzMTYxODM2WhcNMjUwMjAyMTYxODM2WjAoMSYwJAYDVQQDDB1keW5ha3ViZS1h +MIIDqDCCApCgAwIBAgIUXLu0L1BM5PpWjDDFmeNFK+3cEV8wDQYJKoZIhvcNAQEL +BQAwJTEjMCEGA1UEAwwaZHluYWt1YmUtYWN0aXZlZ2F0ZS5pc3N1ZXIwHhcNMjUw +MjAzMDk1OTU4WhcNMjYwMjAzMDk1OTU4WjAoMSYwJAYDVQQDDB1keW5ha3ViZS1h Y3RpdmVnYXRlLmR5bmF0cmFjZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAKiO7ZPq2axVnyXwqerhv3WsRt+GVd4mttvjFuJXoD7b/KuuXypQJbPLnEW0 -Gob0YOzmLyvppfraT+vynHhJjzniEXj6dVuPeUEgoU/8nbRG09lh+E1/IPfgANNx -Sj0emK++3vIE65bFULQ89FFJPfvSAeqjtfl0FczQMzc2COp3iQL+7ZO7Ug/wfWP7 -raVVDsra926IjSlEm7mFN0cKeKjZA91DEJID0Ge50YZ6ZCm1BZGa76mqCmHFmsdY -TpfbMDoWCInc7bY/M6nS3tNQC/cH0QhDoOLAzHj5hO5+Vy3hOXDVstI7JfwCVwyo -29DOzHCGqigYnxv3jHWehk8tPNcCAwEAAaOBzDCByTAfBgNVHSMEGDAWgBSqrFPU -fx0iICfVB9dzmKX/CHqvqzAJBgNVHRMEAjAAMHwGA1UdEQR1MHOCHWR5bmFrdWJl +ggEBAL7HE20SHjkWIiYpNt0QC0v3YS31skD/z1eAWlQZJazIhQOSkcmU5RJShzkJ +oYZPc1zt0WQIUAd1EBFuM7Tc55YBIC9a/PySpvtALMvF11GMt6bRSagUrw5dvJ+T +odUoxhWgveIzRG0f7sPjny0/McFOcRw5cNDr518tZKDm9X0/2yV7Y0RLXKNIRwEv +6pQQl9XXAQ16NxmOAvArdm2LLvLfwrUPNG/XjtOiICmdesWHg6hTMYKXhSkhQYZC +mE9nvMi7fJMWeZFWIZnHSSFThAy5O73yZZ6S0Il+JnvpSf74a8Qh90Rab3nQL6Yj +4aHwWJCVmvP6hEOjJp3UkK75MrUCAwEAAaOBzDCByTAfBgNVHSMEGDAWgBSVn1nI +X+9ryJ9jZwCslweq6OPLZDAJBgNVHRMEAjAAMHwGA1UdEQR1MHOCHWR5bmFrdWJl LWFjdGl2ZWdhdGUuZHluYXRyYWNlgiFkeW5ha3ViZS1hY3RpdmVnYXRlLmR5bmF0 cmFjZS5zdmOCL2R5bmFrdWJlLWFjdGl2ZWdhdGUuZHluYXRyYWNlLnN2Yy5jbHVz -dGVyLmxvY2FsMB0GA1UdDgQWBBSVTtZcoy6Xk65m5qqTSCfK2isTcTANBgkqhkiG -9w0BAQsFAAOCAQEAduSHuFzyxPc2iptS3Zoq82SafgBj/rxdM2CgPdn6nKdtKbot -f0+laaMIoJ0wVxz3jClqMiCPK/l4AFV79bhQwaVRxR8Jp8ebDfKs7WJfxrcoLXvf -TgjyLmBGx/3ucAGh3CY7gelPUXLyzV6R4siWWzu/6Ln8fBwJDwqMDQShZHIkSXXz -xr366z5taXBvIjnwgBW0QXTm09b76PRTMbkM1WYIO54EAjW00xhclzVnn0xwseG2 -fLD9cFcleOovFczlqgVIf2HBe8E+g8WICSW8aeC3CgvpuUtCQZQ1Ha6kEWHc1jop -nWWvK79XYJjoxHnFchyNkcHHRDeujw9rN9P4fg== +dGVyLmxvY2FsMB0GA1UdDgQWBBQWFNPIq2M4ysrDoNXKl/NIPNJR+DANBgkqhkiG +9w0BAQsFAAOCAQEABYm45MXQ20TVWha4dfQxfZ5WCo4IDWNjR/ND/eaRUA704TG/ +u1pV2jflclIvfDw9B55u0bH4b5ZCx57oMPOQpvXgLI2qUONpfLqdmg9hTiGd+P7U +wtm+hOfmCg1YSpVLOdmXF9sglRIUJO9jX7CiFZ1MvFxCYxXkHccBswoSgSTBzhrY +tLAyEpwgh2YwLVSsq+iBXv6tAI3po9Hpr1d266nMQ9J0ry2aiKR8Id0FKhV9LmZl +bCKYedOUqpPgOQ/j3eN+SrH+tI2a6RLbkTrOU934dlyd3AMrr2hGUerVRt8ScC5u +/ryXiTY10wzIkcmjNLvH5q/0TLiyU5SlHzKAEw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDKzCCAhOgAwIBAgIUWQkPicmb4jXD6HdHqXh3GKFXF28wDQYJKoZIhvcNAQEL -BQAwJTEjMCEGA1UEAwwaZHluYWt1YmUtYWN0aXZlZ2F0ZS5pc3N1ZXIwHhcNMjQw -MjAzMTYxODM2WhcNMjkwMjAxMTYxODM2WjAlMSMwIQYDVQQDDBpkeW5ha3ViZS1h +MIIDKzCCAhOgAwIBAgIUejLjZYxit5P49BBArjUQ8LUGr3IwDQYJKoZIhvcNAQEL +BQAwJTEjMCEGA1UEAwwaZHluYWt1YmUtYWN0aXZlZ2F0ZS5pc3N1ZXIwHhcNMjUw +MjAzMTEzNjUxWhcNMzAwMjAyMTEzNjUxWjAlMSMwIQYDVQQDDBpkeW5ha3ViZS1h Y3RpdmVnYXRlLmlzc3VlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AMzNzK3Xpqa3vjRt/kE02gH3o3sWAuGaGwQQDSqhBWTk4w36WQJzzAA/Vi9QiUxU -wFSJ6X4+ctTwcSozBhHlsW796q40X81teDgZyQl0C+cl1x0rO6HrLkBJYQC5A8cy -kj84eKl3wZCk3GKuOH1zvD3Io4dI6SozeSS5cQb9qMIWqomzvRdJDtyUOgT+RdNQ -FL/SKR7/V83T9n0qCGlu0GiZUvoSBG/NI2gFzRppJIiOyDkikRUXutzXTmhHxtD9 -9zDEkgAjpLMtZ5nfNbaDcvo99XQ0Iq85f/3OMDQC1tc4p4spf3s506MrM7o7pPfZ -vgQaiVF9kKO3AQH3uVCUx/sCAwEAAaNTMFEwHQYDVR0OBBYEFKqsU9R/HSIgJ9UH -13OYpf8Ieq+rMB8GA1UdIwQYMBaAFKqsU9R/HSIgJ9UH13OYpf8Ieq+rMA8GA1Ud -EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAL3drdFOkEBvDANYKs0Vg4mt -2jnEJghSQppY/j7iQWVe5lbVfbvnMOQjio1aeIG2xMu+ZYfEJgrX7x1/h3tni4tI -cMA0FZg37LavIJTd0b09+fT/O6SVvJFCFnAotezVS7z/aA54r3pxkjt1JEsADzzb -Cq42IdXkNLiPgqxpAHjI6m83UoS6g6p5+V/Z4sadR6QeIOBxLjO+cEhNz349tm7d -LDYOO+Ti+Z/yb6d7wyVYNFCLFzHkQPXYvKEwAD0mUOWS9doKQkKgVPj3yK5bBjDW -UNPmUJ412aSo1aRsEJt6zlvHaHMtfhSieG/PwF+1Z82D8dRLamPLGioan8qp9jM= +ANe6fMAThI6gccyf/rT6YonH92kGGrkzBK46Gnq1dG6a9Khn3iCCQuTvHzuI+l0x +vE6nNeEo6gjPjt/7t66rDEmdGwJNvwbF7YxElt/S2X/eTPMMIjdTkfUQTAXbVFWI +6Uy1q3g2thuIUohc+IoIJmyFP4hnnPAhN9KwzCwFTxnaqzoVf0gbwrQ6P19M7cpH +UvH9O/QVbcFBiz88y4eDD+jeXfSYRpP41o3cds1OkueBOWnvPhw91WsVw7BxhlDG +17lBKgEbqJ1/4vBKZklkFU0o9WGDccbyGBw1t2nf7dXkKHcgIjQmk4/sebjhsLZr +i+BVGSKW4GI+t3VvEME2SQMCAwEAAaNTMFEwHQYDVR0OBBYEFP83X0iOEm6+6Az4 +3HSnUG5IerqjMB8GA1UdIwQYMBaAFP83X0iOEm6+6Az43HSnUG5IerqjMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAC1TNWD/GLdSuspDrwOn7seC +TQFBRQa6eU8B43ry5+v6YU78lD/CJ5Gm5m5X+u10rEJ4deFCVPm97QEnY6w4QWZR +NKo8RGza8nN5R2Slip6LpFo62UmfeMyzRzYqNkR3wwlHE0u3aggaTv//VdI3bFtR +XOL5McGoybsxKHK1Ts22OZRZO6DefvFbU2gPN/Kq1ZRnz7dRqGUEeyCdLQv7+Jo4 +ZZaVuTvVI5OInPl5nUp43auU6DQeFuYFrB20/G5vx/ycsrnbsClm2y081W7FrSRh +dljXpdkiJc16liykeFDU/YI5WyNwD7k4jq1n+mZgs/2rgOurjS6oA4eBc+ELn7s= -----END CERTIFICATE----- diff --git a/test/testdata/custom-cas/agcrtkey.p12 b/test/testdata/custom-cas/agcrtkey.p12 index 01f80be22186c0cddbc7e4476f02753d8c93b02b..d5b6227920629ce7224d10db8cd31c8b3c6e48a8 100644 GIT binary patch literal 3571 zcmai%Wmppo_r~4m7!3ntpp-NljfhCk2}q2Tc$f^OQwiyuLt+RL(jC&EgbYT5NGK@? z(hngWlL5ZI*Z+S#&&T(}xz2Up_lNWCoZo>)fcAg@GH3*-n36^;1|D+;0#E_+B0z7* zBS6W2>;z~8)%m{>WnKi;_8)5l2)OpA{rEQlK<)k!6d7qFb}{Y2A3YSDS)s zy8)zdd2goUeV_6Dr$X|?m4z>r&Zc_aVPTL2^5<>n<)7|C>c+`~7Sv7azPh~Zj#nwd z!G5!hiogp9&@%lky6CoRK-)B0VehuQ=!>8(NU8J%&mR3(29+{$#M$A;H` zkif+U1Q#;95Nn@a*|7Iet>ho3U)j))#x5ACt7Hk z3c9NH!9mqm`MI(T$dn-8Oe-m{6@e^!_6D_aJx-OuKZLZ+MK|YltbyIET=`x_zWt8F z2U`e^(q4-$k#3={hHE=`T3YTPg&L-n}=x@w`GfL zHViAuGUYy@XS9Lo9Rx)w@4|i+*CfthhmTOjp_bK3HBjJ$@N)~=I)hjzGBSMrCssC8(9&|Nh?%9egTf&ZOsGDm)K-jZ1m@ zHolFrN+<2(GowUbtgFrJZTwod3%xn`(CJ)2a#9@qw(4N~paU$#?GOXBLn>VsZnfUL z*8N-j9k2giC9?;=*e{26+k3;|_W&-fC|>*DEE&16j{@%1=;prDN2t`UdFXon9N#J| zHx8NMZc2E`nv9<_nCU~2cZTO5LrZ8`@Xu&Nm(+I{8qax1Q?M|c&inauJ=rxOrHJ=g zyA`c1pJ9n0_tANKPr9E;S{hlc#I6yO&14>xxiw&B{9>qF&MJ-Y>?Pd6`6n*#M&9V% zg7f9}u?vMon-d!{A_0vGGAp<4nf@yUGZ_7P**3?q{s{@6S!r3@buBV{=(sfyq-@e@ z&5Vy3T3^GP>V%#oX3}D7qwcEvM%O#72GZ9=L3xVUfWXq7*HtRX9Jw|3wzb{2HZ00y z1j4JVcM?n0Sq7PhApVhr2u+RjcKL};+fUcOc~#P!m4^Ph#2(pu_um&|Q7&(+<#Qa} zDx5slsHfFMxLGvqw`F0_Um_`^IGRs zKG@*T(xsmIk7MuqCbEej{PCD0^PU;3lVnm$C4?Cdh$qNQ`XpM16H6xeNsJ@?ftF0O zdfx@23N3-=OWL~IyMxxVdiu-!l?+^CZbsGC6jVc)AD>W2Y?v^b_rcxD6T1(Xb2g?R z`6NmI;Cg1Y&S)=p7q=J&oi9f+b+?)MLK}D=QG0x-aIe&Rd3s+JkyVOYu!xakeV-XJy3&dN zR@}G?J2BYRvwU+dVDg+dT{!b9^X~FDF?V8#PeCT*1R)TX4)_)3ldIfRdTQJ+`hoO) zzSG>Uv1jJUPe{Z&tY)cN{i$BcxdxL*I$p|}6E?y5Gu z^3H^j$*OZ%6JK_br<3TXwS_&P1JCD{!Eu|Jefyjdj;QvD&bYT{ zY&uw)yH52dSS5;muE$9ljFxwe7*-Jp51dd9Z?Y8Kv|7g~SIq)HcBM*H$H-9wS54#- z)BQ-^wG5-n>${Z8wP9tv=J#6zJLhx)o%rDi6faDeJM$FqJI2GdR>29nNw;aIQ2l1< zRNRB7+N(S}$GFsAY}Z**&MuVh06~7j)$O_jA?My8UwZn|#F{|I*aya4N)0>2s#;>! zi8@>p1ULr18evG^IlFy!TX$7#n@{k94!Y#eWj)p<;8oWhOY^u`wXNgwJg7(5;SJ~{yZ)l>hD>!(@*jx*M|#DOQ{Y|5f)TZBIBBScRR`0zHlu=0G=%X2pm za7F|}0+r{1*){aUjsdy|`yvNI%fIscmMf)1qn>*Uy6awc>f5u$;pw5x1@^1kT{j&@ zelaKmj{KF%o5fNnvL9={*Y!Q^h!niVy*Zs*R@${@f7d-IBsi(KD7SxL6XVHUAUN#F ze&#ahFMRW0-84tFyxF}YKE%nGyC5#l>!m2i1o2kET2@+eRS;%QVrAV$bZn^X=j33O zzK1t1?g_4h+~bFldQ;J80BBb#zg5a~aLs7I?dDrDiPTJ1XavQpfA08y!GI!|Jc1(N zkNxaVc~R2+KQqwN0)T%)phvoGp5t>v;S&FyiPWn4E{4d0=5U)jLlas~7^~=ql^%)Rh3Ny-di5(jg2Av8NnA=E@%#YG z6fKZu)o6_vI7ZwE)jN7L*(4R2dtNMs_{8;Ij|y0$nWj&g-q(m#%t$x=oSeo>Yp9=IZI0Kr^}$t%gcM8;aUeW)iu(YJd%~ zs{wE`LH6ahg=a(sU3iN*ug9g8Dc-B%R;g}Amf8X|`bMQy15`y-hLPrPkpmmqHb?Kj zFC#|RQPu%^CDz0M4Zh446g}r^H$DHDbxLu1w`Rvi=L`e=z4ntkP@(uJPca;$j;bZtfG+Di*zbLL_r94po zEo)6Cff8@@Vj3#6s18tYe1GWiT;3Y1kE#gDO^l{1Ru1>ZiMk0#u{HZ+P^?R-ky}No zxBF@RG6eo6X05)9Nl%z4^8w(OzRjSPE2x%-rWo?M>B7DCCyK#V+}zIu*|UiwPB#U~>z9-)^I%U7S@)!{W> zxJw}IbCVfyu=_^2pGt*y38lGOop$IBMD5v-&6;K(4t4jTj=R0+8ijrj z`2}x=A0!N)bLY5mn9_)^YF}c4-8Lf9tSf>buNb+$TD{1rB6B`;w<5~zJpUTH!~HFN z%Bm8BX0M~{6V{vR1(vRTX~5Mb`!mZJ+(jyCO}SdzOpFIcm;!pSXL=q_;y)KwJso%x zR`9U+i!!}Yq`ZNo$|DoyZx9Nk7W$#4mymtW({B4=_1CT34FjpNFh8#=@A;cza0UAV z8o2U>(iuF-f(9tHaRg@JlL(`#PwE7wbl|@FbdP8yqkE-!I)7uT(HU*wCN&S{CKNsx z&g$4Dj`eP4BCug=_InfW7|$gcZ^FvNh1C@i9Scp&)@Z^LIJNh&oH!LGLw~GxK3WbX zTeYFaRNma?VcstS8TjRX9h1r5Lc~8?UBO%8H;f_cGL(($@i;~wZV*feD)7&urD2D0 zkh4v=@P4JzYGUikriM&-L9j=lepjeE6b1$T^CkfS6xYaa2%Bz&e?`wCje}q10=#W$ iMr*da4m-exu7O#3XUY$~$f@_1A0xCz6C(e+YX1W-aiVen literal 3555 zcmai1cQhLe_cjs)F=~`bt+Yjq21Shu%G;Qwtrco@s9mGALu2n5>$Rz^_9j|tQ>v2M zL2PQ)C@NpS^ZT9m{qy_do_n6>IrrTEp8H%l227-)q=sX_SQ-#46d8H~rlh6J#ehQr z7%=7!jfP`r5B`;Caxt`|Kh&Qgia%}gUxgBG{0{(v;aYH!e<33r0-(E{9@-5Ri94mD zqN9K_($M|iHYyO10)CwaWEF~}d_fJMgaKGa*(+V}%E+{$sw10D`Lv-x4DD-iwAQZE z>AmvrnYOwsZr~`5zpd%5nP6;50NZjrP}E23eKFRWyvLELc)+ySQmr(z+xiQySl6Z< zXcFR^UqQALuqz83mrvQmm@oH#TR#==h_G`Oc0dj;u~jKI8#_!E_WdM^RkYp?2@F3p z*|S=vt$XopCMRFMRdVaetfp%o4Qd1#^=uBd(+1UFT9zla^bjLA!;zi}f_I$gx(L~^ z2Nh5q7hDf(FlzkRGO$m`B|If8BksnaI=A+lru#GZ$hE`U8NC@JAniZ{M8U2avFoXX zdAbtkYCoHy3gHUBrkwz{u!(^`+JGUtO-Hi5#9U9Yz#S^@Z@3!UHITg+w!hCn+j6On zG!%O~A5xRw>5IyX^LUl%R~fT#5$E(?EqtnQsDCHq2*GUe&c=p(PTuhP;rOXt2#sG7 zfPK8+8GN8d%1%n;`bkIC^i;s6b3W-Ur26I207`{-3u*erTE8jotc*J|lJHO~;!|9G z3XkF$f_MP9SruVsS$21N=xzoVO8=obCc*rc@I1^|Y=9~{@y&JmU@D+u+A*I$-|_fY zGa+Y~m?Q6Qb?R_lOqynICQhh_cESK+rr(}^1@m&Q*bKB}loc?XC{mU=tfsX9an6aDolWAr9K-mm^}(*anq5nF%{)Vy ztVq*btr;4CcGIhN2Ba* z*QHZiDcd#12}!!jcRjFDrJHl-9fv?h+R3N*Z?!#^>BA2Iv#N+{XYzSAIN`~tnNA`x zmV&oubBwXnP9a`doLq=!lrCw^@fF)(rk5HwW?l%Os~SaP2WxYxJ*tyx+W0fq8liF2 z41$bxhzv^zV!bVF`xz9|Er?m-VLLE2sNIzfCO2D6h|28mDCAN8p~{S zjCNU>+6Rm~gG5+2x9`M$e5>X-GXap|ua^P%Dk-M-4>C!sbC`;11uJ&GGR` zCKNvJD5FFvRy@&#!$y-I@se5TTiJ<2gkWxq+e?#47Gl%s*7d|rGJzzD?qC88R)}tdY{Q|71V7|DdN3sw#Z#)ngDo* zd*e&V=>1`1{?pp$kr$D+^Qo|5sN2XVCWe#&|H+7Yqr>W(z-*#-tPbQS60LK!n9X< zH@Th#D2pSalj~RG6&@v)_pi1!)27qw*YVC@V$m-Gd;5>w_R^6{tYT{fT_db}PjK17 zBGX^N_fPVbXJqY74@uaW>FW5IRy|sF;P2!SjV-x+m-Rd7hrLb^%|na#(~*3)%;D_U$RIcd82r!u{%;@vz5!r>u77B!KV?V5@c&tX zk)D$3k0|+v6#riV02zc{c#Kvp{+|J0v-kC>W_L|<)Qi3X4cSpn00uCIP?W>>G6N*Z zg#_KfQ&MCrNHM&u)uq7zf`_>Gdk~E@4oAl&1|B z&6%B|_?aHbXYIDd&4{x(wl*ZXuC$5q`#9`2ibw7^-+iJpRs5T?ysfj1!$$3LkRG$N zY3nkv$)?u&{#JSM`U1O|;S#~HJws$6O1nBO%Oy;st@o{wXhUIo60j?4Q{4-9`MtNH z)#+#87^k|p+VUOlFDTq|)!%kzGF~h}0f};+Y+6xE_a|}+@dEzO7)FYDjVr;fd9kx8 za9Z^EKE7y~?cB7LTV3l!)quPI`ePg=&klzmH0=AeU7F0($(aYLrFXHjY#FzjtOu*) zqGu`kaTH#M5^{B)p|HT^mq+(_-25Du0DV%zFt4wt?K(`q4IE1Nr%wX-9*QYgaC`Dw z^t!zYDHFTJMc$(0sMz$%)pXV0UW-zgf6R=NI;=fxkr6z%D3t^(f7H0m7wgsV!jdik zJV)B8+T*Hj9&I7q-cHav10Q6eH?nbG`7GZ|tnSm6ZvT*z-SXXNJ@zy?-C1l`;K>E| zQ@|LF;nr3Qsb1utWm<+N*WSv{CZt%2n$VX2M1{3xA0{6hKx}u|YJn&@m%E_QQ1}`O zhxlTsV9DN_YC&4aScW7xnLDwsYoV`63l%XES@sn_16i1yTulq@hB-b-E*^dB{cDBS zW3;I|Yd8ga=c!<4Pzi!O)x&h9`%#s;c{qJI3A)EZ(|*!R$&2m#yG3lC$4)38F<10^ zgN~PHHFcvSA00inKIR<&^)V}f->#d++Rj2=l1AZ%Tes3xT*HjKkW$}am%&AArsomHdH5dvmq@;y9%MI{gBbDiBa&az zm?2^NmK3Faq^p!t>tM0pC8(50RzABOj=c!N|3;Q+w{BAa4oVqk}IRoxN>+9bKz#pEYlH^?j97$2+p~1n&I4q`m zt=mK=Lz?=H?RTn{CoO#OD$B16fCrtMAc#_$rxphUT}lixF(D<3Ar6kEt`LK+T3 z3}61nW7P&JIfP-RpVntId!kFC3Mg%7>Su4`cgQSGn4wV(6qDOG7Am zI=%au?0mM{6vS`ba6*!e185HLhGcrB@AV9A!nRe|_5^@TENeR?1*dh>Kr`{QTb8Tr zDcT@NaBe;^H?1(s-GD3Am1xnt8L;o>Y5Qiiufc+yqX1@X;hDfsPb6K~G z?+x448G)<9CE?(I-XkhXAO(Qm8Vo*2r`yXj)so($r diff --git a/test/testdata/custom-cas/custom.pem b/test/testdata/custom-cas/custom.pem index 4af7c55672..599a335e32 100644 --- a/test/testdata/custom-cas/custom.pem +++ b/test/testdata/custom-cas/custom.pem @@ -1,20 +1,31 @@ -----BEGIN CERTIFICATE----- -MIIDWDCCAkCgAwIBAgIUVYmiolB97PjZq5Mp/nRbSnzoqoAwDQYJKoZIhvcNAQEL -BQAwHTEbMBkGA1UEAwwSc3F1aWQucHJveHkuaXNzdWVyMB4XDTI0MDIwMjEzMjQ0 -M1oXDTI1MDIwMTEzMjQ0M1owFjEUMBIGA1UEAwwLc3F1aWQucHJveHkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9uDub9pA47dVq61IAmvOIlOx2Dcrt -oY9xaf2zw1HBQORIz2ONABiWvq0WK082ZD6sDdwol5YVR8Y6vRhvBiJPMV3WBH8w -+e8SUazrN/aX4uttfx3cE6DGVvuNDzooFuxMr8aitbtEvgG+3fG6bLma4Xb2Xp8q -CcRxww3aOKU84mRsRxQmYl4kBGHRnmnvyBQ8uzM9p31TisUYwH9IRbXU1zXfGZpR -a8XGo61qRo/cUS+KpBEEaLd5CsFEaTmppnVPlmLJj47Ow7enAeucwj4cMOzP9GnP -795EUNOtWYzcuxa3FaLN6uGMeCkI8VXZCsfIZnTIILwmtjehmGy5ixLRAgMBAAGj -gZYwgZMwHwYDVR0jBBgwFoAU7jJjxqWq485VU405vJMQL96JtUEwCQYDVR0TBAIw -ADBGBgNVHREEPzA9ggtzcXVpZC5wcm94eYIPc3F1aWQucHJveHkuc3Zjgh1zcXVp -ZC5wcm94eS5zdmMuY2x1c3Rlci5sb2NhbDAdBgNVHQ4EFgQUGMSDkrUtztRk54bs -84vZJsgyhAkwDQYJKoZIhvcNAQELBQADggEBAFH/Xd50F7kde0zivHxq0Y4MlEr5 -+8TnB+icfTSDYl68lv4s3hPcmFOHSvQbPLk9fbK+Z0WXGb43t4WnzwdLoFO+eumD -NhNcYt/iOpCECoYckjBmtwo4PXLS56UCmNBNWmKAcLSxwpui6HcIPKEecJ5+2Wak -BVMhE0ooUgW0UEIlxf2P1oO4RqsktdTvfJpcrE2eMxCDqxr3MEETLrIuvYPke6aV -mUu0vFhvq+i1AIbBYUKHbI/Y5zKfiWfAqTzpJmmwwAgQesg68xu63GGDvvDfaZim -qFCo5Vr/1iNtCbkGBqQ35c1Ba6Idh68JeHTOF/O4RCaMKsWTJFck2cwnv9s= +MIIFVDCCAzygAwIBAgIUPiRJza3KU2pXzumVpvyHi67nItkwDQYJKoZIhvcNAQEL +BQAwFjEUMBIGA1UEAwwLc3F1aWQucHJveHkwHhcNMjUwMjAzMTIxMjQyWhcNMjYw +MjAzMTIxMjQyWjAWMRQwEgYDVQQDDAtzcXVpZC5wcm94eTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAMFOnjWspDFGJiszWH8wKneVQPNqLoXK0ewm/Ahy +YLDAW4jiRBeI9J2e6v8JdvZzwiHGYbtJQnYzCdPah7qdeLI3RJ6jLA1iBYjuajI6 +Dodgf/ihT9z0vwS4UpJ8FNB98QDugngw2dnTzNbCF1HxxxXhWmTHRKPv79qWGg2Q +MqK7w3mtKPN6ha5DZhNV6ejdcmJZU4L9mOmCJIZEOkU/KKM3hnWQTwT0IzqxppOg +chCXXtsOZWP1JSWgGebCye2yNQQIksBuHYnjZQc9g/919sowCGZbEZc19kgvaa+I +jNNAAh5PH+UuSzjupd+HJGZtz39U/pvQmz/ImuntwGZEEMLCY1Lw+H3O2W7bKAac +hM4QDah5J5En77+lFk+ce0dnctQ76iL1ww0TDiLS5C7oZ5lGfgidXgIYbpsIVhUH +ee8Ei0Zc6K3smMM4dXsqJtwWERhs0G2u/CvJ1r4gxeIAf5+bihXPGI9lMtPRHa/1 +31Sn6UTyZaoizjSYyYmIuIfYMVC5X+DtFUb3wG+/UyStqDqFXPLDS3yHyhj42z8O +SAx82vZDPO+CIVDzsqhrxg2G9s5gBFzv/xSacElZEwzELa0fcrAra8BLjkFVgdhM +NsNZ4CYOhF2iuDC9aQmsWKB0jNBujdMm/EPJKUDLKg0+J4rDa85YND96NaKLZKU2 +c6NdAgMBAAGjgZkwgZYwHQYDVR0OBBYEFAf8Nh6D5ZGPPhVCf8PX8S4p+GpOMB8G +A1UdIwQYMBaAFAf8Nh6D5ZGPPhVCf8PX8S4p+GpOMEYGA1UdEQQ/MD2CC3NxdWlk +LnByb3h5gg9zcXVpZC5wcm94eS5zdmOCHXNxdWlkLnByb3h5LnN2Yy5jbHVzdGVy +LmxvY2FsMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBACsa8L4boFIm +LZTztUZdQAHZnuJiMHHs2vbvbK3nziaFd9ygf0f/x/xJ4b9Ae5mzAsC+tN65PwRt +L9nkYr8KmWHUhDjcB0ya74YbNYjlbbOfPkDtH21HGuORDTBe0Dw9acMmXy0ardYu +cm4/x0I1iAFcOl1OX61U9lb75G2Fj+WObOzWVXBDCJVDkTZ2DN+m4fS/RIEhSrmk +cCMaIr60sKMOiPXgAIpQGVXEV142Rm8bducoM2xo5ffU+PZ7ZUnO+up35wGSCDpq +boGpJTILqA68XhsPaoHF6OF/pDRO9oxQ5aYHQl7RaxNizsf0TqhUbYxg5/XURvSj +gH17Oc0FQihoqSSmEVeUq9iE18uHLCe27eUcl/Uj+oOBX4qvHysdJdFIcPceNrYq +EdSFFzNirJkT9htnzbXGexWuBBAoiZyFiBjSI/hygkL9C43aHR+ezuOedyUFoW+1 +xh/4gWaEe01Ws5Un8XqGexNTukPr9+2RtGtvwXm9fUlhYhJKHEsq7Yh1TzSeylLK +iHE3gabqy9HHwK2iqhR8345F8irFC+7ARHTq55UIvWNojzaW5nwWJDxay+bmP+6r +EjtP36UUhH8ExAR4d59FAeTi6gH/9NFNf1DWHtd4Cndixs9VEKkQZ1Lx1zbIHFNh +iJVRSZs2HZVjPAxGuydRHp9J9b7Jka6C -----END CERTIFICATE----- diff --git a/test/testdata/network/proxy-ssl.yaml b/test/testdata/network/proxy-ssl.yaml index 820ae79d25..1eada72f37 100644 --- a/test/testdata/network/proxy-ssl.yaml +++ b/test/testdata/network/proxy-ssl.yaml @@ -20,7 +20,7 @@ metadata: namespace: proxy data: squid-ca-cert.pem: | - LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURXRENDQWtDZ0F3SUJBZ0lVVlltaW9sQjk3UGpacTVNcC9uUmJTbnpvcW9Bd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0hURWJNQmtHQTFVRUF3d1NjM0YxYVdRdWNISnZlSGt1YVhOemRXVnlNQjRYRFRJME1ESXdNakV6TWpRMApNMW9YRFRJMU1ESXdNVEV6TWpRME0xb3dGakVVTUJJR0ExVUVBd3dMYzNGMWFXUXVjSEp2ZUhrd2dnRWlNQTBHCkNTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDOXVEdWI5cEE0N2RWcTYxSUFtdk9JbE94MkRjcnQKb1k5eGFmMnp3MUhCUU9SSXoyT05BQmlXdnEwV0swODJaRDZzRGR3b2w1WVZSOFk2dlJodkJpSlBNVjNXQkg4dworZThTVWF6ck4vYVg0dXR0ZngzY0U2REdWdnVORHpvb0Z1eE1yOGFpdGJ0RXZnRyszZkc2YkxtYTRYYjJYcDhxCkNjUnh3dzNhT0tVODRtUnNSeFFtWWw0a0JHSFJubW52eUJROHV6TTlwMzFUaXNVWXdIOUlSYlhVMXpYZkdacFIKYThYR282MXFSby9jVVMrS3BCRUVhTGQ1Q3NGRWFUbXBwblZQbG1MSmo0N093N2VuQWV1Y3dqNGNNT3pQOUduUAo3OTVFVU5PdFdZemN1eGEzRmFMTjZ1R01lQ2tJOFZYWkNzZklablRJSUx3bXRqZWhtR3k1aXhMUkFnTUJBQUdqCmdaWXdnWk13SHdZRFZSMGpCQmd3Rm9BVTdqSmp4cVdxNDg1VlU0MDV2Sk1RTDk2SnRVRXdDUVlEVlIwVEJBSXcKQURCR0JnTlZIUkVFUHpBOWdndHpjWFZwWkM1d2NtOTRlWUlQYzNGMWFXUXVjSEp2ZUhrdWMzWmpnaDF6Y1hWcApaQzV3Y205NGVTNXpkbU11WTJ4MWMzUmxjaTVzYjJOaGJEQWRCZ05WSFE0RUZnUVVHTVNEa3JVdHp0Ums1NGJzCjg0dlpKc2d5aEFrd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFGSC9YZDUwRjdrZGUweml2SHhxMFk0TWxFcjUKKzhUbkIraWNmVFNEWWw2OGx2NHMzaFBjbUZPSFN2UWJQTGs5ZmJLK1owV1hHYjQzdDRXbnp3ZExvRk8rZXVtRApOaE5jWXQvaU9wQ0VDb1lja2pCbXR3bzRQWExTNTZVQ21OQk5XbUtBY0xTeHdwdWk2SGNJUEtFZWNKNSsyV2FrCkJWTWhFMG9vVWdXMFVFSWx4ZjJQMW9PNFJxc2t0ZFR2ZkpwY3JFMmVNeENEcXhyM01FRVRMckl1dllQa2U2YVYKbVV1MHZGaHZxK2kxQUliQllVS0hiSS9ZNXpLZmlXZkFxVHpwSm1td3dBZ1Flc2c2OHh1NjNHR0R2dkRmYVppbQpxRkNvNVZyLzFpTnRDYmtHQnFRMzVjMUJhNklkaDY4SmVIVE9GL080UkNhTUtzV1RKRmNrMmN3bnY5cz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQotLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS0KTUlJRXZnSUJBREFOQmdrcWhraUc5dzBCQVFFRkFBU0NCS2d3Z2dTa0FnRUFBb0lCQVFDOXVEdWI5cEE0N2RWcQo2MUlBbXZPSWxPeDJEY3J0b1k5eGFmMnp3MUhCUU9SSXoyT05BQmlXdnEwV0swODJaRDZzRGR3b2w1WVZSOFk2CnZSaHZCaUpQTVYzV0JIOHcrZThTVWF6ck4vYVg0dXR0ZngzY0U2REdWdnVORHpvb0Z1eE1yOGFpdGJ0RXZnRysKM2ZHNmJMbWE0WGIyWHA4cUNjUnh3dzNhT0tVODRtUnNSeFFtWWw0a0JHSFJubW52eUJROHV6TTlwMzFUaXNVWQp3SDlJUmJYVTF6WGZHWnBSYThYR282MXFSby9jVVMrS3BCRUVhTGQ1Q3NGRWFUbXBwblZQbG1MSmo0N093N2VuCkFldWN3ajRjTU96UDlHblA3OTVFVU5PdFdZemN1eGEzRmFMTjZ1R01lQ2tJOFZYWkNzZklablRJSUx3bXRqZWgKbUd5NWl4TFJBZ01CQUFFQ2dnRUFEMHZmWW4vS3VReFQvTDdrYWJBVW1wcUhSaTF1Z3lKWGttbGRUelVjVGx5UgpDMTNOUlAwUS9uWjVOaVJmeXA3aWZyVFBYMlo1YjFYT0ljWkZSZzVVamRZSkhzeFdCUGpoMGJSTUlOcnVRdWpFCjJwczVLUmxjQ1NIU1BsbFA4eE9HRWRqS1J5d240UzhBclFid0NudmhxeDhxbkVxY3dxTHU5ODBtUE1YOGJLQWcKbXhXblh6bDROQ21kZUZqYTlRQ0YvLzNQellUa3hLamNRMGhvSXpBa2N4Q3ZDZFJJVHVZN2Y4a2MwSG1ySWtrego2UGhCNDBKZiswMk9HMzZhK1NGcFZ2em1QZ0FOQUFoT2lPeHE2TlRoRTJaMGwyMGZFMVJxRDB0eTN3R2tMZ3JiCmZwMGg4SGh5bHVnbGtRSlY3TUxuUHVLZE9odnpXWklVVXZJLy94cFZVUUtCZ1FEdVY2OGxiLzRlZkp3b3VMa2MKakV1Z2Z1VXhnc3I1VmRSakZVZmVkdTJsYmRsSDBoanQwUTNQUjZOMUlrRlVqTEgvY1VNS0xBanlFeFFYNisrTAp5SHhYckZqMnQrS3A5bXJSVkE1clVpRUJlZTZ4R29KVkFHRHFzZ0h0UGRBZjYxZ0dXVmwyK2hSS1BiQ3NGTm9VCmJNMStadjg5UHVHbVJjNXhrdnFNY2hrQ1d3S0JnUURMeG1LMjI0OGF3UmZwNzArNloyTWRGMkNVRTJRUFFLK08KTVByaWlIYmxCL3FJazFWemtPajlYL2JqaEYwSjVXZzgrbDAwekNjRzBhTkRLb01PTlE3ZGVSUVZzTnlkaG9Eago4RnlMZUpHa0d3T2pmWXpsc29PazUrUTFrL0hyVDUzbkJGM0VkVmg2UlNhZUNUZ080djUvWEtsOUVwYWI2TWdYCiswNTQ3QTV2UXdLQmdRQ1VIVXVMc1dBelkrN0xZNWd0eElYTzlHekw2dUxtTmM5cHo3Uzg3QjFjKzduV1p4cjAKMTBDRXVwazYxcEhRMENwaGV1cFZiTzRXT1lMNEpyZlRuMENlWDAxZDdRSmY2dkdRcW5MWGdNOWdFbjBoOUQ1ZwpRbjczK3EwMTJINzVCeERKeVViT3FEUnB1cEtMTGQ0a2FVVCtzMVVVbzNvcEVTSnM5QkRkcko0Y0Z3S0JnR252Cjlpdm9VeXB1amxjaEFjci9xc2haK2V5aGRCaDE0WTdEcWZxUlJYWm1Rbm8wVm0xaFBhOVQ3NDl5cGNmYVN1bkEKb3lvcXBITm9Fejk4MzJ0SWJEVDVtRlo2ZndjcUFPSC9lSzFOZmpIWmxYZXVjc3lMbE9MclozbnZNd3JKZG1hKwpuMXplUUtRNFJRNU43cVhXbnNacHp2ZGw3WVNhYlVRQ2MxWnNLa2p2QW9HQkFJbk5zRzAxOUdQUDNpSzdYOWJpCld3MnI4RDdMakpHVlppKzlqM29uOENwMldpYy84dW9TL1ZBSmRsTURHVFFxZ004M2tKUFVhalpNNjI3K1NNT24KTTFiSmMwOGpTSERzcCtMS1hwMEQ4QTVkWnoraUt4TVFyZWxZVG9wcUhUbHh1M1RXSmlTY0FoNHRlWTl0QjZxcQoyc3NkY240eFJZRUFYZnU1aHVad0UyczAKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQoK + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZWRENDQXp5Z0F3SUJBZ0lVUGlSSnphM0tVMnBYenVtVnB2eUhpNjduSXRrd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0ZqRVVNQklHQTFVRUF3d0xjM0YxYVdRdWNISnZlSGt3SGhjTk1qVXdNakF6TVRJeE1qUXlXaGNOTWpZdwpNakF6TVRJeE1qUXlXakFXTVJRd0VnWURWUVFEREF0emNYVnBaQzV3Y205NGVUQ0NBaUl3RFFZSktvWklodmNOCkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFNRk9ualdzcERGR0ppc3pXSDh3S25lVlFQTnFMb1hLMGV3bS9BaHkKWUxEQVc0amlSQmVJOUoyZTZ2OEpkdlp6d2lIR1lidEpRbll6Q2RQYWg3cWRlTEkzUko2akxBMWlCWWp1YWpJNgpEb2RnZi9paFQ5ejB2d1M0VXBKOEZOQjk4UUR1Z25ndzJkblR6TmJDRjFIeHh4WGhXbVRIUktQdjc5cVdHZzJRCk1xSzd3M210S1BONmhhNURaaE5WNmVqZGNtSlpVNEw5bU9tQ0pJWkVPa1UvS0tNM2huV1FUd1QwSXpxeHBwT2cKY2hDWFh0c09aV1AxSlNXZ0dlYkN5ZTJ5TlFRSWtzQnVIWW5qWlFjOWcvOTE5c293Q0daYkVaYzE5a2d2YWErSQpqTk5BQWg1UEgrVXVTemp1cGQrSEpHWnR6MzlVL3B2UW16L0ltdW50d0daRUVNTENZMUx3K0gzTzJXN2JLQWFjCmhNNFFEYWg1SjVFbjc3K2xGaytjZTBkbmN0UTc2aUwxd3cwVERpTFM1QzdvWjVsR2ZnaWRYZ0lZYnBzSVZoVUgKZWU4RWkwWmM2SzNzbU1NNGRYc3FKdHdXRVJoczBHMnUvQ3ZKMXI0Z3hlSUFmNStiaWhYUEdJOWxNdFBSSGEvMQozMVNuNlVUeVphb2l6alNZeVltSXVJZllNVkM1WCtEdEZVYjN3RysvVXlTdHFEcUZYUExEUzN5SHloajQyejhPClNBeDgydlpEUE8rQ0lWRHpzcWhyeGcyRzlzNWdCRnp2L3hTYWNFbFpFd3pFTGEwZmNyQXJhOEJMamtGVmdkaE0KTnNOWjRDWU9oRjJpdURDOWFRbXNXS0Iwak5CdWpkTW0vRVBKS1VETEtnMCtKNHJEYTg1WU5EOTZOYUtMWktVMgpjNk5kQWdNQkFBR2pnWmt3Z1pZd0hRWURWUjBPQkJZRUZBZjhOaDZENVpHUFBoVkNmOFBYOFM0cCtHcE9NQjhHCkExVWRJd1FZTUJhQUZBZjhOaDZENVpHUFBoVkNmOFBYOFM0cCtHcE9NRVlHQTFVZEVRUS9NRDJDQzNOeGRXbGsKTG5CeWIzaDVnZzl6Y1hWcFpDNXdjbTk0ZVM1emRtT0NIWE54ZFdsa0xuQnliM2g1TG5OMll5NWpiSFZ6ZEdWeQpMbXh2WTJGc01Bd0dBMVVkRXdRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFTEJRQURnZ0lCQUNzYThMNGJvRkltCkxaVHp0VVpkUUFIWm51SmlNSEhzMnZidmJLM256aWFGZDl5Z2YwZi94L3hKNGI5QWU1bXpBc0MrdE42NVB3UnQKTDlua1lyOEttV0hVaERqY0IweWE3NFliTllqbGJiT2ZQa0R0SDIxSEd1T1JEVEJlMER3OWFjTW1YeTBhcmRZdQpjbTQveDBJMWlBRmNPbDFPWDYxVTlsYjc1RzJGaitXT2JPeldWWEJEQ0pWRGtUWjJETittNGZTL1JJRWhTcm1rCmNDTWFJcjYwc0tNT2lQWGdBSXBRR1ZYRVYxNDJSbThiZHVjb00yeG81ZmZVK1BaN1pVbk8rdXAzNXdHU0NEcHEKYm9HcEpUSUxxQTY4WGhzUGFvSEY2T0YvcERSTzlveFE1YVlIUWw3UmF4Tml6c2YwVHFoVWJZeGc1L1hVUnZTagpnSDE3T2MwRlFpaG9xU1NtRVZlVXE5aUUxOHVITENlMjdlVWNsL1VqK29PQlg0cXZIeXNkSmRGSWNQY2VOcllxCkVkU0ZGek5pckprVDlodG56YlhHZXhXdUJCQW9pWnlGaUJqU0kvaHlna0w5QzQzYUhSK2V6dU9lZHlVRm9XKzEKeGgvNGdXYUVlMDFXczVVbjhYcUdleE5UdWtQcjkrMlJ0R3R2d1htOWZVbGhZaEpLSEVzcTdZaDFUelNleWxMSwppSEUzZ2FicXk5SEh3SzJpcWhSODM0NUY4aXJGQys3QVJIVHE1NVVJdldOb2p6YVc1bndXSkR4YXkrYm1QKzZyCkVqdFAzNlVVaEg4RXhBUjRkNTlGQWVUaTZnSC85TkZOZjFEV0h0ZDRDbmRpeHM5VkVLa1FaMUx4MXpiSUhGTmgKaUpWUlNaczJIWlZqUEF4R3V5ZFJIcDlKOWI3SmthNkMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQotLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS0KTUlJSlFnSUJBREFOQmdrcWhraUc5dzBCQVFFRkFBU0NDU3d3Z2drb0FnRUFBb0lDQVFEQlRwNDFyS1F4UmlZcgpNMWgvTUNwM2xVRHphaTZGeXRIc0p2d0ljbUN3d0Z1STRrUVhpUFNkbnVyL0NYYjJjOEloeG1HN1NVSjJNd25UCjJvZTZuWGl5TjBTZW95d05ZZ1dJN21veU9nNkhZSC80b1UvYzlMOEV1RktTZkJUUWZmRUE3b0o0TU5uWjA4elcKd2hkUjhjY1Y0VnBreDBTajcrL2FsaG9Oa0RLaXU4TjVyU2p6ZW9XdVEyWVRWZW5vM1hKaVdWT0MvWmpwZ2lTRwpSRHBGUHlpak40WjFrRThFOUNNNnNhYVRvSElRbDE3YkRtVmo5U1Vsb0JubXdzbnRzalVFQ0pMQWJoMko0MlVIClBZUC9kZmJLTUFobVd4R1hOZlpJTDJtdmlJelRRQUllVHgvbExrczQ3cVhmaHlSbWJjOS9WUDZiMEpzL3lKcnAKN2NCbVJCREN3bU5TOFBoOXp0bHUyeWdHbklUT0VBMm9lU2VSSisrL3BSWlBuSHRIWjNMVU8rb2k5Y01ORXc0aQowdVF1NkdlWlJuNEluVjRDR0c2YkNGWVZCM252Qkl0R1hPaXQ3SmpET0hWN0tpYmNGaEVZYk5CdHJ2d3J5ZGErCklNWGlBSCtmbTRvVnp4aVBaVExUMFIydjlkOVVwK2xFOG1XcUlzNDBtTW1KaUxpSDJERlF1Vi9nN1JWRzk4QnYKdjFNa3JhZzZoVnp5dzB0OGg4b1krTnMvRGtnTWZOcjJRenp2Z2lGUTg3S29hOFlOaHZiT1lBUmM3LzhVbW5CSgpXUk1NeEMydEgzS3dLMnZBUzQ1QlZZSFlURGJEV2VBbURvUmRvcmd3dldrSnJGaWdkSXpRYm8zVEp2eER5U2xBCnl5b05QaWVLdzJ2T1dEUS9laldpaTJTbE5uT2pYUUlEQVFBQkFvSUNBQzV6K3hjQTd0QWNnRzJmUUNRSWFod2sKbE9BcDR4WXB3RHFVdjdvejZrSnZaMC9FdUFKRDJpektsTVJHL1B5S290dEU5aFZ3ckhVRkhOWjVUR2F2RXVNWQozdmVVVkxDK25uL2ljMGl3cE84cFpIZFdKSC8vbkt2QXM2OFovRktDQVZsczk1TjBnZFdUelVUS2pab1dsUFlRCkdvM2ZTUUp3VlY1YzlkUE9sQ3lCSEo5djJraHdhQkdSaHNVY3YwSkRmUXBmVnU5Q2krMkpaY2VTTzhLS1EvUzkKRWlYTVVRRHF2bENMZ25FMWZGTzZYSVFkdUlYRjBuQnhRZWd2WlNFbTB4Q3VFcjRGZURtN21IcWQ4TXVDQ0pWYgo1NWpaUjZmand0UmorR3pEVHJ3eFJKRU9DS2NsY2RRem5VN1RCZzlMVWpMU05RRXlweXd6dys1MVFPZ1NjVWhCCkJjWTJzcitXeml3R3lhMC9KdUZGaTFQam9sckpRSmxLRW9sZVVHeGZxUGN3ZWI4OUluOFE3dVlRSHNscmJ2M1AKYzdyWFJQLzkydWd1bS9ocTNJcURWcUhSVUIrUUkwTWdabHlkTi9RbENVaFNUbmxkZUhKbFNrOEwvdXZTTmVhaApXRnV4ZHdBZnBMUUE3ZXo2Z1BSandtRXAzZ3BnVkduRVpNcWIzaGtJbm9ZWnlrVW1TNUI4eHRDV3RXenhITUFDCnl0RU52N1RoeUUwWkdkZkhZRXBmQ2dFYnp5MUZDK0FXZGc3N3VyTE1ORWpvakRKOTZydHd2anUwMk9uRmVDaTAKUm15emEvaEJQanhzRUEzY3JZQXkxQlNMM0l2TGNGUC9nRXM4a0FqaWt3cURsNWNxeVcvYzdGN2VTTXBkeWY5QwplaXMrNHpIRDZORnpFYzBPNWhQaEFvSUJBUUR2Szh1UzBYdXB5aXZreThUVDVveGR5SnlNUk1xZW9DVWRGYndjClg4cUdmZnYxdlo4SkJKRHZGdHFZWnF4YlpTVmVBbTdWeTFCVGs3TlhhbmdoRi9tL05aM0dIRUVmWHZxY3lsdzYKL21QRXRLYXcwRU1DOC9tZFNMNjFramdlT2JiWVl4bW5Hd2QzYXJ4VEtacEJkOWFUcWZGUWdjQTdSZWVWa3hFWAo5N0F0TzZ1Qzk5OTJrRVdWS1dNRGtKbjNGSTBQTWN4WVN2bi9ORi95M1RncHJSTTZ0UDlGUWNtWC9OVElYb2l1CmhoM0x2bEU1MlhKQnpweC84SnhreGpPSkI5QXdLUC85endlVG1ncW1peUVJcWhlM0lUNjMzdDltV2hQR29JZVUKT0FkcFVBNHg1UmlLWGVaelUzZm4wQW83WlZVdjN3UWRkOFVhTThXZVcxVVA3clhaQW9JQkFRRE82S3dEMzJxcgo4bzdYWWhlS0toZHRMUnkzcFpHUlZheVlqWHZObFFQb1hQb1BvNjkxSk9OZWQrQWhrdVNNYzBJdFNBMGtMaXRUCmdyaVhpemhsNHpZMkptdENoRzhDRXRVVXhzbGY3UkY5SlNlN1p3ekhxeWVRVlNvdVF5aFllK1VKTWYwdTR6QTAKMWNTWTlFUGNweG1ja01nZ3dkc0NRbEpNYnJaMWRLeFNBTTBFRXlPcnFXdU9wd1hBWkhLRVdwcXh5M0Z4SGlZVgpXYVZ0K2ZzOERsODhwZU9tMVZaeXk4TllMSHl3VlFzS2s0UFpUL0hwZStMMHhyUGdxNXJyWHBjVWRmL3RmZGVoCjBxc3h4cmRSSmliMUFmdGh2ME5Mb1F0TUxxaXJjU1o4S1hxWFEwVG5PQ0JYTm9XSWNXUmlrM0ZlN1BGYXMrS0EKdkVEVXV5Z3ZMbE1sQW9JQkFBaExpNDczQndQM2lCZ3lYUXhBWmNQbTdrOExINy9xcS83YlB4LzR6b3hsbURTSQp0QmhhK1MvaHFnazVIbWM1RmRleDIrZzhXZmZjR285QW1SUUV3ZHU0MzFUOHErR0xxTU9CWFR1S2tTbEVYcmVwCk1Ybkx2bStQRTFZMjBRMXpVUDBtU3NCNTlvTlV4MTFYQnd1WVBXLzNwKy96NEJmdUw3OEhUOE4yQ3IwMjRaYjAKUStMWDFDSDlRbnJnTEFiZXhwbXRUM29NZDZrN1JzeWtrWXNZZnA4OW9kRGtIRHJTUVFzR0JGV1JQejFPeDRCcgpJMFJYQnlTRTB0Zkg3QWVucHJmVTVEUUlWeW51WU1vdjd5QmV6ZDNESUdxK0p4OWtwbVR3TW1PWW9lRXNMcUhhCllVU0RSemZld0R6aEFVbllGT0ZKS2RwZnlnMURtR29LbnVPamt0a0NnZ0VBWlVzYkN6cFJLcVN3c1ZqZ1ZVK04KOEhEcFlpNjRPUUpNWU5MRERUNHFqNU1WQ0pzRnhyK3NZQThudHNnSEE0dFpsbmx6bFliVXh5bHozUnpYRzJwRQptL1hyQk1GNDV2YjVRaGFmZDByRUNSUXJnMTlMcm1Sb0ZnemJmWko3S2ZaZGhrYm13QkdSQkF5ekZuNWV5cU16CnNxWmVrMHJVUVNMZXozUlQ5dVNMaUFuRVZINWFOQ3ZZOEJsc2cyZXBlSW95dVYvenhZRVErOXJMVmkvUGd2TTIKUkthaDhJYjRyM0o1eTZ6YnppZVVKRFZia3dQRVZwM0Qyamw4emp5MHR3Mnp3TnlUMGx5Tk9EZStmN3ZjK3VsRwpvU083UVhzMUlzMVFqcGM1RTlWdEZkUG9wQ3pXaXF1N2lYYXpvTHlDZkkvYUxMS3E1ZEN5em50YThjbytQZnJiCjBRS0NBUUVBcktXSThDOW1ENnlRdWZIQVBCRDJLTXhnUTJVdjNaUHZqNU5kcUppMjFweThNSjNyNWQ4RFFsQWcKQ2w3RURoNml0alY2cFhCeGdsL0Nha1lMcURtczh4aG1KVkhWSmtlZ0E4OW53QXMxekx3d21tUmpyU3U2R0F3VgphOWpNdEJWK3dhY09kWHQwUVRlbVVhbzdNY1gzVy9PU1l6WXBlS1dEemQwUy9qeDZadHJkM2lGQ20vMTBydkYyCmJ1QTlJTWE2Q041QytHTTFhZ2xrb2s0Z1VWYWtHSk1uMXJRc3F3b0JlVkpxSkFHRVRWcExKY0hhbzNhVFh6ckgKU2gvVGFxUEVZUzlpRnV6NWhsc3ZNWUFFZUtML0VZNGo4Vi9EMlljYTJMTG5HV1BzS2VMQ2FMWkhucU1ieWtHeQo3ZEVQdGVZRTlrVFZqcmtwV2t6SGYyelQ4d3NxNkE9PQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg== --- apiVersion: v1 kind: ConfigMap From cbcf116cb7fe4c4c3d46801cbb8bcabe689b1aeb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 08:46:53 +0000 Subject: [PATCH 167/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1738643550 (main) (#4394) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ea95bdbee8..51217ad312 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1736426761@sha256:f6e0a71b7e0875b54ea559c2e0a6478703268a8d4b8bdcf5d911d0dae76aef51 AS base -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1736404036@sha256:53d6c19d664f4f418ce5c823d3a33dbb562a2550ea249cf07ef10aa063ace38f AS dependency +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1738643550@sha256:95356f4377e6ca6b8ad56fe33af8258d48010476aac287031dd572cfafceb285 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 3f78638e5567e328696e8905e2f437415969e259 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Tue, 4 Feb 2025 10:45:00 +0100 Subject: [PATCH 168/426] Revert "misleading declaration of healthz port between server and liveness-probe" (#4397) --- .../helm/chart/default/templates/Common/csi/daemonset.yaml | 5 ++--- .../helm/chart/default/tests/Common/csi/daemonset_test.yaml | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/config/helm/chart/default/templates/Common/csi/daemonset.yaml b/config/helm/chart/default/templates/Common/csi/daemonset.yaml index 605b0ffb27..7ec83f1f02 100644 --- a/config/helm/chart/default/templates/Common/csi/daemonset.yaml +++ b/config/helm/chart/default/templates/Common/csi/daemonset.yaml @@ -120,6 +120,8 @@ spec: timeoutSeconds: 4 {{- end }} ports: + - containerPort: 9808 + name: healthz - containerPort: 8080 name: metrics resources: @@ -244,9 +246,6 @@ spec: - --probe-timeout=4s command: - livenessprobe - ports: - - name: healthz - containerPort: 9808 resources: {{- if .Values.csidriver.livenessprobe.resources }} {{- toYaml .Values.csidriver.livenessprobe.resources | nindent 10 }} diff --git a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml index 7e7572186c..35c0205547 100644 --- a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml @@ -193,6 +193,8 @@ tests: timeoutSeconds: 4 name: server ports: + - containerPort: 9808 + name: healthz - containerPort: 8080 name: metrics resources: @@ -337,9 +339,6 @@ tests: - "--probe-timeout=4s" command: - livenessprobe - ports: - - containerPort: 9808 - name: healthz image: image-name imagePullPolicy: Always name: liveness-probe From 043c0005f3df84d4d08329d74817a530e5545573 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:12:36 +0000 Subject: [PATCH 169/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1738659858 (main) (#4398) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 51217ad312..1659920a45 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1736426761@sha256:f6e0a71b7e0875b54ea559c2e0a6478703268a8d4b8bdcf5d911d0dae76aef51 AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1738659858@sha256:a434c4babbc08a8d0a7f227154b46f0df0a4b701af0796716cb5305807b2b2b3 AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1738643550@sha256:95356f4377e6ca6b8ad56fe33af8258d48010476aac287031dd572cfafceb285 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From d684d417a59ffcaecf27441595aabfd931661f0f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:25:14 +0000 Subject: [PATCH 170/426] fix(deps): update module golang.org/x/mod to v0.23.0 (main) (#4400) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 562ce81f52..56dbc4d50e 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stretchr/testify v1.10.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/mod v0.22.0 + golang.org/x/mod v0.23.0 golang.org/x/net v0.34.0 golang.org/x/oauth2 v0.25.0 golang.org/x/sys v0.29.0 diff --git a/go.sum b/go.sum index b86e182005..bf8dff581f 100644 --- a/go.sum +++ b/go.sum @@ -183,8 +183,8 @@ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From 241f94472e18d5aa6c9fbc18e108458bdd4e124f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:44:44 +0000 Subject: [PATCH 171/426] fix(deps): update module golang.org/x/oauth2 to v0.26.0 (main) (#4401) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 56dbc4d50e..4b23aeed60 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.23.0 golang.org/x/net v0.34.0 - golang.org/x/oauth2 v0.25.0 + golang.org/x/oauth2 v0.26.0 golang.org/x/sys v0.29.0 google.golang.org/grpc v1.70.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index bf8dff581f..2263840015 100644 --- a/go.sum +++ b/go.sum @@ -191,8 +191,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= +golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 4deefeb5e32ceb56ce1e5f80b82701e7ac134968 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:41:53 +0000 Subject: [PATCH 172/426] chore(deps): update golangci/golangci-lint-action action to v6.3.0 (main) (#4404) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3111fa6d34..7593df5624 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,7 +86,7 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint - uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6.2.0 + uses: golangci/golangci-lint-action@e60da84bfae8c7920a47be973d75e15710aa8bd7 # v6.3.0 with: # renovate depName=github.com/golangci/golangci-lint version: v1.63.4 From 90ae2c355ab910f96e9f580d14c2ebf497f50d62 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 21:57:26 +0000 Subject: [PATCH 173/426] fix(deps): update module golang.org/x/sys to v0.30.0 (main) (#4405) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4b23aeed60..fff83eda3f 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( golang.org/x/mod v0.23.0 golang.org/x/net v0.34.0 golang.org/x/oauth2 v0.26.0 - golang.org/x/sys v0.29.0 + golang.org/x/sys v0.30.0 google.golang.org/grpc v1.70.0 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.2 diff --git a/go.sum b/go.sum index 2263840015..7c37006814 100644 --- a/go.sum +++ b/go.sum @@ -202,8 +202,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 6b8fcc83b2188148d995eb523a2881fef1671292 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2025 01:31:41 +0000 Subject: [PATCH 174/426] chore(deps): update sigstore/cosign-installer action to v3.8.0 (main) (#4408) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/sign-image/action.yaml | 2 +- .github/actions/upload-sbom/action.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/sign-image/action.yaml b/.github/actions/sign-image/action.yaml index 36c6e88fe9..bb3a4ef8b7 100644 --- a/.github/actions/sign-image/action.yaml +++ b/.github/actions/sign-image/action.yaml @@ -14,7 +14,7 @@ runs: using: "composite" steps: - name: Install Cosign - uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 + uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0 - name: Sign image with a key shell: bash run: | diff --git a/.github/actions/upload-sbom/action.yaml b/.github/actions/upload-sbom/action.yaml index 27e7a4788e..01e18b37e0 100644 --- a/.github/actions/upload-sbom/action.yaml +++ b/.github/actions/upload-sbom/action.yaml @@ -17,7 +17,7 @@ runs: using: "composite" steps: - name: Install Cosign - uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 + uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0 - name: Attach sbom attestation to image shell: bash run: | From 1acc9e75dcd5b4213c5b1c199cec1ab1e5d5a24b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2025 11:13:57 +0100 Subject: [PATCH 175/426] chore(deps): update golang docker tag to v1.23.6 (main) (#4409) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1659920a45..7c9c3c6c90 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # check=skip=RedundantTargetPlatform # setup build image -FROM --platform=$BUILDPLATFORM golang:1.23.5@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 AS operator-build +FROM --platform=$BUILDPLATFORM golang:1.23.6@sha256:958bd2e45b2d6d166aa0e33ee737093fe0c773c89c3fc142f26ac65ec37507cd AS operator-build WORKDIR /app From fcac2b45370418847fcac3009fe62e6e500ad779 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Wed, 5 Feb 2025 12:01:10 +0100 Subject: [PATCH 176/426] Adds possibility to enable Live Debugger module in ActiveGate. (#4407) --- pkg/api/v1beta3/dynakube/activegate/spec.go | 6 ++++++ .../dynakube/activegate/capability/capability.go | 11 +++++++++++ .../activegate/capability/capability_test.go | 12 ++++++++++++ test/features/activegate/activegate.go | 1 + test/helpers/components/dynakube/options.go | 1 + 5 files changed, 31 insertions(+) diff --git a/pkg/api/v1beta3/dynakube/activegate/spec.go b/pkg/api/v1beta3/dynakube/activegate/spec.go index 992072897a..ff1231c57c 100644 --- a/pkg/api/v1beta3/dynakube/activegate/spec.go +++ b/pkg/api/v1beta3/dynakube/activegate/spec.go @@ -43,6 +43,11 @@ var ( ShortName: "dynatrace-api", ArgumentName: "restInterface", } + DebuggingCapability = Capability{ + DisplayName: "debugging", + ShortName: "debugging", + ArgumentName: "debugging", + } ) var CapabilityDisplayNames = map[CapabilityDisplayName]struct{}{ @@ -50,6 +55,7 @@ var CapabilityDisplayNames = map[CapabilityDisplayName]struct{}{ KubeMonCapability.DisplayName: {}, MetricsIngestCapability.DisplayName: {}, DynatraceApiCapability.DisplayName: {}, + DebuggingCapability.DisplayName: {}, } type ActiveGate struct { diff --git a/pkg/controllers/dynakube/activegate/capability/capability.go b/pkg/controllers/dynakube/activegate/capability/capability.go index 2d34468f3c..6224713353 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability.go +++ b/pkg/controllers/dynakube/activegate/capability/capability.go @@ -19,6 +19,7 @@ var ( activegate.RoutingCapability.DisplayName: routingBase, activegate.MetricsIngestCapability.DisplayName: metricsIngestBase, activegate.DynatraceApiCapability.DisplayName: dynatraceApiBase, + activegate.DebuggingCapability.DisplayName: debuggingBase, } ) @@ -153,6 +154,16 @@ func dynatraceApiBase() *capabilityBase { return &c } +func debuggingBase() *capabilityBase { + c := capabilityBase{ + shortName: activegate.DebuggingCapability.ShortName, + argName: activegate.DebuggingCapability.ArgumentName, + displayName: string(activegate.DebuggingCapability.DisplayName), + } + + return &c +} + func GenerateActiveGateCapabilities(dk *dynakube.DynaKube) []Capability { return []Capability{ NewMultiCapability(dk), diff --git a/pkg/controllers/dynakube/activegate/capability/capability_test.go b/pkg/controllers/dynakube/activegate/capability/capability_test.go index c05bb186d9..8b551b9265 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability_test.go +++ b/pkg/controllers/dynakube/activegate/capability/capability_test.go @@ -18,6 +18,7 @@ const ( testApiUrl = "https://demo.dev.dynatracelabs.com/api" expectedShortName = "activegate" expectedArgName = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface" + expectedArgNameWithDebugging = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,debugging" expectedArgNameWithExtensions = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller" expectedArgNameWithExtensionsOnly = "extension_controller" expectedArgNameWithOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest_enabled,otlp_ingest" @@ -181,6 +182,17 @@ func TestNewMultiCapabilityWithOTLPingestAndTelemetryService(t *testing.T) { }) } +func TestNewMultiCapabilityWithDebugging(t *testing.T) { + t.Run(`creates new multicapability with debugging capability enabled`, func(t *testing.T) { + dk := buildDynakube(append(capabilities, activegate.DebuggingCapability.DisplayName), false, false, false) + mc := NewMultiCapability(dk) + require.NotNil(t, mc) + assert.True(t, mc.Enabled()) + assert.Equal(t, expectedShortName, mc.ShortName()) + assert.Equal(t, expectedArgNameWithDebugging, mc.ArgName()) + }) +} + func TestBuildServiceDomainNameForDNSEntryPoint(t *testing.T) { actual := buildServiceDomainName("test-name", "test-namespace", "test-component-feature") assert.NotEmpty(t, actual) diff --git a/test/features/activegate/activegate.go b/test/features/activegate/activegate.go index a887bcf145..54ca51fe0f 100644 --- a/test/features/activegate/activegate.go +++ b/test/features/activegate/activegate.go @@ -192,6 +192,7 @@ func assertExpectedModulesAreActive(t *testing.T, log string) { "kubernetes_monitoring", "odin_collector", "metrics_ingest", + "debugging", } head := strings.SplitAfter(log, "[, ModulesManager] Modules:") diff --git a/test/helpers/components/dynakube/options.go b/test/helpers/components/dynakube/options.go index a0a89f3cb5..9f62a73cc0 100644 --- a/test/helpers/components/dynakube/options.go +++ b/test/helpers/components/dynakube/options.go @@ -65,6 +65,7 @@ func WithActiveGate() Option { activegate.DynatraceApiCapability.DisplayName, activegate.RoutingCapability.DisplayName, activegate.MetricsIngestCapability.DisplayName, + activegate.DebuggingCapability.DisplayName, }, } } From 305db87b6fae1d7fb85e28331cafd5127f3d2508 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Thu, 6 Feb 2025 09:47:46 +0100 Subject: [PATCH 177/426] Increase CSI driver server container livenessProbe default timeouts (#4406) (#4416) --- .../chart/default/templates/Common/csi/daemonset.yaml | 8 ++++---- .../chart/default/tests/Common/csi/daemonset_test.yaml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/config/helm/chart/default/templates/Common/csi/daemonset.yaml b/config/helm/chart/default/templates/Common/csi/daemonset.yaml index 7ec83f1f02..f23dcfebb6 100644 --- a/config/helm/chart/default/templates/Common/csi/daemonset.yaml +++ b/config/helm/chart/default/templates/Common/csi/daemonset.yaml @@ -114,10 +114,10 @@ spec: path: /healthz port: healthz scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 5 + initialDelaySeconds: 15 + periodSeconds: 15 successThreshold: 1 - timeoutSeconds: 4 + timeoutSeconds: 10 {{- end }} ports: - containerPort: 9808 @@ -243,7 +243,7 @@ spec: args: - --csi-address=/csi/csi.sock - --health-port=9808 - - --probe-timeout=4s + - --probe-timeout=9s command: - livenessprobe resources: diff --git a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml index 35c0205547..4aa19761a9 100644 --- a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml @@ -187,10 +187,10 @@ tests: path: "/healthz" port: healthz scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 5 + initialDelaySeconds: 15 + periodSeconds: 15 successThreshold: 1 - timeoutSeconds: 4 + timeoutSeconds: 10 name: server ports: - containerPort: 9808 @@ -336,7 +336,7 @@ tests: - args: - "--csi-address=/csi/csi.sock" - "--health-port=9808" - - "--probe-timeout=4s" + - "--probe-timeout=9s" command: - livenessprobe image: image-name From 7856d831eb54031b78ddb0c0da25ff4cfc3de9f1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:47:52 +0100 Subject: [PATCH 178/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1738816380 (main) (#4415) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7c9c3c6c90..f0a4cc4cd5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1738659858@sha256:a434c4babbc08a8d0a7f227154b46f0df0a4b701af0796716cb5305807b2b2b3 AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1738816380@sha256:7e85855f6925e03f91b5c51f07886ff1c18c6ec69b5fc65491428a899da914a2 AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1738643550@sha256:95356f4377e6ca6b8ad56fe33af8258d48010476aac287031dd572cfafceb285 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From b3ecfc16ac8a925996f52914c058a50426678ad3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:41:25 +0000 Subject: [PATCH 179/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1738814488 (main) (#4414) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f0a4cc4cd5..96f8a68cc4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1738816380@sha256:7e85855f6925e03f91b5c51f07886ff1c18c6ec69b5fc65491428a899da914a2 AS base -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1738643550@sha256:95356f4377e6ca6b8ad56fe33af8258d48010476aac287031dd572cfafceb285 AS dependency +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1738814488@sha256:be214e191bbe3f4d0f16a5a4f5642e1f32fccd6fae7d2b6c6acb066ba51fb507 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 29a6ade4a54ec2ccb070409ab736b72be7af6887 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Thu, 6 Feb 2025 13:23:24 +0100 Subject: [PATCH 180/426] Add rbac for otel collector with open signal (#4403) --- .../clusterole-telemetry-endpoints.yaml | 67 +++++++++++++++ ...erviceaccount-opentelemetry-collector.yaml | 2 +- .../helm/chart/default/templates/_labels.tpl | 2 +- .../clusterrole-telemetry-endpoints_test.yaml | 85 +++++++++++++++++++ ...eaccount-opentelemetry-collector_test.yaml | 1 + config/helm/chart/default/values.yaml | 3 + 6 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 config/helm/chart/default/templates/Common/opentelemetry-collector/clusterole-telemetry-endpoints.yaml create mode 100644 config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml diff --git a/config/helm/chart/default/templates/Common/opentelemetry-collector/clusterole-telemetry-endpoints.yaml b/config/helm/chart/default/templates/Common/opentelemetry-collector/clusterole-telemetry-endpoints.yaml new file mode 100644 index 0000000000..6a3449bd03 --- /dev/null +++ b/config/helm/chart/default/templates/Common/opentelemetry-collector/clusterole-telemetry-endpoints.yaml @@ -0,0 +1,67 @@ +{{- if .Values.rbac.telemetryService.create }} +# Copyright 2021 Dynatrace LLC + +# 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. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: dynatrace-telemetry-service + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.openTelemetryCollectorLabels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - pods + - namespaces + - nodes + verbs: + - get + - watch + - list + - apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - list + - watch + {{- if (eq (include "dynatrace-operator.openshiftOrOlm" .) "true") }} + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use + {{ end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dynatrace-telemetry-service + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.openTelemetryCollectorLabels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: dynatrace-telemetry-service +subjects: + - kind: ServiceAccount + name: dynatrace-opentelemetry-collector + namespace: {{ .Release.Namespace }} +{{ end }} diff --git a/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml b/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml index 3f59b77e3b..119e411e44 100644 --- a/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml +++ b/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml @@ -1,4 +1,4 @@ -{{- if .Values.rbac.extensions.create }} +{{- if or (.Values.rbac.extensions.create) (.Values.rbac.telemetryService.create) }} # Copyright 2021 Dynatrace LLC # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/config/helm/chart/default/templates/_labels.tpl b/config/helm/chart/default/templates/_labels.tpl index 7a293eff6f..fab11a00bd 100644 --- a/config/helm/chart/default/templates/_labels.tpl +++ b/config/helm/chart/default/templates/_labels.tpl @@ -114,7 +114,7 @@ OpenTelemetry Collector (OTelC) labels */}} {{- define "dynatrace-operator.openTelemetryCollectorLabels" -}} {{ include "dynatrace-operator.commonLabels" . }} -app.kubernetes.io/component: dynatrace-extensions-collector +app.kubernetes.io/component: dynatrace-opentelemetry-collector {{- end -}} {{/* diff --git a/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml b/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml new file mode 100644 index 0000000000..860c1c5012 --- /dev/null +++ b/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml @@ -0,0 +1,85 @@ +suite: test clusterrole for the dynatrace OpenTelemetry collector endpoints +templates: + - Common/opentelemetry-collector/clusterole-telemetry-endpoints.yaml +tests: + - it: ClusterRole and ClusterRoleBinding exists + asserts: + - hasDocuments: + count: 2 + + - it: ClusterRole has correct permissions + documentIndex: 0 + asserts: + - isKind: + of: ClusterRole + - equal: + path: metadata.name + value: dynatrace-telemetry-service + - isNotEmpty: + path: metadata.labels + - isNotEmpty: + path: rules + - contains: + path: rules + content: + apiGroups: + - "" + resources: + - pods + - namespaces + - nodes + verbs: + - get + - watch + - list + - contains: + path: rules + content: + apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - list + - watch + - it: ClusterRole should exist with extra permissions for openshift + documentIndex: 0 + set: + platform: openshift + asserts: + - isKind: + of: ClusterRole + - equal: + path: metadata.name + value: dynatrace-telemetry-service + - isNotEmpty: + path: metadata.labels + - contains: + path: rules + content: + apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use + - it: ClusterRoleBinding exists + documentIndex: 1 + asserts: + - isKind: + of: ClusterRoleBinding + - equal: + path: metadata.name + value: dynatrace-telemetry-service + - isNotEmpty: + path: metadata.labels + + - it: shouldn't exist if turned off + set: + rbac.telemetryService.create: false + asserts: + - hasDocuments: + count: 0 diff --git a/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml b/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml index eb9736f84a..6dab0b2a2f 100644 --- a/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml +++ b/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml @@ -20,6 +20,7 @@ tests: - it: shouldn't exist if turned off set: rbac.extensions.create: false + rbac.telemetryService.create: false asserts: - hasDocuments: count: 0 diff --git a/config/helm/chart/default/values.yaml b/config/helm/chart/default/values.yaml index b68a97a06b..65c79db4aa 100644 --- a/config/helm/chart/default/values.yaml +++ b/config/helm/chart/default/values.yaml @@ -208,6 +208,9 @@ rbac: extensions: create: true annotations: {} + telemetryService: + create: true + annotations: {} logMonitoring: create: true annotations: {} From 574d51394f914f207095663f1ac2fbf457fe20c2 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 6 Feb 2025 14:45:43 +0100 Subject: [PATCH 181/426] Add logic to download CodeModules in separate Job (#4392) --- .../templates/Common/csi/daemonset.yaml | 9 + .../templates/Common/csi/role-csi.yaml | 2 +- .../tests/Common/csi/daemonset_test.yaml | 11 +- .../tests/Common/csi/role-csi_test.yaml | 2 +- doc/api/feature-flags.md | 8 +- pkg/api/v1beta3/dynakube/feature_flags.go | 12 +- pkg/controllers/csi/config.go | 1 + pkg/controllers/csi/metadata/path_resolver.go | 8 + .../csi/provisioner/cleanup/run.go | 1 + pkg/controllers/csi/provisioner/controller.go | 16 +- .../csi/provisioner/controller_test.go | 83 ++++++++ pkg/controllers/csi/provisioner/install.go | 38 +++- .../codemodule/installer/image/installer.go | 2 +- .../codemodule/installer/job/bootstrapper.go | 95 +++++++++ .../installer/job/bootstrapper_test.go | 185 ++++++++++++++++++ .../codemodule/installer/job/config.go | 9 + .../codemodule/installer/job/installer.go | 117 +++++++++++ .../installer/job/installer_test.go | 175 +++++++++++++++++ .../codemodule/installer/url/installer.go | 2 +- pkg/util/kubeobjects/env/env.go | 25 +++ pkg/util/kubeobjects/env/env_test.go | 43 ++++ pkg/util/kubeobjects/internal/query/query.go | 8 +- pkg/util/kubeobjects/job/builder.go | 108 ++++++++++ pkg/util/kubeobjects/job/query.go | 45 +++++ pkg/util/kubeobjects/labels/labels.go | 1 + 25 files changed, 981 insertions(+), 25 deletions(-) create mode 100644 pkg/injection/codemodule/installer/job/bootstrapper.go create mode 100644 pkg/injection/codemodule/installer/job/bootstrapper_test.go create mode 100644 pkg/injection/codemodule/installer/job/config.go create mode 100644 pkg/injection/codemodule/installer/job/installer.go create mode 100644 pkg/injection/codemodule/installer/job/installer_test.go create mode 100644 pkg/util/kubeobjects/job/builder.go create mode 100644 pkg/util/kubeobjects/job/query.go diff --git a/config/helm/chart/default/templates/Common/csi/daemonset.yaml b/config/helm/chart/default/templates/Common/csi/daemonset.yaml index f23dcfebb6..a9379b2ebf 100644 --- a/config/helm/chart/default/templates/Common/csi/daemonset.yaml +++ b/config/helm/chart/default/templates/Common/csi/daemonset.yaml @@ -166,6 +166,15 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.namespace + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: TOLERATIONS + value: '{{ .Values.csidriver.tolerations | toJson }}' + - name: CSI_DATA_DIR + value: {{ include "dynatrace-operator.CSIDataDir" . }} {{- if .Values.csidriver.cleanupPeriod }} - name: CLEANUP_PERIOD value: "{{ .Values.csidriver.cleanupPeriod}}" diff --git a/config/helm/chart/default/templates/Common/csi/role-csi.yaml b/config/helm/chart/default/templates/Common/csi/role-csi.yaml index 9002ff6885..c933e13804 100644 --- a/config/helm/chart/default/templates/Common/csi/role-csi.yaml +++ b/config/helm/chart/default/templates/Common/csi/role-csi.yaml @@ -38,7 +38,7 @@ rules: - list - watch - apiGroups: - - "" + - batch resources: - jobs verbs: diff --git a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml index 4aa19761a9..3e8a35a649 100644 --- a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml @@ -49,7 +49,7 @@ tests: csidriver.cleanupPeriod: "5m" asserts: - equal: - path: spec.template.spec.containers[1].env[1] #provisioner + path: spec.template.spec.containers[1].env[4] #provisioner value: name: CLEANUP_PERIOD value: "5m" @@ -236,6 +236,15 @@ tests: fieldRef: apiVersion: v1 fieldPath: metadata.namespace + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: TOLERATIONS + value: '[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master","operator":"Exists"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane","operator":"Exists"}]' + - name: CSI_DATA_DIR + value: /var/lib/kubelet/plugins/csi.oneagent.dynatrace.com/data - name: modules.json value: | { diff --git a/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml b/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml index 2e81785642..fc521097fc 100644 --- a/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml @@ -53,7 +53,7 @@ tests: - list - watch - apiGroups: - - "" + - "batch" resources: - jobs verbs: diff --git a/doc/api/feature-flags.md b/doc/api/feature-flags.md index 2e1b81ad51..38e3a90b68 100644 --- a/doc/api/feature-flags.md +++ b/doc/api/feature-flags.md @@ -54,10 +54,10 @@ const ( AnnotationFeatureEnforcementMode = AnnotationFeaturePrefix + "enforcement-mode" // CSI. - AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" - AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" - AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureCodeModulesRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remoteImageDownload" + AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" + AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" + AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" + AnnotationFeatureDownloadViaJob = AnnotationFeatureCodeModulesPrefix + "remoteImageDownload" ) ``` diff --git a/pkg/api/v1beta3/dynakube/feature_flags.go b/pkg/api/v1beta3/dynakube/feature_flags.go index c3eb2e0b51..92c3c13691 100644 --- a/pkg/api/v1beta3/dynakube/feature_flags.go +++ b/pkg/api/v1beta3/dynakube/feature_flags.go @@ -70,10 +70,10 @@ const ( AnnotationFeatureEnforcementMode = AnnotationFeaturePrefix + "enforcement-mode" // CSI. - AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" - AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" - AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureCodeModulesRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remoteImageDownload" + AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" + AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" + AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" + AnnotationFeatureDownloadViaJob = AnnotationFeatureCodeModulesPrefix + "remoteImageDownload" falsePhrase = "false" truePhrase = "true" @@ -270,8 +270,8 @@ func (dk *DynaKube) FeatureReadOnlyCsiVolume() bool { return dk.getFeatureFlagRaw(AnnotationFeatureReadOnlyCsiVolume) == truePhrase } -func (dk *DynaKube) FeatureRemoteImageDownload() bool { - return dk.getFeatureFlagRaw(AnnotationFeatureCodeModulesRemoteImageDownload) == truePhrase +func (dk *DynaKube) FeatureDownloadViaJob() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureDownloadViaJob) == truePhrase } func (dk *DynaKube) FeatureInjectionFailurePolicy() string { diff --git a/pkg/controllers/csi/config.go b/pkg/controllers/csi/config.go index a62e57aaf0..b4ffcebf64 100644 --- a/pkg/controllers/csi/config.go +++ b/pkg/controllers/csi/config.go @@ -30,6 +30,7 @@ const ( OverlayVarDirPath = "var" OverlayWorkDirPath = "work" SharedAgentBinDir = "codemodules" + SharedJobWorkDir = "work" SharedAppMountsDir = "appmounts" SharedAgentConfigDir = "config" diff --git a/pkg/controllers/csi/metadata/path_resolver.go b/pkg/controllers/csi/metadata/path_resolver.go index 72fb8bce78..2414d57409 100644 --- a/pkg/controllers/csi/metadata/path_resolver.go +++ b/pkg/controllers/csi/metadata/path_resolver.go @@ -23,6 +23,14 @@ func (pr PathResolver) AgentSharedBinaryDirBase() string { return filepath.Join(pr.RootDir, dtcsi.SharedAgentBinDir) } +func (pr PathResolver) AgentJobWorkDirBase() string { + return filepath.Join(pr.RootDir, dtcsi.SharedJobWorkDir) +} + +func (pr PathResolver) AgentJobWorkDirForJob(jobName string) string { + return filepath.Join(pr.AgentJobWorkDirBase(), jobName) +} + func (pr PathResolver) AgentSharedBinaryDirForAgent(versionOrDigest string) string { return filepath.Join(pr.AgentSharedBinaryDirBase(), versionOrDigest) } diff --git a/pkg/controllers/csi/provisioner/cleanup/run.go b/pkg/controllers/csi/provisioner/cleanup/run.go index 3ea503f5a9..035ff2eeab 100644 --- a/pkg/controllers/csi/provisioner/cleanup/run.go +++ b/pkg/controllers/csi/provisioner/cleanup/run.go @@ -89,6 +89,7 @@ func (c *Cleaner) getFilesystemState() (fsState fsState, err error) { //nolint:r for _, fileInfo := range rootSubDirs { if !fileInfo.IsDir() || fileInfo.Name() == dtcsi.SharedAppMountsDir || + fileInfo.Name() == dtcsi.SharedJobWorkDir || fileInfo.Name() == dtcsi.SharedAgentBinDir { continue } diff --git a/pkg/controllers/csi/provisioner/controller.go b/pkg/controllers/csi/provisioner/controller.go index f5bd45f54d..17ce40b9c3 100644 --- a/pkg/controllers/csi/provisioner/controller.go +++ b/pkg/controllers/csi/provisioner/controller.go @@ -29,6 +29,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/image" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/job" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/url" "github.com/pkg/errors" "github.com/spf13/afero" @@ -48,15 +49,18 @@ const ( type urlInstallerBuilder func(afero.Fs, dtclient.Client, *url.Properties) installer.Installer type imageInstallerBuilder func(context.Context, afero.Fs, *image.Properties) (installer.Installer, error) +type jobInstallerBuilder func(context.Context, afero.Fs, *job.Properties) installer.Installer // OneAgentProvisioner reconciles a DynaKube object type OneAgentProvisioner struct { - apiReader client.Reader - fs afero.Fs + apiReader client.Reader + kubeClient client.Client + fs afero.Fs dynatraceClientBuilder dynatraceclient.Builder urlInstallerBuilder urlInstallerBuilder imageInstallerBuilder imageInstallerBuilder + jobInstallerBuilder jobInstallerBuilder cleaner *cleanup.Cleaner path metadata.PathResolver } @@ -68,11 +72,13 @@ func NewOneAgentProvisioner(mgr manager.Manager, opts dtcsi.CSIOptions) *OneAgen return &OneAgentProvisioner{ apiReader: mgr.GetAPIReader(), + kubeClient: mgr.GetClient(), fs: fs, path: path, dynatraceClientBuilder: dynatraceclient.NewBuilder(mgr.GetAPIReader()), urlInstallerBuilder: url.NewUrlInstaller, imageInstallerBuilder: image.NewImageInstaller, + jobInstallerBuilder: job.NewInstaller, cleaner: cleanup.New(afero.Afero{Fs: fs}, mgr.GetAPIReader(), path, mount.New("")), } } @@ -129,7 +135,11 @@ func (provisioner *OneAgentProvisioner) Reconcile(ctx context.Context, request r } err = provisioner.installAgent(ctx, dk) - if err != nil { + if err != nil && errors.Is(err, errNotReady) { + log.Info(err.Error(), "dynakube", dk.Name) + + return reconcile.Result{RequeueAfter: notReadyRequeueDuration}, nil + } else if err != nil { return reconcile.Result{}, err } diff --git a/pkg/controllers/csi/provisioner/controller_test.go b/pkg/controllers/csi/provisioner/controller_test.go index 7fdd4ae88c..cdb78874db 100644 --- a/pkg/controllers/csi/provisioner/controller_test.go +++ b/pkg/controllers/csi/provisioner/controller_test.go @@ -18,6 +18,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/image" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/job" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/url" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/processmoduleconfig" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" @@ -117,6 +118,53 @@ func TestReconcile(t *testing.T) { installer.AssertCalled(t, "InstallAgent", mock.Anything, mock.Anything) }) + t.Run("dynakube with job => job installer used, dtclient not created, no error", func(t *testing.T) { + dk := createDynaKubeWithJobFF(t) + prov := createProvisioner(t, dk, createPMCSecret(t, dk)) + installer := createSuccessfulInstaller(t) + prov.jobInstallerBuilder = mockJobInstallerBuilder(t, installer) + createPMCSourceFile(t, prov, dk) + + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) + require.NoError(t, err) + require.NotNil(t, result) + assert.Equal(t, defaultRequeueDuration, result.RequeueAfter) + + assert.True(t, areFsDirsCreated(t, prov, dk)) + installer.AssertCalled(t, "InstallAgent", mock.Anything, mock.Anything) + }) + + t.Run("dynakube with job => job installer used, back-off when not ready, no error", func(t *testing.T) { + dk := createDynaKubeWithJobFF(t) + prov := createProvisioner(t, dk, createPMCSecret(t, dk)) + installer := createNotReadyInstaller(t) + prov.jobInstallerBuilder = mockJobInstallerBuilder(t, installer) + createPMCSourceFile(t, prov, dk) + + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) + require.NoError(t, err) + require.NotNil(t, result) + assert.Equal(t, notReadyRequeueDuration, result.RequeueAfter) + + assert.True(t, areFsDirsCreated(t, prov, dk)) + installer.AssertCalled(t, "InstallAgent", mock.Anything, mock.Anything) + }) + + t.Run("dynakube with job => job installer used, with error", func(t *testing.T) { + dk := createDynaKubeWithJobFF(t) + prov := createProvisioner(t, dk, createPMCSecret(t, dk)) + installer := createFailingInstaller(t) + prov.jobInstallerBuilder = mockJobInstallerBuilder(t, installer) + createPMCSourceFile(t, prov, dk) + + result, err := prov.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(dk)}) + require.Error(t, err) + require.NotNil(t, result) + + assert.True(t, areFsDirsCreated(t, prov, dk)) + installer.AssertCalled(t, "InstallAgent", mock.Anything, mock.Anything) + }) + t.Run("installer fails => error", func(t *testing.T) { dk := createDynaKubeWithImage(t) prov := createProvisioner(t, dk) @@ -194,6 +242,24 @@ func createDynaKubeWithImage(t *testing.T) *dynakube.DynaKube { return dk } +func createDynaKubeWithJobFF(t *testing.T) *dynakube.DynaKube { + t.Helper() + + dk := createDynaKubeBase(t) + imageId := "test-image" + dk.Spec.OneAgent = oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{CodeModulesImage: imageId}, + }, + } + dk.Status.CodeModules.ImageID = imageId + dk.Annotations = map[string]string{ + dynakube.AnnotationFeatureDownloadViaJob: "true", + } + + return dk +} + func createNotReadyDynaKube(t *testing.T) *dynakube.DynaKube { t.Helper() @@ -236,6 +302,15 @@ func createSuccessfulInstaller(t *testing.T) *installermock.Installer { return m } +func createNotReadyInstaller(t *testing.T) *installermock.Installer { + t.Helper() + + m := installermock.NewInstaller(t) + m.On("InstallAgent", mock.Anything, mock.Anything).Return(false, nil) + + return m +} + func createFailingInstaller(t *testing.T) *installermock.Installer { t.Helper() @@ -261,6 +336,14 @@ func mockImageInstallerBuilder(t *testing.T, mockedInstaller *installermock.Inst } } +func mockJobInstallerBuilder(t *testing.T, mockedInstaller *installermock.Installer) jobInstallerBuilder { + t.Helper() + + return func(_ context.Context, _ afero.Fs, _ *job.Properties) installer.Installer { + return mockedInstaller + } +} + func createToken(t *testing.T, dk *dynakube.DynaKube) *corev1.Secret { t.Helper() diff --git a/pkg/controllers/csi/provisioner/install.go b/pkg/controllers/csi/provisioner/install.go index e980860a85..816cfd91f0 100644 --- a/pkg/controllers/csi/provisioner/install.go +++ b/pkg/controllers/csi/provisioner/install.go @@ -3,6 +3,8 @@ package csiprovisioner import ( "context" "encoding/base64" + "errors" + "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/arch" @@ -10,11 +12,16 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/image" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/job" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/symlink" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/url" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/processmoduleconfig" ) +const notReadyRequeueDuration = 30 * time.Second + +var errNotReady = errors.New("download job is not ready yet") + func (provisioner *OneAgentProvisioner) installAgent(ctx context.Context, dk dynakube.DynaKube) error { agentInstaller, err := provisioner.getInstaller(ctx, dk) if err != nil { @@ -25,11 +32,15 @@ func (provisioner *OneAgentProvisioner) installAgent(ctx context.Context, dk dyn targetDir := provisioner.getTargetDir(dk) - _, err = agentInstaller.InstallAgent(ctx, targetDir) + ready, err := agentInstaller.InstallAgent(ctx, targetDir) if err != nil { return err } + if !ready { + return errNotReady + } + err = provisioner.createLatestVersionSymlink(dk, targetDir) if err != nil { return err @@ -39,7 +50,10 @@ func (provisioner *OneAgentProvisioner) installAgent(ctx context.Context, dk dyn } func (provisioner *OneAgentProvisioner) getInstaller(ctx context.Context, dk dynakube.DynaKube) (installer.Installer, error) { - if dk.OneAgent().GetCustomCodeModulesImage() != "" { + switch { + case dk.FeatureDownloadViaJob(): + return provisioner.getJobInstaller(ctx, dk), nil + case dk.OneAgent().GetCustomCodeModulesImage() != "": props := &image.Properties{ ImageUri: dk.OneAgent().GetCodeModulesImage(), ApiReader: provisioner.apiReader, @@ -53,7 +67,7 @@ func (provisioner *OneAgentProvisioner) getInstaller(ctx context.Context, dk dyn } return imageInstaller, nil - } else { + default: dtc, err := buildDtc(provisioner, ctx, dk) if err != nil { return nil, err @@ -76,6 +90,24 @@ func (provisioner *OneAgentProvisioner) getInstaller(ctx context.Context, dk dyn } } +func (provisioner *OneAgentProvisioner) getJobInstaller(ctx context.Context, dk dynakube.DynaKube) installer.Installer { + imageUri := dk.OneAgent().GetCustomCodeModulesImage() + if imageUri == "" { + imageUri = "public.ecr.aws/dynatrace/dynatrace-codemodules:" + dk.OneAgent().GetCodeModulesVersion() + } + + props := &job.Properties{ + ImageUri: imageUri, + Owner: &dk, + PullSecrets: dk.PullSecretNames(), + ApiReader: provisioner.apiReader, + Client: provisioner.kubeClient, + PathResolver: provisioner.path, + } + + return provisioner.jobInstallerBuilder(ctx, provisioner.fs, props) +} + func (provisioner *OneAgentProvisioner) getTargetDir(dk dynakube.DynaKube) string { var dirName string diff --git a/pkg/injection/codemodule/installer/image/installer.go b/pkg/injection/codemodule/installer/image/installer.go index 9a555eb374..0a6ede3dc3 100644 --- a/pkg/injection/codemodule/installer/image/installer.go +++ b/pkg/injection/codemodule/installer/image/installer.go @@ -64,7 +64,7 @@ func (installer *Installer) InstallAgent(_ context.Context, targetDir string) (b if installer.isAlreadyPresent(targetDir) { log.Info("agent already installed", "image", installer.props.ImageUri, "target dir", targetDir) - return false, nil + return true, nil } err := installer.fs.MkdirAll(installer.props.PathResolver.AgentSharedBinaryDirBase(), common.MkDirFileMode) diff --git a/pkg/injection/codemodule/installer/job/bootstrapper.go b/pkg/injection/codemodule/installer/job/bootstrapper.go new file mode 100644 index 0000000000..f96b5de186 --- /dev/null +++ b/pkg/injection/codemodule/installer/job/bootstrapper.go @@ -0,0 +1,95 @@ +package job + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + jobutil "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/job" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" +) + +const ( + namePrefix = "codemodule-download-" + + volumeName = "dynatrace-codemodules" + + bootstrapCommand = "/opt/dynatrace/bin/bootstrap" + codeModuleSource = "/opt/dynatrace/oneagent" +) + +func (inst *Installer) buildJobName() string { + hashPostfix, _ := hasher.GenerateHash(inst.props.ImageUri + inst.nodeName) + + return namePrefix + hashPostfix +} + +func (inst *Installer) buildJob(name, targetDir string) (*batchv1.Job, error) { + tolerations, err := env.GetTolerations() + if err != nil { + log.Info("failed to get tolerations from env") + + return nil, err + } + + appLabels := labels.NewAppLabels(labels.CodeModuleComponentLabel, inst.props.Owner.GetName(), "", "") + + container := corev1.Container{ + Name: "codemodule-download", + Image: inst.props.ImageUri, + ImagePullPolicy: corev1.PullIfNotPresent, + Command: []string{bootstrapCommand}, + VolumeMounts: []corev1.VolumeMount{ + { + Name: volumeName, + MountPath: inst.props.PathResolver.RootDir, + }, + }, + SecurityContext: &corev1.SecurityContext{ // TODO: Use the SecurityContext from the `provisioner` container + RunAsUser: ptr.To(int64(0)), + ReadOnlyRootFilesystem: ptr.To(true), + SELinuxOptions: &corev1.SELinuxOptions{ + Level: "s0", + }, + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + }, + } + + hostVolume := corev1.Volume{ + Name: volumeName, + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: env.GetCSIDataDir(), + }, + }, + } + + container.Args = inst.buildArgs(name, targetDir) + + annotations := map[string]string{ + webhook.AnnotationDynatraceInject: "false", + } + + return jobutil.Build(inst.props.Owner, name, container, + jobutil.SetPodAnnotations(annotations), + jobutil.SetNodeName(inst.nodeName), + jobutil.SetPullSecret(inst.props.PullSecrets...), + jobutil.SetTolerations(tolerations), + jobutil.SetAllLabels(appLabels.BuildLabels(), map[string]string{}, appLabels.BuildLabels(), map[string]string{}), + jobutil.SetVolumes([]corev1.Volume{hostVolume}), + jobutil.SetOnFailureRestartPolicy(), + jobutil.SetAutomountServiceAccountToken(false), + ) +} + +func (inst *Installer) buildArgs(jobName, targetDir string) []string { + return []string{ + "--source=" + codeModuleSource, + "--target=" + targetDir, + "--work=" + inst.props.PathResolver.AgentJobWorkDirForJob(jobName), + } +} diff --git a/pkg/injection/codemodule/installer/job/bootstrapper_test.go b/pkg/injection/codemodule/installer/job/bootstrapper_test.go new file mode 100644 index 0000000000..0931417e50 --- /dev/null +++ b/pkg/injection/codemodule/installer/job/bootstrapper_test.go @@ -0,0 +1,185 @@ +package job + +import ( + "encoding/json" + "slices" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestBuildJobName(t *testing.T) { + t.Run("job names are unique", func(t *testing.T) { + uris := []string{"test1.com", "test2.com", "test3.com", "test4.com", "test5.com"} + nodeNames := []string{"node1", "node2", "node3", "node4", "node5"} + + jobNames := []string{} + + for i := range nodeNames { + for j := range uris { + props := &Properties{ + ImageUri: uris[j], + } + inst := &Installer{ + nodeName: nodeNames[i], + props: props, + } + jobNames = append(jobNames, inst.buildJobName()) + } + } + + slices.Sort(jobNames) + jobNames = slices.Compact(jobNames) + + assert.Len(t, jobNames, len(nodeNames)*len(uris)) + }) +} + +func TestBuildArgs(t *testing.T) { + t.Run("args are built correctly", func(t *testing.T) { + targetDir := "1.2.3" + jobName := "test-job-123" + props := &Properties{ + PathResolver: metadata.PathResolver{RootDir: "root"}, + } + inst := &Installer{ + props: props, + } + + args := inst.buildArgs(jobName, targetDir) + + require.Len(t, args, 3) + assert.Contains(t, args[0], "--source") + assert.Contains(t, args[0], codeModuleSource) + + assert.Contains(t, args[1], "--target") + assert.Contains(t, args[1], targetDir) + + assert.Contains(t, args[2], "--work") + assert.Contains(t, args[2], props.PathResolver.RootDir) + assert.Contains(t, args[2], jobName) + }) +} + +func TestBuildJob(t *testing.T) { + owner := dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-dk", + }, + } + name := "job-1" + imageURI := "test:5000/repo" + nodeName := "node1" + targetDir := "1.2.3" + pullSecrets := []string{"secret-1", "secret-2"} + + t.Run("job created correctly", func(t *testing.T) { + tolerations := setupTolerations(t) + dataDir := setupDataDir(t) + + props := &Properties{ + Owner: &owner, + ImageUri: imageURI, + PullSecrets: pullSecrets, + PathResolver: metadata.PathResolver{RootDir: "root"}, + } + inst := &Installer{ + nodeName: nodeName, + props: props, + } + + job, err := inst.buildJob(name, targetDir) + require.NoError(t, err) + require.NotNil(t, job) + + // Global/pod level checks + assert.Equal(t, name, job.Name) + assert.NotNil(t, job.Labels) + assert.NotNil(t, job.Spec.Template.Labels) + assert.Empty(t, job.Spec.Selector) // the Job objects handles this by default, our generated MatchLabels wound't even work + + assert.Equal(t, tolerations, job.Spec.Template.Spec.Tolerations) + assert.Equal(t, nodeName, job.Spec.Template.Spec.NodeName) + assert.False(t, *job.Spec.Template.Spec.AutomountServiceAccountToken) + assert.Equal(t, corev1.RestartPolicyOnFailure, job.Spec.Template.Spec.RestartPolicy) + + require.Len(t, job.Spec.Template.Spec.Volumes, 1) + require.NotNil(t, job.Spec.Template.Spec.Volumes[0].HostPath) + assert.Equal(t, dataDir, job.Spec.Template.Spec.Volumes[0].HostPath.Path) + + require.Len(t, job.Spec.Template.Spec.ImagePullSecrets, len(pullSecrets)) + + for i, ps := range pullSecrets { + assert.Equal(t, ps, job.Spec.Template.Spec.ImagePullSecrets[i].Name) + } + + // Container level checks + require.Len(t, job.Spec.Template.Spec.Containers, 1) + container := job.Spec.Template.Spec.Containers[0] + + assert.Equal(t, imageURI, container.Image) + assert.Contains(t, container.Command, bootstrapCommand) + assert.NotEmpty(t, container.Args) + assert.NotEmpty(t, container.SecurityContext) + + require.Len(t, container.VolumeMounts, 1) + assert.Equal(t, job.Spec.Template.Spec.Volumes[0].Name, container.VolumeMounts[0].Name) + assert.Equal(t, props.PathResolver.RootDir, container.VolumeMounts[0].MountPath) + }) + + t.Run("job create fail, can't parse tolerations", func(t *testing.T) { + setupMalformedTolerations(t) + + inst := &Installer{} + + _, err := inst.buildJob(name, targetDir) + require.Error(t, err) + }) +} + +func setupTolerations(t *testing.T) []corev1.Toleration { + t.Helper() + + expected := []corev1.Toleration{ + { + Key: "key1", + Operator: corev1.TolerationOpEqual, + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: corev1.TolerationOpEqual, + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + }, + } + + raw, err := json.Marshal(expected) + require.NoError(t, err) + + t.Setenv(env.Tolerations, string(raw)) + + return expected +} + +func setupMalformedTolerations(t *testing.T) { + t.Helper() + t.Setenv(env.Tolerations, "{$^$&^%}") +} + +func setupDataDir(t *testing.T) string { + t.Helper() + + dataDir := "test/data" + + t.Setenv(env.CSIDataDir, dataDir) + + return dataDir +} diff --git a/pkg/injection/codemodule/installer/job/config.go b/pkg/injection/codemodule/installer/job/config.go new file mode 100644 index 0000000000..e84e85bbc4 --- /dev/null +++ b/pkg/injection/codemodule/installer/job/config.go @@ -0,0 +1,9 @@ +package job + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/logd" +) + +var ( + log = logd.Get().WithName("oneagent-job") +) diff --git a/pkg/injection/codemodule/installer/job/installer.go b/pkg/injection/codemodule/installer/job/installer.go new file mode 100644 index 0000000000..cd9cd8df14 --- /dev/null +++ b/pkg/injection/codemodule/installer/job/installer.go @@ -0,0 +1,117 @@ +package job + +import ( + "context" + "os" + + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/common" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/symlink" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + jobutil "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/job" + "github.com/pkg/errors" + "github.com/spf13/afero" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Properties struct { + Owner client.Object + ApiReader client.Reader + Client client.Client + ImageUri string + PathResolver metadata.PathResolver + PullSecrets []string +} + +func NewInstaller(ctx context.Context, fs afero.Fs, props *Properties) installer.Installer { + return &Installer{ + fs: fs, + props: props, + nodeName: env.GetNodeName(), + } +} + +type Installer struct { + fs afero.Fs + props *Properties + nodeName string +} + +func (inst *Installer) InstallAgent(ctx context.Context, targetDir string) (bool, error) { + log.Info("installing agent via Job", "image", inst.props.ImageUri, "target dir", targetDir) + + err := inst.fs.MkdirAll(inst.props.PathResolver.AgentSharedBinaryDirBase(), common.MkDirFileMode) + if err != nil { + log.Info("failed to create the base shared agent directory", "err", err) + + return false, errors.WithStack(err) + } + + jobName := inst.buildJobName() + + ready, err := inst.isReady(ctx, targetDir, jobName) + if err != nil { + return false, err + } + + if !ready { + return false, nil + } + + if err := symlink.CreateForCurrentVersionIfNotExists(inst.fs, targetDir); err != nil { + _ = inst.fs.RemoveAll(targetDir) + + log.Info("failed to create symlink for agent installation", "err", err) + + return false, errors.WithStack(err) + } + + return true, nil +} + +func (inst *Installer) isReady(ctx context.Context, targetDir, jobName string) (bool, error) { + if inst.isAlreadyPresent(targetDir) { + log.Info("agent already installed", "image", inst.props.ImageUri, "target dir", targetDir) + + return true, inst.query().DeleteForNamespace(ctx, jobName, inst.props.Owner.GetNamespace(), &client.DeleteOptions{PropagationPolicy: ptr.To(metav1.DeletePropagationBackground)}) + } + + job, err := inst.query().Get(ctx, types.NamespacedName{Name: jobName, Namespace: inst.props.Owner.GetNamespace()}) + if err != nil && !k8serrors.IsNotFound(err) { + log.Info("failed to determine the status of the download job", "err", err) + + return false, err + } else if err == nil { + log.Info("job is not finished", "job", jobName) + + if job.Status.Failed > 0 { + return false, errors.Errorf("the job is failing; job: %s", jobName) + } + + return false, nil + } + + log.Info("creating new download job", "job", jobName) + + job, err = inst.buildJob(jobName, targetDir) + if err != nil { + return false, err + } + + return false, inst.query().WithOwner(inst.props.Owner).Create(ctx, job) +} + +func (installer *Installer) isAlreadyPresent(targetDir string) bool { + _, err := installer.fs.Stat(targetDir) + + return !os.IsNotExist(err) +} + +func (inst *Installer) query() jobutil.QueryObject { + return jobutil.Query(inst.props.Client, inst.props.ApiReader, log) +} diff --git a/pkg/injection/codemodule/installer/job/installer_test.go b/pkg/injection/codemodule/installer/job/installer_test.go new file mode 100644 index 0000000000..4dcd39995d --- /dev/null +++ b/pkg/injection/codemodule/installer/job/installer_test.go @@ -0,0 +1,175 @@ +package job + +import ( + "context" + "os" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" + "github.com/spf13/afero" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + batchv1 "k8s.io/api/batch/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func TestIsAlreadyPresent(t *testing.T) { + testImageURL := "test:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + testVersion := "1.2.3" + pathResolver := metadata.PathResolver{} + + t.Run("returns early if path doesn't exist", func(t *testing.T) { + installer := Installer{ + fs: afero.NewMemMapFs(), + props: &Properties{ + PathResolver: pathResolver, + ImageUri: testImageURL, + }, + } + isDownloaded := installer.isAlreadyPresent(pathResolver.AgentSharedBinaryDirForAgent(testVersion)) + assert.False(t, isDownloaded) + }) + t.Run("returns true if path present", func(t *testing.T) { + installer := Installer{ + fs: testFileSystemWithSharedDirPresent(pathResolver, testVersion), + props: &Properties{ + PathResolver: pathResolver, + }, + } + isDownloaded := installer.isAlreadyPresent(pathResolver.AgentSharedBinaryDirForAgent(testVersion)) + assert.True(t, isDownloaded) + }) +} + +func testFileSystemWithSharedDirPresent(pathResolver metadata.PathResolver, imageDigest string) afero.Fs { + fs := afero.NewMemMapFs() + _ = fs.MkdirAll(pathResolver.AgentSharedBinaryDirForAgent(imageDigest), 0777) + + return fs +} + +func TestIsReady(t *testing.T) { + ctx := context.Background() + owner := dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-dk", + Namespace: "test", + }, + } + name := "job-1" + targetDir := "/download/here/1.2.3" + nodeName := "node-1" + + t.Run("nothing present -> create job", func(t *testing.T) { + cl := fake.NewClient() + props := &Properties{ + ApiReader: cl, + Client: cl, + Owner: &owner, + } + inst := &Installer{ + fs: afero.NewMemMapFs(), + nodeName: nodeName, + props: props, + } + + ready, err := inst.isReady(ctx, targetDir, name) + require.NoError(t, err) + require.False(t, ready) + + var newJob batchv1.Job + + require.NoError(t, cl.Get(ctx, types.NamespacedName{Name: name, Namespace: owner.GetNamespace()}, &newJob)) + require.NotEmpty(t, newJob) + }) + + t.Run("job present, target not present -> return not ready, no error", func(t *testing.T) { + cl := fake.NewClient() + props := &Properties{ + ApiReader: setupInCompleteJob(t, name, owner.Namespace), + Client: cl, + Owner: &owner, + } + inst := &Installer{ + fs: afero.NewMemMapFs(), + nodeName: nodeName, + props: props, + } + + ready, err := inst.isReady(ctx, targetDir, name) + require.NoError(t, err) + require.False(t, ready) + + var newJob batchv1.Job // should not create a Job as it already exists, bit of a hack, that I use different clients for ApiReader and Client + err = cl.Get(ctx, types.NamespacedName{Name: name, Namespace: owner.GetNamespace()}, &newJob) + require.Error(t, err) + require.NoError(t, client.IgnoreNotFound(err)) + }) + + t.Run("job present, target present -> return ready, cleanup job", func(t *testing.T) { + cl := setupCompleteJob(t, name, owner.Namespace) + props := &Properties{ + ApiReader: cl, + Client: cl, + Owner: &owner, + } + inst := &Installer{ + fs: afero.NewMemMapFs(), + nodeName: nodeName, + props: props, + } + + setupTargetDir(t, inst.fs, targetDir) + + ready, err := inst.isReady(ctx, targetDir, name) + require.NoError(t, err) + require.True(t, ready) + + var newJob batchv1.Job + err = cl.Get(ctx, types.NamespacedName{Name: name, Namespace: owner.GetNamespace()}, &newJob) + require.Error(t, err) + require.NoError(t, client.IgnoreNotFound(err)) + }) +} + +func setupCompleteJob(t *testing.T, name, namespace string) client.Client { + t.Helper() + + fakeJob := batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Status: batchv1.JobStatus{ + Succeeded: 1, + }, + } + + return fake.NewClient(&fakeJob) +} + +func setupInCompleteJob(t *testing.T, name, namespace string) client.Client { + t.Helper() + + fakeJob := batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Status: batchv1.JobStatus{ + Succeeded: 0, + }, + } + + return fake.NewClient(&fakeJob) +} + +func setupTargetDir(t *testing.T, fs afero.Fs, targetDir string) { + t.Helper() + + require.NoError(t, fs.MkdirAll(targetDir, os.ModePerm)) +} diff --git a/pkg/injection/codemodule/installer/url/installer.go b/pkg/injection/codemodule/installer/url/installer.go index dcc404a147..7b8b2c99e0 100644 --- a/pkg/injection/codemodule/installer/url/installer.go +++ b/pkg/injection/codemodule/installer/url/installer.go @@ -57,7 +57,7 @@ func (installer Installer) InstallAgent(ctx context.Context, targetDir string) ( if installer.isAlreadyDownloaded(targetDir) { log.Info("agent already installed", "target dir", targetDir) - return false, nil + return true, nil } err := installer.fs.MkdirAll(installer.props.PathResolver.AgentSharedBinaryDirBase(), common.MkDirFileMode) diff --git a/pkg/util/kubeobjects/env/env.go b/pkg/util/kubeobjects/env/env.go index 1acca5603b..118a7740f7 100644 --- a/pkg/util/kubeobjects/env/env.go +++ b/pkg/util/kubeobjects/env/env.go @@ -1,12 +1,16 @@ package env import ( + "encoding/json" "os" corev1 "k8s.io/api/core/v1" ) const ( + Tolerations = "TOLERATIONS" + NodeName = "KUBE_NODE_NAME" + CSIDataDir = "CSI_DATA_DIR" PodNamespace = "POD_NAMESPACE" PodName = "POD_NAME" ) @@ -56,3 +60,24 @@ func DefaultNamespace() string { return namespace } + +func GetNodeName() string { + return os.Getenv(NodeName) +} + +func GetCSIDataDir() string { + return os.Getenv(CSIDataDir) +} + +func GetTolerations() ([]corev1.Toleration, error) { + var tolerations []corev1.Toleration + + raw := os.Getenv(Tolerations) + if raw == "" { + return tolerations, nil + } + + err := json.Unmarshal([]byte(os.Getenv(Tolerations)), &tolerations) + + return tolerations, err +} diff --git a/pkg/util/kubeobjects/env/env_test.go b/pkg/util/kubeobjects/env/env_test.go index f1314224ac..3597ba3a31 100644 --- a/pkg/util/kubeobjects/env/env_test.go +++ b/pkg/util/kubeobjects/env/env_test.go @@ -1,9 +1,11 @@ package env import ( + "encoding/json" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" ) @@ -82,3 +84,44 @@ func TestDefaultNamespace(t *testing.T) { assert.Equal(t, "dynatrace", got) }) } + +func TestGetToleration(t *testing.T) { + t.Run("Get tolerations from env var", func(t *testing.T) { + expected := []corev1.Toleration{ + { + Key: "key1", + Operator: corev1.TolerationOpEqual, + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: corev1.TolerationOpEqual, + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + }, + } + + raw, err := json.Marshal(expected) + require.NoError(t, err) + + t.Setenv(Tolerations, string(raw)) + + actual, err := GetTolerations() + require.NoError(t, err) + assert.Equal(t, expected, actual) + }) + t.Run("Error incase of malformed", func(t *testing.T) { + t.Setenv(Tolerations, "{!@@@#}") + + _, err := GetTolerations() + require.Error(t, err) + }) + + t.Run("no error incase of empty", func(t *testing.T) { + t.Setenv(Tolerations, "") + + _, err := GetTolerations() + require.NoError(t, err) + }) +} diff --git a/pkg/util/kubeobjects/internal/query/query.go b/pkg/util/kubeobjects/internal/query/query.go index 36c198f530..10e8ac83d3 100644 --- a/pkg/util/kubeobjects/internal/query/query.go +++ b/pkg/util/kubeobjects/internal/query/query.go @@ -77,10 +77,10 @@ func (c Generic[T, L]) Update(ctx context.Context, object T) error { return errors.WithStack(c.KubeClient.Update(ctx, object)) } -func (c Generic[T, L]) Delete(ctx context.Context, object T) error { +func (c Generic[T, L]) Delete(ctx context.Context, object T, options ...client.DeleteOption) error { c.log(object).Info("deleting") - err := c.KubeClient.Delete(ctx, object) + err := c.KubeClient.Delete(ctx, object, options...) return errors.WithStack(client.IgnoreNotFound(err)) } @@ -218,13 +218,13 @@ func (c Generic[T, L]) createOrUpdateForNamespaces(ctx context.Context, object T return goerrors.Join(errs...) } -func (c Generic[T, L]) DeleteForNamespace(ctx context.Context, objectName string, namespace string) error { +func (c Generic[T, L]) DeleteForNamespace(ctx context.Context, objectName string, namespace string, options ...client.DeleteOption) error { c.Log.Info("deleting object from namespace", "name", objectName, "namespace", namespace) c.Target.SetName(objectName) c.Target.SetNamespace(namespace) - return c.Delete(ctx, c.Target) + return c.Delete(ctx, c.Target, options...) } func (c Generic[T, L]) DeleteForNamespaces(ctx context.Context, objectName string, namespaces []string) error { diff --git a/pkg/util/kubeobjects/job/builder.go b/pkg/util/kubeobjects/job/builder.go new file mode 100644 index 0000000000..9698b59bb7 --- /dev/null +++ b/pkg/util/kubeobjects/job/builder.go @@ -0,0 +1,108 @@ +package job + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/internal/builder" + maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var ( + // Mandatory fields, provided in constructor as named params + setName = builder.SetName[*batchv1.Job] + setNamespace = builder.SetNamespace[*batchv1.Job] + + // Optional fields, provided in constructor as list of options + SetLabels = builder.SetLabels[*batchv1.Job] +) + +func Build(owner metav1.Object, name string, container corev1.Container, options ...builder.Option[*batchv1.Job]) (*batchv1.Job, error) { + neededOpts := []builder.Option[*batchv1.Job]{ + setName(name), + SetContainer(container), + setNamespace(owner.GetNamespace()), + } + neededOpts = append(neededOpts, options...) + + return builder.Build(owner, &batchv1.Job{}, neededOpts...) +} + +func SetVolumes(volumes []corev1.Volume) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.Spec.Template.Spec.Volumes = volumes + } +} + +func SetTolerations(tolerations []corev1.Toleration) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.Spec.Template.Spec.Tolerations = tolerations + } +} + +func SetNodeName(nodeName string) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.Spec.Template.Spec.NodeName = nodeName + } +} + +func SetOnFailureRestartPolicy() builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.Spec.Template.Spec.RestartPolicy = corev1.RestartPolicyOnFailure + } +} + +func SetPullSecret(pullSecrets ...string) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + imagePullSecrets := make([]corev1.LocalObjectReference, 0) + for _, pullSecretName := range pullSecrets { + imagePullSecrets = append(imagePullSecrets, corev1.LocalObjectReference{ + Name: pullSecretName, + }) + } + + s.Spec.Template.Spec.ImagePullSecrets = append(s.Spec.Template.Spec.ImagePullSecrets, imagePullSecrets...) + } +} + +func SetAutomountServiceAccountToken(isEnabled bool) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.Spec.Template.Spec.AutomountServiceAccountToken = &isEnabled + } +} + +func SetPodAnnotations(annotations map[string]string) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.Spec.Template.ObjectMeta.Annotations = annotations + } +} + +func SetAllLabels(labels, matchLabels, templateLabels, customLabels map[string]string) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.ObjectMeta.Labels = labels + if matchLabels == nil { + s.Spec.Selector = &metav1.LabelSelector{MatchLabels: matchLabels} + } + + s.Spec.Template.ObjectMeta.Labels = maputils.MergeMap(customLabels, templateLabels) + } +} + +func SetContainer(container corev1.Container) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + targetIndex := 0 + for index := range s.Spec.Template.Spec.Containers { + if s.Spec.Template.Spec.Containers[targetIndex].Name == container.Name { + targetIndex = index + + break + } + } + + if targetIndex == 0 { + s.Spec.Template.Spec.Containers = make([]corev1.Container, 1) + } + + s.Spec.Template.Spec.Containers[targetIndex] = container + } +} diff --git a/pkg/util/kubeobjects/job/query.go b/pkg/util/kubeobjects/job/query.go new file mode 100644 index 0000000000..bb2a954de8 --- /dev/null +++ b/pkg/util/kubeobjects/job/query.go @@ -0,0 +1,45 @@ +package job + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/internal/query" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + batchv1 "k8s.io/api/batch/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type QueryObject struct { + query.Generic[*batchv1.Job, *batchv1.JobList] +} + +func Query(kubeClient client.Client, kubeReader client.Reader, log logd.Logger) QueryObject { + return QueryObject{ + query.Generic[*batchv1.Job, *batchv1.JobList]{ + Target: &batchv1.Job{}, + ListTarget: &batchv1.JobList{}, + ToList: func(sl *batchv1.JobList) []*batchv1.Job { + out := []*batchv1.Job{} + for _, s := range sl.Items { + out = append(out, &s) + } + + return out + }, + IsEqual: isEqual, + MustRecreate: mustRecreate, + + KubeClient: kubeClient, + KubeReader: kubeReader, + Log: log, + }, + } +} + +func isEqual(current, desired *batchv1.Job) bool { + return !hasher.IsAnnotationDifferent(current, desired) +} + +func mustRecreate(current, desired *batchv1.Job) bool { + return labels.NotEqual(current.Spec.Selector.MatchLabels, desired.Spec.Selector.MatchLabels) +} diff --git a/pkg/util/kubeobjects/labels/labels.go b/pkg/util/kubeobjects/labels/labels.go index 29e76e16f7..7788eda228 100644 --- a/pkg/util/kubeobjects/labels/labels.go +++ b/pkg/util/kubeobjects/labels/labels.go @@ -15,6 +15,7 @@ const ( AppVersionLabel = "app.kubernetes.io/version" OneAgentComponentLabel = "oneagent" + CodeModuleComponentLabel = "codemodule" LogMonitoringComponentLabel = "logmonitoring" KSPMComponentLabel = "kspm" ActiveGateComponentLabel = "activegate" From 40c9d2bcb187c250cc9344033f3f999cc64d21a0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Feb 2025 07:56:00 +0000 Subject: [PATCH 182/426] chore(deps): update docker/setup-buildx-action action to v3.9.0 (main) (#4422) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index f0a833b597..f116fb0014 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -16,7 +16,7 @@ runs: - name: Set up QEMU uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3.3.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 + uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3.9.0 - name: Set up Golang uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: From 241af312cb8841fa60ad239597885c86e1d4da79 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Feb 2025 09:19:50 +0000 Subject: [PATCH 183/426] chore(deps): update docker/setup-qemu-action action to v3.4.0 (main) (#4423) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index f116fb0014..782d5b8e5b 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -14,7 +14,7 @@ runs: using: "composite" steps: - name: Set up QEMU - uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3.3.0 + uses: docker/setup-qemu-action@4574d27a4764455b42196d70a065bc6853246a25 # v3.4.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3.9.0 - name: Set up Golang From cedd536143a1bfd302c21941da2a8d6b2bfd2793 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Fri, 7 Feb 2025 11:46:27 +0100 Subject: [PATCH 184/426] update e2e tests ondemand according to available clusters (#4427) --- .github/workflows/e2e-tests-ondemand.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e-tests-ondemand.yaml b/.github/workflows/e2e-tests-ondemand.yaml index 1cfa82d71d..2321a680a9 100644 --- a/.github/workflows/e2e-tests-ondemand.yaml +++ b/.github/workflows/e2e-tests-ondemand.yaml @@ -23,8 +23,6 @@ jobs: max-parallel: 4 matrix: include: - - version: 1-25 - platform: k8s - version: 1-26 platform: k8s - version: 1-27 @@ -35,6 +33,8 @@ jobs: platform: k8s - version: 1-30 platform: k8s + - version: 1-31 + platform: k8s - version: 4-10 platform: ocp - version: 4-11 @@ -49,6 +49,8 @@ jobs: platform: ocp - version: 4-16 platform: ocp + - version: 4-17 + platform: ocp environment: E2E runs-on: - self-hosted From 51a3921acc51733aef97934f8598d1594258120d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Feb 2025 10:55:31 +0000 Subject: [PATCH 185/426] chore(deps): update github/codeql-action action to v3.28.9 (main) (#4428) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index b6e245f0e4..ea69f8c94b 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 + uses: github/codeql-action/init@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 + uses: github/codeql-action/autobuild@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 + uses: github/codeql-action/analyze@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 1a8292d636..8d2936e26f 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 + uses: github/codeql-action/upload-sarif@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9 with: sarif_file: results.sarif From 4ba6fb36f08c8b675776e7d5cebcfd600d346780 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 7 Feb 2025 12:16:43 +0100 Subject: [PATCH 186/426] Remove hard-coded command from CodeModule download jobs (#4429) --- pkg/injection/codemodule/installer/job/bootstrapper.go | 5 +---- pkg/injection/codemodule/installer/job/bootstrapper_test.go | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/injection/codemodule/installer/job/bootstrapper.go b/pkg/injection/codemodule/installer/job/bootstrapper.go index f96b5de186..4f3989eb15 100644 --- a/pkg/injection/codemodule/installer/job/bootstrapper.go +++ b/pkg/injection/codemodule/installer/job/bootstrapper.go @@ -14,9 +14,7 @@ import ( const ( namePrefix = "codemodule-download-" - volumeName = "dynatrace-codemodules" - - bootstrapCommand = "/opt/dynatrace/bin/bootstrap" + volumeName = "dynatrace-codemodules" codeModuleSource = "/opt/dynatrace/oneagent" ) @@ -40,7 +38,6 @@ func (inst *Installer) buildJob(name, targetDir string) (*batchv1.Job, error) { Name: "codemodule-download", Image: inst.props.ImageUri, ImagePullPolicy: corev1.PullIfNotPresent, - Command: []string{bootstrapCommand}, VolumeMounts: []corev1.VolumeMount{ { Name: volumeName, diff --git a/pkg/injection/codemodule/installer/job/bootstrapper_test.go b/pkg/injection/codemodule/installer/job/bootstrapper_test.go index 0931417e50..979983a3b0 100644 --- a/pkg/injection/codemodule/installer/job/bootstrapper_test.go +++ b/pkg/injection/codemodule/installer/job/bootstrapper_test.go @@ -124,7 +124,7 @@ func TestBuildJob(t *testing.T) { container := job.Spec.Template.Spec.Containers[0] assert.Equal(t, imageURI, container.Image) - assert.Contains(t, container.Command, bootstrapCommand) + assert.Empty(t, container.Command) assert.NotEmpty(t, container.Args) assert.NotEmpty(t, container.SecurityContext) From 149951f4d019f0baaa86cbb3febc7bc8261cf7ce Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Fri, 7 Feb 2025 12:56:53 +0100 Subject: [PATCH 187/426] cherry-pick: Add `/var/log` mount to log agent (#4413) (#4420) --- .../logmonitoring/daemonset/volumes.go | 32 +++++++++++++++---- .../logmonitoring/daemonset/volumes_test.go | 2 +- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go index d4f84b4b80..ab912a74ae 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go @@ -22,12 +22,15 @@ const ( dtLogVolumeMountPath = "/var/log/dynatrace" // for the logs that the logmonitoring will ingest - podLogsVolumeName = "var-log-pods" - podLogsVolumePath = "/var/log/pods" - dockerLogsVolumeName = "docker-container-logs" - dockerLogsVolumePath = "/var/lib/docker/containers" - containerLogsVolumeName = "container-logs" - containerLogsVolumePath = "/var/log/containers" + podLogsVolumeName = "var-log-pods" + podLogsVolumePath = "/var/log/pods" + dockerLogsVolumeName = "docker-container-logs" + dockerLogsVolumePath = "/var/lib/docker/containers" + containerLogsVolumeName = "container-logs" + containerLogsVolumePath = "/var/log/containers" + journalLogsVolumeName = "var-log-journal" + journalLogsVolumePath = "/var/log/journal" + journalLogsVolumeHostPath = "/var/log" ) // getConfigVolumeMount provides the VolumeMount for the deployment.conf @@ -103,6 +106,11 @@ func getIngestVolumeMounts() []corev1.VolumeMount { MountPath: containerLogsVolumePath, ReadOnly: true, }, + { + Name: journalLogsVolumeName, + MountPath: journalLogsVolumePath, + ReadOnly: true, + }, } } @@ -114,6 +122,7 @@ func getIngestVolumes() []corev1.Volume { VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ Path: dockerLogsVolumePath, + Type: ptr.To(corev1.HostPathDirectory), }, }, }, @@ -122,6 +131,7 @@ func getIngestVolumes() []corev1.Volume { VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ Path: podLogsVolumePath, + Type: ptr.To(corev1.HostPathDirectory), }, }, }, @@ -130,6 +140,16 @@ func getIngestVolumes() []corev1.Volume { VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ Path: containerLogsVolumePath, + Type: ptr.To(corev1.HostPathDirectory), + }, + }, + }, + { + Name: journalLogsVolumeName, + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: journalLogsVolumeHostPath, + Type: ptr.To(corev1.HostPathDirectory), }, }, }, diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go index bdb8b7fe40..dc68f19d7b 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go @@ -8,7 +8,7 @@ import ( ) const ( - expectedMountLen = 6 + expectedMountLen = 7 expectedInitMountLen = 2 ) From aae121f8ec58f9fda05ee40d7e80f36a288f3c43 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:34:27 +0100 Subject: [PATCH 188/426] Follow naming pattern of previous feature-flags for Job feature-flag (#4430) --- doc/api/feature-flags.md | 2 +- pkg/api/v1beta3/dynakube/feature_flags.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/feature-flags.md b/doc/api/feature-flags.md index 38e3a90b68..0ae8bb9eaf 100644 --- a/doc/api/feature-flags.md +++ b/doc/api/feature-flags.md @@ -57,7 +57,7 @@ const ( AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureDownloadViaJob = AnnotationFeatureCodeModulesPrefix + "remoteImageDownload" + AnnotationFeatureDownloadViaJob = AnnotationFeatureCodeModulesPrefix + "remote-image-download" ) ``` diff --git a/pkg/api/v1beta3/dynakube/feature_flags.go b/pkg/api/v1beta3/dynakube/feature_flags.go index 92c3c13691..4f67e6d2ce 100644 --- a/pkg/api/v1beta3/dynakube/feature_flags.go +++ b/pkg/api/v1beta3/dynakube/feature_flags.go @@ -73,7 +73,7 @@ const ( AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureDownloadViaJob = AnnotationFeatureCodeModulesPrefix + "remoteImageDownload" + AnnotationFeatureDownloadViaJob = AnnotationFeatureCodeModulesPrefix + "remote-image-download" falsePhrase = "false" truePhrase = "true" From 35c3dcb0f01b270bacbd950250803f6ba78d47eb Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:50:07 +0100 Subject: [PATCH 189/426] Mount telemetryService.TlsRefName secret to OtelC POD (#4412) --- pkg/api/consts.go | 8 +-- .../dynakube/extension/eec/reconciler_test.go | 12 ++-- .../dynakube/extension/eec/statefulset.go | 2 +- .../dynakube/otelc/statefulset/reconciler.go | 33 ++++++++-- .../otelc/statefulset/reconciler_test.go | 66 ++++++++++++++++--- .../dynakube/otelc/statefulset/volumes.go | 32 +++++++++ 6 files changed, 125 insertions(+), 28 deletions(-) diff --git a/pkg/api/consts.go b/pkg/api/consts.go index 3dc4754d1f..25bd0dbe1b 100644 --- a/pkg/api/consts.go +++ b/pkg/api/consts.go @@ -1,8 +1,8 @@ package api const ( - LatestTag = "latest" - RawTag = "raw" - InternalFlagPrefix = "internal.operator.dynatrace.com/" - AnnotationSecretHash = InternalFlagPrefix + "secret-hash" + LatestTag = "latest" + RawTag = "raw" + InternalFlagPrefix = "internal.operator.dynatrace.com/" + AnnotationExtensionsSecretHash = InternalFlagPrefix + "extensions-secret-hash" ) diff --git a/pkg/controllers/dynakube/extension/eec/reconciler_test.go b/pkg/controllers/dynakube/extension/eec/reconciler_test.go index 3b410335ff..91e4f5e999 100644 --- a/pkg/controllers/dynakube/extension/eec/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/eec/reconciler_test.go @@ -180,7 +180,7 @@ func TestSecretHashAnnotation(t *testing.T) { statefulSet := getStatefulset(t, dk) require.Len(t, statefulSet.Spec.Template.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash]) }) t.Run("annotation is set with tlsRefName", func(t *testing.T) { dk := getTestDynakube() @@ -188,7 +188,7 @@ func TestSecretHashAnnotation(t *testing.T) { statefulSet := getStatefulset(t, dk) require.Len(t, statefulSet.Spec.Template.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash]) }) t.Run("annotation is updated when TLS Secret gets updated", func(t *testing.T) { statefulSet := &appsv1.StatefulSet{} @@ -205,7 +205,7 @@ func TestSecretHashAnnotation(t *testing.T) { err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsExecutionControllerStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) - originalSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash] + originalSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash] // then update the TLS Secret and call reconcile again updatedTLSSecret := getTLSSecret(dk.ExtensionsTLSSecretName(), dk.Namespace, "updated-cert", "updated-key") @@ -217,7 +217,7 @@ func TestSecretHashAnnotation(t *testing.T) { err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsExecutionControllerStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) - resultingSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash] + resultingSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash] // original hash and resulting hash should be different, value got updated on reconcile assert.NotEqual(t, originalSecretHash, resultingSecretHash) @@ -548,7 +548,7 @@ func TestAnnotations(t *testing.T) { assert.Len(t, statefulSet.ObjectMeta.Annotations, 2) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationExtensionsSecretHash]) }) t.Run("custom annotations", func(t *testing.T) { @@ -564,7 +564,7 @@ func TestAnnotations(t *testing.T) { assert.Empty(t, statefulSet.ObjectMeta.Annotations["a"]) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 2) assert.Equal(t, "b", statefulSet.Spec.Template.ObjectMeta.Annotations["a"]) - assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationExtensionsSecretHash]) }) } diff --git a/pkg/controllers/dynakube/extension/eec/statefulset.go b/pkg/controllers/dynakube/extension/eec/statefulset.go index af9039edd5..86cd31282e 100644 --- a/pkg/controllers/dynakube/extension/eec/statefulset.go +++ b/pkg/controllers/dynakube/extension/eec/statefulset.go @@ -152,7 +152,7 @@ func (r *reconciler) buildTemplateAnnotations(ctx context.Context) (map[string]s return nil, err } - templateAnnotations[api.AnnotationSecretHash] = tlsSecretHash + templateAnnotations[api.AnnotationExtensionsSecretHash] = tlsSecretHash return templateAnnotations, nil } diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go index 273e6ee6be..bc7a903585 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go @@ -20,7 +20,8 @@ import ( ) const ( - serviceAccountName = "dynatrace-opentelemetry-collector" + serviceAccountName = "dynatrace-opentelemetry-collector" + annotationTelemetryServiceSecretHash = api.InternalFlagPrefix + "telemetry-service-secret-hash" ) type Reconciler struct { @@ -127,24 +128,42 @@ func (r *Reconciler) buildTemplateAnnotations(ctx context.Context) (map[string]s templateAnnotations = r.dk.Spec.Templates.OpenTelemetryCollector.Annotations } + tlsSecretHash, err := r.calculateSecretHash(ctx, r.dk.ExtensionsTLSSecretName()) + if err != nil { + return nil, err + } + + templateAnnotations[api.AnnotationExtensionsSecretHash] = tlsSecretHash + + if r.dk.TelemetryService().IsEnabled() && r.dk.TelemetryService().Spec.TlsRefName != "" { + tlsSecretHash, err = r.calculateSecretHash(ctx, r.dk.TelemetryService().Spec.TlsRefName) + if err != nil { + return nil, err + } + + templateAnnotations[annotationTelemetryServiceSecretHash] = tlsSecretHash + } + + return templateAnnotations, nil +} + +func (r *Reconciler) calculateSecretHash(ctx context.Context, secretName string) (string, error) { query := k8ssecret.Query(r.client, r.client, log) tlsSecret, err := query.Get(ctx, types.NamespacedName{ - Name: r.dk.ExtensionsTLSSecretName(), + Name: secretName, Namespace: r.dk.Namespace, }) if err != nil { - return nil, err + return "", err } tlsSecretHash, err := hasher.GenerateHash(tlsSecret.Data) if err != nil { - return nil, err + return "", err } - templateAnnotations[api.AnnotationSecretHash] = tlsSecretHash - - return templateAnnotations, nil + return tlsSecretHash, nil } func getReplicas(dk *dynakube.DynaKube) int32 { diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go index de5be03f5d..0a8e2020b1 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" @@ -27,9 +28,10 @@ import ( ) const ( - testDynakubeName = "dynakube" - testNamespaceName = "dynatrace" - testOtelPullSecret = "otelc-pull-secret" + testDynakubeName = "dynakube" + testNamespaceName = "dynatrace" + testOtelPullSecret = "otelc-pull-secret" + testTelemetryServiceSecret = "test-ts-secret" ) func TestReconcile(t *testing.T) { @@ -98,7 +100,7 @@ func TestSecretHashAnnotation(t *testing.T) { statefulSet := getStatefulset(t, dk) require.Len(t, statefulSet.Spec.Template.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash]) }) t.Run("annotation is set with tlsRefName", func(t *testing.T) { dk := getTestDynakube() @@ -106,7 +108,7 @@ func TestSecretHashAnnotation(t *testing.T) { statefulSet := getStatefulset(t, dk) require.Len(t, statefulSet.Spec.Template.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash]) }) t.Run("annotation is updated when TLS Secret gets updated", func(t *testing.T) { statefulSet := &appsv1.StatefulSet{} @@ -123,7 +125,7 @@ func TestSecretHashAnnotation(t *testing.T) { err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) - originalSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash] + originalSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash] // then update the TLS Secret and call reconcile again updatedTLSSecret := getTLSSecret(dk.ExtensionsTLSSecretName(), dk.Namespace, "updated-cert", "updated-key") @@ -135,7 +137,7 @@ func TestSecretHashAnnotation(t *testing.T) { err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) - resultingSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationSecretHash] + resultingSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash] // original hash and resulting hash should be different, value got updated on reconcile assert.NotEqual(t, originalSecretHash, resultingSecretHash) @@ -342,7 +344,7 @@ func TestAnnotations(t *testing.T) { assert.Len(t, statefulSet.ObjectMeta.Annotations, 1) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 1) - assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationExtensionsSecretHash]) }) t.Run("custom annotations", func(t *testing.T) { @@ -358,7 +360,7 @@ func TestAnnotations(t *testing.T) { assert.Empty(t, statefulSet.ObjectMeta.Annotations["a"]) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 2) assert.Equal(t, "b", statefulSet.Spec.Template.ObjectMeta.Annotations["a"]) - assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationSecretHash]) + assert.NotEmpty(t, statefulSet.Spec.Template.ObjectMeta.Annotations[api.AnnotationExtensionsSecretHash]) }) } @@ -503,6 +505,45 @@ func TestVolumes(t *testing.T) { assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) }) + + t.Run("volumes and volume mounts with telemetry service custom TLS certificate", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.TelemetryService = &telemetryservice.Spec{ + TlsRefName: testTelemetryServiceSecret, + } + + tlsSecret := getTLSSecret(dk.TelemetryService().Spec.TlsRefName, dk.Namespace, "crt", "key") + statefulSet := getStatefulset(t, dk, &tlsSecret) + + expectedVolume := corev1.Volume{ + Name: customTlsCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.TelemetryService().Spec.TlsRefName, + Items: []corev1.KeyToPath{ + { + Key: consts.TLSCrtDataName, + Path: consts.TLSCrtDataName, + }, + { + Key: consts.TLSKeyDataName, + Path: consts.TLSKeyDataName, + }, + }, + }, + }, + } + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) + + expectedVolumeMount := corev1.VolumeMount{ + Name: customTlsCertVolumeName, + MountPath: customTlsCertMountPath, + ReadOnly: true, + } + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + }) } func getTestDynakube() *dynakube.DynaKube { @@ -519,10 +560,15 @@ func getTestDynakube() *dynakube.DynaKube { } } -func getStatefulset(t *testing.T, dk *dynakube.DynaKube) *appsv1.StatefulSet { +func getStatefulset(t *testing.T, dk *dynakube.DynaKube, objs ...client.Object) *appsv1.StatefulSet { mockK8sClient := fake.NewClient(dk) mockK8sClient = mockTLSSecret(t, mockK8sClient, dk) + for _, obj := range objs { + err := mockK8sClient.Create(context.Background(), obj) + require.NoError(t, err) + } + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) diff --git a/pkg/controllers/dynakube/otelc/statefulset/volumes.go b/pkg/controllers/dynakube/otelc/statefulset/volumes.go index 5b6a9c9957..64058081e6 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/volumes.go +++ b/pkg/controllers/dynakube/otelc/statefulset/volumes.go @@ -13,6 +13,9 @@ const ( caCertsVolumeName = "cacerts" trustedCAsFile = "rootca.pem" + + customTlsCertVolumeName = "telemetry-custom-tls" + customTlsCertMountPath = "/tls/custom/telemetry" ) func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { @@ -67,6 +70,27 @@ func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { }, }, }) + + if dk.TelemetryService().IsEnabled() && dk.TelemetryService().Spec.TlsRefName != "" { + o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ + Name: customTlsCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.TelemetryService().Spec.TlsRefName, + Items: []corev1.KeyToPath{ + { + Key: consts.TLSCrtDataName, + Path: consts.TLSCrtDataName, + }, + { + Key: consts.TLSKeyDataName, + Path: consts.TLSKeyDataName, + }, + }, + }, + }, + }) + } } } @@ -89,5 +113,13 @@ func buildContainerVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { ReadOnly: true, }) + if dk.TelemetryService().IsEnabled() && dk.TelemetryService().Spec.TlsRefName != "" { + vm = append(vm, corev1.VolumeMount{ + Name: customTlsCertVolumeName, + MountPath: customTlsCertMountPath, + ReadOnly: true, + }) + } + return vm } From fa3bd12b807602b67ab5068ec57642eec781bdf4 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Fri, 7 Feb 2025 18:56:05 +0100 Subject: [PATCH 190/426] Cherry-pick: Change readonly oneAgent + custom image validation to a warning #4346 (#4386) Co-authored-by: StefanHauth <63204425+StefanHauth@users.noreply.github.com> --- pkg/api/validation/dynakube/image_test.go | 6 +-- pkg/api/validation/dynakube/oneagent.go | 10 +++++ pkg/api/validation/dynakube/oneagent_test.go | 44 ++++++++++++++++++++ pkg/api/validation/dynakube/validation.go | 1 + 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/pkg/api/validation/dynakube/image_test.go b/pkg/api/validation/dynakube/image_test.go index dc74cea41b..badcec42ef 100644 --- a/pkg/api/validation/dynakube/image_test.go +++ b/pkg/api/validation/dynakube/image_test.go @@ -50,7 +50,7 @@ func TestImageFieldHasTenantImage(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testTenantUrl + "/api", OneAgent: oneagent.Spec{ - ClassicFullStack: &oneagent.HostInjectSpec{ + HostMonitoring: &oneagent.HostInjectSpec{ Image: testRegistryUrl + "/linux/oneagent:latest", }, }, @@ -72,7 +72,7 @@ func TestImageFieldHasTenantImage(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testTenantUrl + "/api", OneAgent: oneagent.Spec{ - ClassicFullStack: &oneagent.HostInjectSpec{ + HostMonitoring: &oneagent.HostInjectSpec{ Image: testRegistryUrl + "/linux/oneagent:latest", }, }, @@ -88,7 +88,7 @@ func TestImageFieldHasTenantImage(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testTenantUrl + "/api", OneAgent: oneagent.Spec{ - ClassicFullStack: &oneagent.HostInjectSpec{ + HostMonitoring: &oneagent.HostInjectSpec{ Image: "127.0.0.1:5000/test:tag", }, }, diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index 8c67f0adfc..dc77d9b94f 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -24,6 +24,8 @@ Use a nodeSelector to avoid this conflict. Conflicting DynaKubes: %s` errorVolumeStorageReadOnlyModeConflict = `The DynaKube specification specifies a read-only host file system while OneAgent has volume storage enabled.` + warningPublicImageWithWrongConfig = `Custom OneAgent image is only supported when CSI Driver is used.` + warningOneAgentInstallerEnvVars = `The environment variables ONEAGENT_INSTALLER_SCRIPT_URL and ONEAGENT_INSTALLER_TOKEN are only relevant for an unsupported image type. Please ensure you are using a supported image.` warningHostGroupConflict = `The DynaKube specification sets the host group using the --set-host-group parameter. Instead, specify the new spec.oneagent.hostGroup field. If both settings are used, the new field takes precedence over the parameter.` @@ -125,6 +127,14 @@ func mapKeysToString(m map[string]bool, sep string) string { return strings.Join(keys, sep) } +func publicImageSetWithoutReadOnlyMode(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { + if !dk.OneAgent().IsReadOnlyOneAgentsMode() && dk.OneAgent().GetCustomImage() != "" { + return warningPublicImageWithWrongConfig + } + + return "" +} + func imageFieldSetWithoutCSIFlag(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { if dk.OneAgent().IsApplicationMonitoringMode() { if len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) > 0 && !v.modules.CSIDriver { diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index 47057cbac2..bfbd05a4b0 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -492,6 +492,50 @@ func TestIsOneAgentVersionValid(t *testing.T) { } } +func TestPublicImageSetWithReadOnlyMode(t *testing.T) { + t.Run("reject dk with hostMon without csi and custom image", func(t *testing.T) { + setupDisabledCSIEnv(t) + assertAllowedWithWarnings(t, 1, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ + Image: "test/image/test-image:some-tag", + }, + }, + }, + }) + }) + t.Run("allow dk with hostMon without csi and no custom image", func(t *testing.T) { + setupDisabledCSIEnv(t) + assertAllowed(t, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, + }, + }, + }) + }) + t.Run("allow dk with hostMon with csi and custom image", func(t *testing.T) { + assertAllowed(t, &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{ + Image: "test/image/test-image:some-tag", + }, + }, + }, + }) + }) +} + func TestOneAgentArguments(t *testing.T) { type oneAgentArgumentTest struct { testName string diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index bd2d3201e0..562c1965af 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -70,6 +70,7 @@ var ( deprecatedFeatureFlag, ignoredLogMonitoringTemplate, conflictingApiUrlForExtensions, + publicImageSetWithoutReadOnlyMode, } updateValidatorErrorFuncs = []updateValidatorFunc{ IsMutatedApiUrl, From da6a359ee652875683bbc70b5731e65fe754d278 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 9 Feb 2025 13:55:30 +0000 Subject: [PATCH 191/426] chore(deps): update golangci/golangci-lint-action action to v6.3.1 (main) (#4432) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7593df5624..43675280c2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,7 +86,7 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint - uses: golangci/golangci-lint-action@e60da84bfae8c7920a47be973d75e15710aa8bd7 # v6.3.0 + uses: golangci/golangci-lint-action@2e788936b09dd82dc280e845628a40d2ba6b204c # v6.3.1 with: # renovate depName=github.com/golangci/golangci-lint version: v1.63.4 From 066ce989a53e8c729594fb7095e4d49c8c9a2040 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 08:25:10 +0000 Subject: [PATCH 192/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1739146154 (main) (#4433) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 96f8a68cc4..082337bafc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1738816380@sha256:7e85855f6925e03f91b5c51f07886ff1c18c6ec69b5fc65491428a899da914a2 AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739146154@sha256:4a2052ef4db4fd1a53b45263b5067eb01d5745fdd300b27986952af27887bc27 AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1738814488@sha256:be214e191bbe3f4d0f16a5a4f5642e1f32fccd6fae7d2b6c6acb066ba51fb507 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From b94a1c2f61dcc085b36c60c88a21d92d128fdc66 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Mon, 10 Feb 2025 11:30:25 +0100 Subject: [PATCH 193/426] Add automatic restarts of agents if token is rotated (#4361) --- config/crd/bases/dynatrace.com_dynakubes.yaml | 18 ++++++++++++ .../Common/crd/dynatrace-operator-crd.yaml | 18 ++++++++++++ pkg/api/shared/communication/types.go | 3 ++ pkg/api/v1beta1/dynakube/dynakube_status.go | 3 ++ pkg/api/v1beta2/dynakube/dynakube_status.go | 3 ++ .../dynakube/activegate/consts/consts.go | 1 + .../internal/statefulset/statefulset.go | 1 + .../internal/statefulset/statefulset_test.go | 8 ++++++ .../connectioninfo/activegate/reconciler.go | 6 ++++ .../activegate/reconciler_test.go | 5 ++++ .../connectioninfo/oneagent/reconciler.go | 5 ++++ .../oneagent/reconciler_test.go | 5 ++++ .../logmonitoring/daemonset/annotations.go | 22 +++++++++++++++ .../logmonitoring/daemonset/reconciler.go | 2 +- .../daemonset/reconciler_test.go | 28 +++++++++---------- .../dynakube/oneagent/daemonset/daemonset.go | 3 ++ .../oneagent/daemonset/daemonset_test.go | 15 +++++++++- 17 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 pkg/controllers/dynakube/logmonitoring/daemonset/annotations.go diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index 778cf1c6c1..58b94ab4a3 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -2290,6 +2290,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -2445,6 +2448,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -4169,6 +4175,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -4345,6 +4354,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -7560,6 +7572,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -7745,6 +7760,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 53775b3e53..8c5ea30826 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -2302,6 +2302,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -2457,6 +2460,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -4181,6 +4187,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -4357,6 +4366,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -7572,6 +7584,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string @@ -7757,6 +7772,9 @@ spec: description: Time of the last connection request format: date-time type: string + tenantTokenHash: + description: Hash of the tenant token + type: string tenantUUID: description: UUID of the tenant, received from the tenant type: string diff --git a/pkg/api/shared/communication/types.go b/pkg/api/shared/communication/types.go index 437d762b55..6bbbbc9f80 100644 --- a/pkg/api/shared/communication/types.go +++ b/pkg/api/shared/communication/types.go @@ -14,4 +14,7 @@ type ConnectionInfo struct { // Available connection endpoints Endpoints string `json:"endpoints,omitempty"` + + // Hash of the tenant token + TenantTokenHash string `json:"tenantTokenHash,omitempty"` } diff --git a/pkg/api/v1beta1/dynakube/dynakube_status.go b/pkg/api/v1beta1/dynakube/dynakube_status.go index dc43c4a84b..f1accb4f05 100644 --- a/pkg/api/v1beta1/dynakube/dynakube_status.go +++ b/pkg/api/v1beta1/dynakube/dynakube_status.go @@ -61,6 +61,9 @@ type ConnectionInfoStatus struct { // Available connection endpoints Endpoints string `json:"endpoints,omitempty"` + + // Hash of the tenant token + TenantTokenHash string `json:"tenantTokenHash,omitempty"` } type OneAgentConnectionInfoStatus struct { diff --git a/pkg/api/v1beta2/dynakube/dynakube_status.go b/pkg/api/v1beta2/dynakube/dynakube_status.go index cdb9c2d9fe..c1815173ec 100644 --- a/pkg/api/v1beta2/dynakube/dynakube_status.go +++ b/pkg/api/v1beta2/dynakube/dynakube_status.go @@ -66,6 +66,9 @@ type ConnectionInfoStatus struct { // Available connection endpoints Endpoints string `json:"endpoints,omitempty"` + + // Hash of the tenant token + TenantTokenHash string `json:"tenantTokenHash,omitempty"` } type OneAgentConnectionInfoStatus struct { diff --git a/pkg/controllers/dynakube/activegate/consts/consts.go b/pkg/controllers/dynakube/activegate/consts/consts.go index e973e56c6a..3798114423 100644 --- a/pkg/controllers/dynakube/activegate/consts/consts.go +++ b/pkg/controllers/dynakube/activegate/consts/consts.go @@ -28,6 +28,7 @@ const ( EnvDtHttpPort = "DT_HTTP_PORT" AnnotationActiveGateConfigurationHash = api.InternalFlagPrefix + "activegate-configuration-hash" + AnnotationActiveGateTenantTokenHash = api.InternalFlagPrefix + "activegate-tenant-token-hash" AnnotationActiveGateContainerAppArmor = "container.apparmor.security.beta.kubernetes.io/" + ActiveGateContainerName GatewayConfigVolumeName = "ag-lib-gateway-config" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index 1ad00e44bf..e5bf4d8053 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -92,6 +92,7 @@ func (statefulSetBuilder Builder) getBaseSpec() appsv1.StatefulSetSpec { ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ consts.AnnotationActiveGateConfigurationHash: statefulSetBuilder.configHash, + consts.AnnotationActiveGateTenantTokenHash: statefulSetBuilder.dynakube.Status.ActiveGate.ConnectionInfo.TenantTokenHash, }, }, }, diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index 00d85a8e24..2e45a39aea 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" @@ -29,6 +30,7 @@ import ( const ( testKubeUID = "test-uid" testConfigHash = "test-hash" + testTokenHash = "test-hash-token" testDynakubeName = "test-dynakube" testNamespaceName = "test-namespace" ) @@ -57,6 +59,9 @@ func getTestDynakube() dynakube.DynaKube { Status: dynakube.DynaKubeStatus{ ActiveGate: activegate.Status{ VersionStatus: status.VersionStatus{}, + ConnectionInfo: communication.ConnectionInfo{ + TenantTokenHash: testTokenHash, + }, }, }, } @@ -82,6 +87,7 @@ func TestGetBaseObjectMeta(t *testing.T) { sts, _ := builder.CreateStatefulSet(nil) expectedTemplateAnnotations := map[string]string{ consts.AnnotationActiveGateConfigurationHash: testConfigHash, + consts.AnnotationActiveGateTenantTokenHash: testTokenHash, } require.NotEmpty(t, sts.Spec.Template.Labels) @@ -146,6 +152,7 @@ func TestGetBaseObjectMeta(t *testing.T) { sts, _ := builder.CreateStatefulSet(nil) expectedTemplateAnnotations := map[string]string{ consts.AnnotationActiveGateConfigurationHash: testConfigHash, + consts.AnnotationActiveGateTenantTokenHash: testTokenHash, "test": "test", } @@ -167,6 +174,7 @@ func TestGetBaseSpec(t *testing.T) { assert.Equal(t, &testReplicas, stsSpec.Replicas) require.NotNil(t, stsSpec.Template.Annotations) assert.Equal(t, testConfigHash, stsSpec.Template.Annotations[consts.AnnotationActiveGateConfigurationHash]) + assert.Equal(t, testTokenHash, stsSpec.Template.Annotations[consts.AnnotationActiveGateTenantTokenHash]) }) } diff --git a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler.go b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler.go index ce132605b0..f3dfce99b5 100644 --- a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler.go +++ b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler.go @@ -9,6 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "github.com/pkg/errors" @@ -110,6 +111,11 @@ func (r *reconciler) reconcileConnectionInfo(ctx context.Context) error { return err } + r.dk.Status.ActiveGate.ConnectionInfo.TenantTokenHash, err = hasher.GenerateHash(connectionInfo.ConnectionInfo.TenantToken) + if err != nil { + return errors.Wrap(err, "failed to generate TenantTokenHash") + } + log.Info("activegate connection info updated") return nil diff --git a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go index 663898b72d..3420b9f7dd 100644 --- a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go +++ b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go @@ -13,6 +13,7 @@ import ( dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -108,8 +109,12 @@ func TestReconcile(t *testing.T) { assert.Equal(t, metav1.ConditionTrue, condition.Status) assert.Equal(t, conditions.SecretCreatedReason, condition.Reason) + tenantTokenHash, err := hasher.GenerateHash(testTenantToken) + + require.NoError(t, err) assert.Equal(t, testTenantUUID, dk.Status.ActiveGate.ConnectionInfo.TenantUUID) assert.Equal(t, testTenantEndpoints, dk.Status.ActiveGate.ConnectionInfo.Endpoints) + assert.Equal(t, tenantTokenHash, dk.Status.ActiveGate.ConnectionInfo.TenantTokenHash) var actualSecret corev1.Secret err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.ActiveGate().GetTenantSecretName(), Namespace: testNamespace}, &actualSecret) diff --git a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go index 2c69933623..c445742255 100644 --- a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go +++ b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go @@ -128,6 +128,11 @@ func (r *reconciler) reconcileConnectionInfo(ctx context.Context) error { return err } + r.dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash, err = hasher.GenerateHash(connectionInfo.ConnectionInfo.TenantToken) + if err != nil { + return errors.Wrap(err, "failed to generate TenantTokenHash") + } + log.Info("received OneAgent communication hosts", "communication hosts", connectionInfo.CommunicationHosts, "tenant", connectionInfo.TenantUUID) return nil diff --git a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go index a16e811877..f3e0b233a4 100644 --- a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go +++ b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go @@ -12,6 +12,7 @@ import ( dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/pkg/errors" "github.com/stretchr/testify/assert" @@ -131,9 +132,13 @@ func TestReconcile(t *testing.T) { err := r.Reconcile(ctx) require.NoError(t, err) + tenantTokenHash, err := hasher.GenerateHash(testTenantToken) + + require.NoError(t, err) assert.Equal(t, testTenantUUID, dk.Status.OneAgent.ConnectionInfoStatus.TenantUUID) assert.Equal(t, testTenantEndpoints, dk.Status.OneAgent.ConnectionInfoStatus.Endpoints) assert.Equal(t, getTestCommunicationHosts(), dk.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts) + assert.Equal(t, tenantTokenHash, dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash) var actualSecret corev1.Secret err = fakeClient.Get(ctx, client.ObjectKey{Name: dk.OneAgent().GetTenantSecret(), Namespace: testNamespace}, &actualSecret) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/annotations.go b/pkg/controllers/dynakube/logmonitoring/daemonset/annotations.go new file mode 100644 index 0000000000..1716ccb173 --- /dev/null +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/annotations.go @@ -0,0 +1,22 @@ +package daemonset + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api" + maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" +) + +const annotationTenantTokenHash = api.InternalFlagPrefix + "tenant-token-hash" + +func (r *Reconciler) getAnnotations() map[string]string { + return maputils.MergeMap( + r.dk.LogMonitoring().Template().Annotations, + r.buildTenantTokenHashAnnotation()) +} + +func (r *Reconciler) buildTenantTokenHashAnnotation() map[string]string { + annotations := map[string]string{ + annotationTenantTokenHash: r.dk.Status.OneAgent.ConnectionInfoStatus.ConnectionInfo.TenantTokenHash, + } + + return annotations +} diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go index ca04f33ff1..bdf7f6e9bd 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go @@ -96,7 +96,7 @@ func (r *Reconciler) generateDaemonSet() (*appsv1.DaemonSet, error) { ds, err := daemonset.Build(r.dk, r.dk.LogMonitoring().GetDaemonSetName(), getContainer(*r.dk, tenantUUID), daemonset.SetInitContainer(getInitContainer(*r.dk, tenantUUID)), daemonset.SetAllLabels(labels.BuildLabels(), labels.BuildMatchLabels(), labels.BuildLabels(), r.dk.LogMonitoring().Template().Labels), - daemonset.SetAllAnnotations(nil, r.dk.LogMonitoring().Template().Annotations), + daemonset.SetAllAnnotations(nil, r.getAnnotations()), daemonset.SetServiceAccount(serviceAccountName), daemonset.SetDNSPolicy(r.dk.LogMonitoring().Template().DNSPolicy), daemonset.SetAffinity(node.Affinity()), diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go index 6ae01c42c3..10cd0a0d2a 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go @@ -147,8 +147,7 @@ func TestGenerateDaemonSet(t *testing.T) { t.Run("generate daemonset", func(t *testing.T) { dk := createDynakube(true) - reconciler := NewReconciler(nil, - nil, dk) + reconciler := NewReconciler(nil, fake.NewClient(), dk) daemonset, err := reconciler.generateDaemonSet() require.NoError(t, err) require.NotNil(t, daemonset) @@ -164,6 +163,8 @@ func TestGenerateDaemonSet(t *testing.T) { assert.Subset(t, daemonset.Spec.Template.Labels, daemonset.Spec.Selector.MatchLabels) require.Len(t, daemonset.Annotations, 1) assert.Contains(t, daemonset.Annotations, hasher.AnnotationHash) + require.Len(t, daemonset.Spec.Template.Annotations, 1) + assert.Contains(t, daemonset.Spec.Template.Annotations, annotationTenantTokenHash) assert.Equal(t, serviceAccountName, daemonset.Spec.Template.Spec.ServiceAccountName) assert.Empty(t, daemonset.Spec.Template.Spec.DNSPolicy) assert.Empty(t, daemonset.Spec.Template.Spec.PriorityClassName) @@ -183,8 +184,7 @@ func TestGenerateDaemonSet(t *testing.T) { Labels: customLabels, } - reconciler := NewReconciler(nil, - nil, dk) + reconciler := NewReconciler(nil, fake.NewClient(), dk) daemonset, err := reconciler.generateDaemonSet() require.NoError(t, err) require.NotNil(t, daemonset) @@ -192,23 +192,25 @@ func TestGenerateDaemonSet(t *testing.T) { assert.Subset(t, daemonset.Spec.Template.Labels, customLabels) }) - t.Run("respect custom annotations", func(t *testing.T) { + t.Run("respect annotations", func(t *testing.T) { customAnnotations := map[string]string{ "custom": "annotation", } + testTokenHash := "testTokenHash" dk := createDynakube(true) dk.Spec.Templates.LogMonitoring = &logmonitoring.TemplateSpec{ Annotations: customAnnotations, } + dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash = testTokenHash - reconciler := NewReconciler(nil, - nil, dk) + reconciler := NewReconciler(nil, fake.NewClient(), dk) daemonset, err := reconciler.generateDaemonSet() require.NoError(t, err) require.NotNil(t, daemonset) assert.Subset(t, daemonset.Spec.Template.Annotations, customAnnotations) + assert.Equal(t, testTokenHash, daemonset.Spec.Template.Annotations[annotationTenantTokenHash]) }) t.Run("respect dns policy", func(t *testing.T) { @@ -219,8 +221,7 @@ func TestGenerateDaemonSet(t *testing.T) { DNSPolicy: customPolicy, } - reconciler := NewReconciler(nil, - nil, dk) + reconciler := NewReconciler(nil, fake.NewClient(), dk) daemonset, err := reconciler.generateDaemonSet() require.NoError(t, err) require.NotNil(t, daemonset) @@ -236,8 +237,7 @@ func TestGenerateDaemonSet(t *testing.T) { PriorityClassName: customClass, } - reconciler := NewReconciler(nil, - nil, dk) + reconciler := NewReconciler(nil, fake.NewClient(), dk) daemonset, err := reconciler.generateDaemonSet() require.NoError(t, err) require.NotNil(t, daemonset) @@ -251,8 +251,7 @@ func TestGenerateDaemonSet(t *testing.T) { dk := createDynakube(true) dk.Spec.CustomPullSecret = customPullSecret - reconciler := NewReconciler(nil, - nil, dk) + reconciler := NewReconciler(nil, fake.NewClient(), dk) daemonset, err := reconciler.generateDaemonSet() require.NoError(t, err) require.NotNil(t, daemonset) @@ -273,8 +272,7 @@ func TestGenerateDaemonSet(t *testing.T) { dk.Spec.Templates.LogMonitoring = &logmonitoring.TemplateSpec{ Tolerations: customTolerations, } - reconciler := NewReconciler(nil, - nil, dk) + reconciler := NewReconciler(nil, fake.NewClient(), dk) daemonset, err := reconciler.generateDaemonSet() require.NoError(t, err) require.NotNil(t, daemonset) diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go index 0a8abd97f4..d8564e96aa 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go @@ -1,6 +1,7 @@ package daemonset import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" @@ -21,6 +22,7 @@ import ( const ( annotationUnprivileged = "container.apparmor.security.beta.kubernetes.io/dynatrace-oneagent" annotationUnprivilegedValue = "unconfined" + annotationTenantTokenHash = api.InternalFlagPrefix + "tenant-token-hash" serviceAccountName = "dynatrace-dynakube-oneagent" @@ -148,6 +150,7 @@ func (b *builder) BuildDaemonSet() (*appsv1.DaemonSet, error) { annotations := map[string]string{ annotationUnprivileged: annotationUnprivilegedValue, webhook.AnnotationDynatraceInject: "false", + annotationTenantTokenHash: dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash, } annotations = maputils.MergeMap(annotations, b.hostInjectSpec.Annotations) diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go index c9607cfa37..411797b8f2 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go @@ -22,7 +22,8 @@ import ( ) const ( - testImageTag = "1.203.0.0-0" + testImageTag = "1.203.0.0-0" + testTokenHash = "test-token-hash" ) func TestUseImmutableImage(t *testing.T) { @@ -768,9 +769,11 @@ func TestAnnotations(t *testing.T) { }, }, } + dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash = testTokenHash expectedAnnotations := map[string]string{ webhook.AnnotationDynatraceInject: "false", annotationUnprivileged: annotationUnprivilegedValue, + annotationTenantTokenHash: testTokenHash, } builder := NewCloudNativeFullStack(&dk, testClusterID) @@ -788,9 +791,11 @@ func TestAnnotations(t *testing.T) { }, }, } + dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash = testTokenHash expectedAnnotations := map[string]string{ webhook.AnnotationDynatraceInject: "false", annotationUnprivileged: annotationUnprivilegedValue, + annotationTenantTokenHash: testTokenHash, } builder := NewHostMonitoring(&dk, testClusterID) @@ -808,9 +813,11 @@ func TestAnnotations(t *testing.T) { }, }, } + dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash = testTokenHash expectedAnnotations := map[string]string{ webhook.AnnotationDynatraceInject: "false", annotationUnprivileged: annotationUnprivilegedValue, + annotationTenantTokenHash: testTokenHash, } builder := NewClassicFullStack(&dk, testClusterID) @@ -834,10 +841,12 @@ func TestAnnotations(t *testing.T) { }, }, } + dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash = testTokenHash expectedAnnotations := map[string]string{ webhook.AnnotationDynatraceInject: "false", annotationUnprivileged: annotationUnprivilegedValue, testKey: testName, + annotationTenantTokenHash: testTokenHash, } builder := NewCloudNativeFullStack(&dk, testClusterID) @@ -859,10 +868,12 @@ func TestAnnotations(t *testing.T) { }, }, } + dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash = testTokenHash expectedAnnotations := map[string]string{ webhook.AnnotationDynatraceInject: "false", annotationUnprivileged: annotationUnprivilegedValue, testKey: testName, + annotationTenantTokenHash: testTokenHash, } builder := NewHostMonitoring(&dk, testClusterID) @@ -884,10 +895,12 @@ func TestAnnotations(t *testing.T) { }, }, } + dk.Status.OneAgent.ConnectionInfoStatus.TenantTokenHash = testTokenHash expectedAnnotations := map[string]string{ webhook.AnnotationDynatraceInject: "false", annotationUnprivileged: annotationUnprivilegedValue, testKey: testName, + annotationTenantTokenHash: testTokenHash, } builder := NewClassicFullStack(&dk, testClusterID) From b4229f8fcaa9c16f55e0b6ea1218557016c58b2d Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Tue, 11 Feb 2025 10:00:45 +0100 Subject: [PATCH 194/426] New OpenSignal package to generate configurations for OTEL collector (#4306) --- go.mod | 79 +++++- go.sum | 188 ++++++++++++- pkg/otelcgen/consts.go | 17 ++ pkg/otelcgen/exporters.go | 29 ++ pkg/otelcgen/exporters_test.go | 27 ++ pkg/otelcgen/extensions.go | 15 ++ pkg/otelcgen/extensions_test.go | 25 ++ pkg/otelcgen/otelcgen.go | 204 ++++++++++++++ pkg/otelcgen/otelcgen_test.go | 32 +++ pkg/otelcgen/processors.go | 153 +++++++++++ pkg/otelcgen/processors_test.go | 25 ++ pkg/otelcgen/receivers.go | 72 +++++ pkg/otelcgen/receivers_test.go | 83 ++++++ pkg/otelcgen/services.go | 64 +++++ pkg/otelcgen/services_test.go | 24 ++ pkg/otelcgen/testdata/exporters_only.yaml | 35 +++ pkg/otelcgen/testdata/extensions_only.yaml | 31 +++ pkg/otelcgen/testdata/full_config.yaml | 254 ++++++++++++++++++ pkg/otelcgen/testdata/open-signals.yaml | 191 +++++++++++++ pkg/otelcgen/testdata/processors_only.yaml | 158 +++++++++++ .../testdata/receivers_jaeger_only.yaml | 45 ++++ .../testdata/receivers_otlp_only.yaml | 41 +++ pkg/otelcgen/testdata/receivers_statsd.yaml | 44 +++ .../testdata/receivers_zipkin_only.yaml | 34 +++ pkg/otelcgen/testdata/services_only.yaml | 69 +++++ 25 files changed, 1931 insertions(+), 8 deletions(-) create mode 100644 pkg/otelcgen/consts.go create mode 100644 pkg/otelcgen/exporters.go create mode 100644 pkg/otelcgen/exporters_test.go create mode 100644 pkg/otelcgen/extensions.go create mode 100644 pkg/otelcgen/extensions_test.go create mode 100644 pkg/otelcgen/otelcgen.go create mode 100644 pkg/otelcgen/otelcgen_test.go create mode 100644 pkg/otelcgen/processors.go create mode 100644 pkg/otelcgen/processors_test.go create mode 100644 pkg/otelcgen/receivers.go create mode 100644 pkg/otelcgen/receivers_test.go create mode 100644 pkg/otelcgen/services.go create mode 100644 pkg/otelcgen/services_test.go create mode 100644 pkg/otelcgen/testdata/exporters_only.yaml create mode 100644 pkg/otelcgen/testdata/extensions_only.yaml create mode 100644 pkg/otelcgen/testdata/full_config.yaml create mode 100644 pkg/otelcgen/testdata/open-signals.yaml create mode 100644 pkg/otelcgen/testdata/processors_only.yaml create mode 100644 pkg/otelcgen/testdata/receivers_jaeger_only.yaml create mode 100644 pkg/otelcgen/testdata/receivers_otlp_only.yaml create mode 100644 pkg/otelcgen/testdata/receivers_statsd.yaml create mode 100644 pkg/otelcgen/testdata/receivers_zipkin_only.yaml create mode 100644 pkg/otelcgen/testdata/services_only.yaml diff --git a/go.mod b/go.mod index fff83eda3f..ba0fcc0365 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,11 @@ require ( github.com/spf13/afero v1.12.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 + go.opentelemetry.io/collector/component v0.118.0 + go.opentelemetry.io/collector/confmap v1.24.0 + go.opentelemetry.io/collector/otelcol v0.118.0 + go.opentelemetry.io/collector/pipeline v0.118.0 + go.opentelemetry.io/collector/service v0.118.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.23.0 @@ -39,19 +44,24 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect + github.com/ebitengine/purego v0.8.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect @@ -59,11 +69,19 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.2 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mailru/easyjson v0.7.7 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/userns v0.1.0 // indirect @@ -73,21 +91,78 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.61.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect + github.com/shirou/gopsutil/v4 v4.24.12 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.2 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/vbatts/tar-split v0.11.6 // indirect github.com/vladimirvivien/gexe v0.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/collector/component/componentstatus v0.118.0 // indirect + go.opentelemetry.io/collector/component/componenttest v0.118.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.118.0 // indirect + go.opentelemetry.io/collector/connector v0.118.0 // indirect + go.opentelemetry.io/collector/connector/connectortest v0.118.0 // indirect + go.opentelemetry.io/collector/connector/xconnector v0.118.0 // indirect + go.opentelemetry.io/collector/consumer v1.24.0 // indirect + go.opentelemetry.io/collector/consumer/consumererror v0.118.0 // indirect + go.opentelemetry.io/collector/consumer/consumertest v0.118.0 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.118.0 // indirect + go.opentelemetry.io/collector/exporter v0.118.0 // indirect + go.opentelemetry.io/collector/exporter/exportertest v0.118.0 // indirect + go.opentelemetry.io/collector/exporter/xexporter v0.118.0 // indirect + go.opentelemetry.io/collector/extension v0.118.0 // indirect + go.opentelemetry.io/collector/extension/extensioncapabilities v0.118.0 // indirect + go.opentelemetry.io/collector/extension/extensiontest v0.118.0 // indirect + go.opentelemetry.io/collector/featuregate v1.24.0 // indirect + go.opentelemetry.io/collector/internal/fanoutconsumer v0.118.0 // indirect + go.opentelemetry.io/collector/pdata v1.24.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.118.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.118.0 // indirect + go.opentelemetry.io/collector/pipeline/xpipeline v0.118.0 // indirect + go.opentelemetry.io/collector/processor v0.118.0 // indirect + go.opentelemetry.io/collector/processor/processortest v0.118.0 // indirect + go.opentelemetry.io/collector/processor/xprocessor v0.118.0 // indirect + go.opentelemetry.io/collector/receiver v0.118.0 // indirect + go.opentelemetry.io/collector/receiver/receivertest v0.118.0 // indirect + go.opentelemetry.io/collector/receiver/xreceiver v0.118.0 // indirect + go.opentelemetry.io/collector/semconv v0.118.0 // indirect + go.opentelemetry.io/contrib/bridges/otelzap v0.6.0 // indirect + go.opentelemetry.io/contrib/config v0.10.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.31.0 // indirect + go.opentelemetry.io/otel v1.33.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.54.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect + go.opentelemetry.io/otel/log v0.8.0 // indirect + go.opentelemetry.io/otel/metric v1.33.0 // indirect + go.opentelemetry.io/otel/sdk v1.33.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.7.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.33.0 // indirect + go.opentelemetry.io/proto/otlp v1.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/term v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.8.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect google.golang.org/protobuf v1.36.3 // indirect diff --git a/go.sum b/go.sum index 7c37006814..7b94a15509 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/container-storage-interface/spec v1.11.0 h1:H/YKTOeUZwHtyPOr9raR+HgFmGluGCklulxDYxSdVNM= @@ -20,22 +22,29 @@ github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBi github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= +github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE= +github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= @@ -46,14 +55,19 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -68,6 +82,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -78,6 +96,12 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.2 h1:I2rtLRqXRy1p01m/utEtpZSSA6dcJbgGVuE27kW2PzQ= +github.com/knadh/koanf/v2 v2.1.2/go.mod h1:Gphfaen0q1Fc1HTgJgSTC4oRX9R2R5ErYMZJy8fLJBo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -87,10 +111,16 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= @@ -114,22 +144,30 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= +github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= +github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shirou/gopsutil/v4 v4.24.12 h1:qvePBOk20e0IKA1QXrIIU+jmk+zEiYVVx06WjBRlZo4= +github.com/shirou/gopsutil/v4 v4.24.12/go.mod h1:DCtMPAad2XceTeIAbGyVfycbYQNBGk2P8cvDi7/VN9o= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= @@ -150,6 +188,10 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= github.com/vladimirvivien/gexe v0.2.0 h1:nbdAQ6vbZ+ZNsolCgSVb9Fno60kzSuvtzVh6Ytqi/xY= @@ -158,18 +200,146 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/collector v0.118.0 h1:OBqxppK9Ul6bzEabcHsx11pXwgp05sBpqYxIxiOkyFo= +go.opentelemetry.io/collector v0.118.0/go.mod h1:yxfijW5k9dwd9sifTBAEoItE+ahFEtOlyvex1B99uno= +go.opentelemetry.io/collector/client v1.24.0 h1:eH7ctqDnRWNH5QVVbAvdYYdkvr8QWLkEm8FUPaaYbWE= +go.opentelemetry.io/collector/client v1.24.0/go.mod h1:C/38SYPa0tTL6ikPz/glYz6f3GVzEuT4nlEml6IBDMw= +go.opentelemetry.io/collector/component v0.118.0 h1:sSO/ObxJ+yH77Z4DmT1mlSuxhbgUmY1ztt7xCA1F/8w= +go.opentelemetry.io/collector/component v0.118.0/go.mod h1:LUJ3AL2b+tmFr3hZol3hzKzCMvNdqNq0M5CF3SWdv4M= +go.opentelemetry.io/collector/component/componentstatus v0.118.0 h1:1aCIdUjqz0noKNQr1v04P+lwF89Lkua5U7BhH9IAxkE= +go.opentelemetry.io/collector/component/componentstatus v0.118.0/go.mod h1:ynO1Nyj0t1h6x/djIMJy35bhnnWEc2mlQaFgDNUO504= +go.opentelemetry.io/collector/component/componenttest v0.118.0 h1:knEHckoiL2fEWSIc0iehg39zP4IXzi9sHa45O+oxKo8= +go.opentelemetry.io/collector/component/componenttest v0.118.0/go.mod h1:aHc7t7zVwCpbhrWIWY+GMuaMxMCUP8C8P7pJOt8r/vU= +go.opentelemetry.io/collector/config/configauth v0.118.0 h1:uBH/s9kRw/m7VWuibrkCzbXSCVLf9ElKq9NuKb0wAwk= +go.opentelemetry.io/collector/config/configauth v0.118.0/go.mod h1:uAmSGkihIENoIah6mEQ8S/HX4oiFOHZu3EoZLZwi9OI= +go.opentelemetry.io/collector/config/configcompression v1.24.0 h1:jyM6BX7wYcrh+eVSC0FMbWgy/zb9iP58SerOrvisccE= +go.opentelemetry.io/collector/config/configcompression v1.24.0/go.mod h1:LvYG00tbPTv0NOLoZN0wXq1F5thcxvukO8INq7xyfWU= +go.opentelemetry.io/collector/config/confighttp v0.118.0 h1:ey50dfySOCPgUPJ1x8Kq6CmNcv/TpZHt6cYmPhZItj0= +go.opentelemetry.io/collector/config/confighttp v0.118.0/go.mod h1:4frheVFiIfKUHuD/KAPn+u+d+EUx5GlQTNmoI1ftReA= +go.opentelemetry.io/collector/config/configopaque v1.24.0 h1:EPOprMDreZPKyIgT0/eVBvEGQVvq7ncvBCBVnWerj54= +go.opentelemetry.io/collector/config/configopaque v1.24.0/go.mod h1:sW0t0iI/VfRL9VYX7Ik6XzVgPcR+Y5kejTLsYcMyDWs= +go.opentelemetry.io/collector/config/configretry v1.24.0 h1:sIPHhNNY2YlHMIJ//63iMxIqlgDeGczId0uUb1njsPM= +go.opentelemetry.io/collector/config/configretry v1.24.0/go.mod h1:cleBc9I0DIWpTiiHfu9v83FUaCTqcPXmebpLxjEIqro= +go.opentelemetry.io/collector/config/configtelemetry v0.118.0 h1:UlN46EViG2X42odWtXgWaqY7Y01ZKpsnswSwXTWx5mM= +go.opentelemetry.io/collector/config/configtelemetry v0.118.0/go.mod h1:SlBEwQg0qly75rXZ6W1Ig8jN25KBVBkFIIAUI1GiAAE= +go.opentelemetry.io/collector/config/configtls v1.24.0 h1:rOhl8qjIlUVVRHnwQj6/vZe6cuCYImyx7aVDBR35bqI= +go.opentelemetry.io/collector/config/configtls v1.24.0/go.mod h1:d0OdfkbuYEMYDBJLSbpH0wPI29lmSiFT3geqh/ygF2k= +go.opentelemetry.io/collector/confmap v1.24.0 h1:UUHVhkDCsVw14jPOarug9PDQE2vaB2ELPWMr7ARFBCA= +go.opentelemetry.io/collector/confmap v1.24.0/go.mod h1:Rrhs+MWoaP6AswZp+ReQ2VO9dfOfcUjdjiSHBsG+nec= +go.opentelemetry.io/collector/connector v0.118.0 h1:amay4UriWrtydaAxjQ8/MTTaVYERlZcYLCAGcjoBejw= +go.opentelemetry.io/collector/connector v0.118.0/go.mod h1:R6jbMrHZYg21pZ0nsoo4cSHIn7Lrdpi5R3OWcDEQwhE= +go.opentelemetry.io/collector/connector/connectortest v0.118.0 h1:hLMSTqtFWveXa3b1qJMEaWuaX3PHx7dfl8G/bsac2fE= +go.opentelemetry.io/collector/connector/connectortest v0.118.0/go.mod h1:hm6TNLiQLe65NpENCFsFoiO8fOf3BbN4UF1heUsT73Q= +go.opentelemetry.io/collector/connector/xconnector v0.118.0 h1:0s6rwZmt8va6xd3BEZs7s2QBNFNjLv0kzYi6l44dKqc= +go.opentelemetry.io/collector/connector/xconnector v0.118.0/go.mod h1:12mJPGWo90iZrrpgOkmSd5TkejweL34V/R6AqwqJnMA= +go.opentelemetry.io/collector/consumer v1.24.0 h1:7DeyBm9qdr1EPuCfPjWyChPK16DbVc0wZeSa9LZprFU= +go.opentelemetry.io/collector/consumer v1.24.0/go.mod h1:0G6jvZprIp4dpKMD1ZxCjriiP9GdFvFMObsQEtTk71s= +go.opentelemetry.io/collector/consumer/consumererror v0.118.0 h1:Cx//ZFDa6wUEoRDRYRZ/Rkb52dWNoHj2e9FdlcM9jCA= +go.opentelemetry.io/collector/consumer/consumererror v0.118.0/go.mod h1:2mhnzzLYR5zS2Zz4h9ZnRM8Uogu9qatcfQwGNenhing= +go.opentelemetry.io/collector/consumer/consumertest v0.118.0 h1:8AAS9ejQapP1zqt0+cI6u+AUBheT3X0171N9WtXWsVY= +go.opentelemetry.io/collector/consumer/consumertest v0.118.0/go.mod h1:spRM2wyGr4QZzqMHlLmZnqRCxqXN4Wd0piogC4Qb5PQ= +go.opentelemetry.io/collector/consumer/xconsumer v0.118.0 h1:guWnzzRqgCInjnYlOQ1BPrimppNGIVvnknAjlIbWXuY= +go.opentelemetry.io/collector/consumer/xconsumer v0.118.0/go.mod h1:C5V2d6Ys/Fi6k3tzjBmbdZ9v3J/rZSAMlhx4KVcMIIg= +go.opentelemetry.io/collector/exporter v0.118.0 h1:PE0vF2U+znOB8OVLPWNw40bGCoT/5QquQ8Xbz4i9Rb0= +go.opentelemetry.io/collector/exporter v0.118.0/go.mod h1:5ST3gxT/RzE/vg2bcGDtWJxlQF1ypwk50UpmdK1kUqY= +go.opentelemetry.io/collector/exporter/exportertest v0.118.0 h1:8gWky42BcJsxoaqWbnqCDUjP3Y84hjC6RD/UWHwR7sI= +go.opentelemetry.io/collector/exporter/exportertest v0.118.0/go.mod h1:UbpQBZvznA8YPqqcKlafVIhB6Qa4fPf2+I67MUGyNqo= +go.opentelemetry.io/collector/exporter/xexporter v0.118.0 h1:PZAo1CFhZHfQwtzUNj+Fwcv/21pWHJHTsrIddD096fw= +go.opentelemetry.io/collector/exporter/xexporter v0.118.0/go.mod h1:x4J+qyrRcp4DfWKqK3DLZomFTIUhedsqCQWqq6Gqps4= +go.opentelemetry.io/collector/extension v0.118.0 h1:9o5jLCTRvs0+rtFDx04zTBuB4WFrE0RvtVCPovYV0sA= +go.opentelemetry.io/collector/extension v0.118.0/go.mod h1:BFwB0WOlse6JnrStO44+k9kwUVjjtseFEHhJLHD7lBg= +go.opentelemetry.io/collector/extension/auth v0.118.0 h1:+eMNUBUK1JK9A3mr95BasbWE90Lxu+WlR9sqS36sJms= +go.opentelemetry.io/collector/extension/auth v0.118.0/go.mod h1:MJpYcRGSERkgOhczqTKoAhkHmcugr+YTlRhc/SpYYYI= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.118.0 h1:I/SjuacUXdBOxa6ZnVMuMKkZX+m40tUm+5YKqWnNv/c= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.118.0/go.mod h1:IxDALY0rMvsENrVui7Y5tvvL/xHNgMKuhfiQiSHMiTQ= +go.opentelemetry.io/collector/extension/extensiontest v0.118.0 h1:rKBUaFS9elGfENG45wANmrwx7mHsmt1+YWCzxjftElg= +go.opentelemetry.io/collector/extension/extensiontest v0.118.0/go.mod h1:CqNXzkIOR32D8EUpptpOXhpFkibs3kFlRyNMEgIW8l4= +go.opentelemetry.io/collector/extension/xextension v0.118.0 h1:P6gvJzqnH9ma2QfnWde/E6Xu9bAzuefzIwm5iupiVPE= +go.opentelemetry.io/collector/extension/xextension v0.118.0/go.mod h1:ne4Q8ZtRlbC0Etr2hTcVkjOpVM2bE2xy1u+R80LUkDw= +go.opentelemetry.io/collector/extension/zpagesextension v0.118.0 h1:XkaLvST4p1/i/dsk5yCwFG4HJUUr6joCbegJc2MEOrE= +go.opentelemetry.io/collector/extension/zpagesextension v0.118.0/go.mod h1:alaAK7I7UeM1Hcs/eNqIjTLIZpqrk3mD1Ua42mJ7JnU= +go.opentelemetry.io/collector/featuregate v1.24.0 h1:DEqDsuJgxjZ3E5JNC9hXCd4sWGFiF7h9kaziODuqwFY= +go.opentelemetry.io/collector/featuregate v1.24.0/go.mod h1:3GaXqflNDVwWndNGBJ1+XJFy3Fv/XrFgjMN60N3z7yg= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.118.0 h1:affTj1Qxjbg9dZ1x2tbV9Rs9/otZQ1lHA++L8qB5KiQ= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.118.0/go.mod h1:9mbE68mYdtTyozr3jTtNMB1RA5F8/dt2aWVYSu6bsQ4= +go.opentelemetry.io/collector/otelcol v0.118.0 h1:uSD3wU0sO4vsw5VvWI2yUFLggLdq1BWN/nC1LJXIhMg= +go.opentelemetry.io/collector/otelcol v0.118.0/go.mod h1:OdKz/AXj+ewCwXp/acZCBIoMIYiIxeNRNkbqUXvWi+o= +go.opentelemetry.io/collector/pdata v1.24.0 h1:D6j92eAzmAbQgivNBUnt8r9juOl8ugb+ihYynoFZIEg= +go.opentelemetry.io/collector/pdata v1.24.0/go.mod h1:cf3/W9E/uIvPS4MR26SnMFJhraUCattzzM6qusuONuc= +go.opentelemetry.io/collector/pdata/pprofile v0.118.0 h1:VK/fr65VFOwEhsSGRPj5c3lCv0yIK1Kt0sZxv9WZBb8= +go.opentelemetry.io/collector/pdata/pprofile v0.118.0/go.mod h1:eJyP/vBm179EghV3dPSnamGAWQwLyd+4z/3yG54YFoQ= +go.opentelemetry.io/collector/pdata/testdata v0.118.0 h1:5N0w1SX9KIRkwvtkrpzQgXy9eGk3vfNG0ds6mhEPMIM= +go.opentelemetry.io/collector/pdata/testdata v0.118.0/go.mod h1:UY+GHV5bOC1BnFburOZ0wiHReJj1XbW12mi2Ogbc5Lw= +go.opentelemetry.io/collector/pipeline v0.118.0 h1:RI1DMe7L0+5hGkx0EDGxG00TaJoh96MEQppgOlGx1Oc= +go.opentelemetry.io/collector/pipeline v0.118.0/go.mod h1:qE3DmoB05AW0C3lmPvdxZqd/H4po84NPzd5MrqgtL74= +go.opentelemetry.io/collector/pipeline/xpipeline v0.118.0 h1:ZUVF1MYNQYZvmuL30KfP+QbVGSbFZvldBM9hgCe4J4k= +go.opentelemetry.io/collector/pipeline/xpipeline v0.118.0/go.mod h1:XgG1ktGO9J1f6fasMYPWSXL9Raan/VYB9vddKKWp5hQ= +go.opentelemetry.io/collector/processor v0.118.0 h1:NlqWiTTpPP+EPbrqTcNP9nh/4O4/9U9RGWVB49xo4ws= +go.opentelemetry.io/collector/processor v0.118.0/go.mod h1:Y8OD7wk51oPuBqrbn1qXIK91AbprRHP76hlvEzC24U4= +go.opentelemetry.io/collector/processor/processortest v0.118.0 h1:VfTLHuIaJWGyUmrvAOvf63gPMf1vAW68/jtJClEsKtU= +go.opentelemetry.io/collector/processor/processortest v0.118.0/go.mod h1:ZFWxsSoafGNOEk83FtGz43M5ypUzAOvGnfT0aQTDHdU= +go.opentelemetry.io/collector/processor/xprocessor v0.118.0 h1:M/EMhPRbadHLpv7g99fBjfgyuYexBZmgQqb2vjTXjvM= +go.opentelemetry.io/collector/processor/xprocessor v0.118.0/go.mod h1:lkoQoCv2Cz+C0kf2VHgBUDYWDecZLLeaHEvHDXbBCXU= +go.opentelemetry.io/collector/receiver v0.118.0 h1:X4mspHmbbtwdCQZ7o370kNmdWfxRnK1FrsvEShCCKEc= +go.opentelemetry.io/collector/receiver v0.118.0/go.mod h1:wFyfu6sgrkDPLQoGOGMuChGZzkZnYcI/tPJWV4CRTzs= +go.opentelemetry.io/collector/receiver/receivertest v0.118.0 h1:XlMr2mPsyXJsMUOqCpEoY3uCPsLZQbNA5fmVNDGB7Bw= +go.opentelemetry.io/collector/receiver/receivertest v0.118.0/go.mod h1:dtu/H1RNjhy11hTVf/XUfc02uGufMhYYdhhYBbglcUg= +go.opentelemetry.io/collector/receiver/xreceiver v0.118.0 h1:dzECve9e0H3ot0JWnWPuQr9Y84RhOYSd0+CjvJskx7Y= +go.opentelemetry.io/collector/receiver/xreceiver v0.118.0/go.mod h1:Lv1nD/mSYSP64iV8k+C+mWWZZOMLRubv9d1SUory3/E= +go.opentelemetry.io/collector/semconv v0.118.0 h1:V4vlMIK7TIaemrrn2VawvQPwruIKpj7Xgw9P5+BL56w= +go.opentelemetry.io/collector/semconv v0.118.0/go.mod h1:N6XE8Q0JKgBN2fAhkUQtqK9LT7rEGR6+Wu/Rtbal1iI= +go.opentelemetry.io/collector/service v0.118.0 h1:acZ9LzUbEF5M3G7o5FgenPJVuuM2y8c4HW5JVm648L4= +go.opentelemetry.io/collector/service v0.118.0/go.mod h1:uw3cl3UtkAOrEr8UQV2lXKjyTIbhWxURaQec8kE+Pic= +go.opentelemetry.io/contrib/bridges/otelzap v0.6.0 h1:j8icMXyyqNf6HGuwlYhniPnVsbJIq7n+WirDu3VAJdQ= +go.opentelemetry.io/contrib/bridges/otelzap v0.6.0/go.mod h1:evIOZpl+kAlU5IsaYX2Siw+IbpacAZvXemVsgt70uvw= +go.opentelemetry.io/contrib/config v0.10.0 h1:2JknAzMaYjxrHkTnZh3eOme/Y2P5eHE2SWfhfV6Xd6c= +go.opentelemetry.io/contrib/config v0.10.0/go.mod h1:aND2M6/KfNkntI5cyvHriR/zvZgPf8j9yETdSmvpfmc= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= +go.opentelemetry.io/contrib/propagators/b3 v1.31.0 h1:PQPXYscmwbCp76QDvO4hMngF2j8Bx/OTV86laEl8uqo= +go.opentelemetry.io/contrib/propagators/b3 v1.31.0/go.mod h1:jbqfV8wDdqSDrAYxVpXQnpM0XFMq2FtDesblJ7blOwQ= +go.opentelemetry.io/contrib/zpages v0.56.0 h1:W7vP6s3juzL5KiHpr41zLNmsJ0QAZudYu8ay0zGAoko= +go.opentelemetry.io/contrib/zpages v0.56.0/go.mod h1:IxPRP4TYHw9jLeaEOSDIiA9zmyJNZNO6sbW55iMvSXs= go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 h1:mMOmtYie9Fx6TSVzw4W+NTpvoaS1JWWga37oI1a/4qQ= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0/go.mod h1:yy7nDsMMBUkD+jeekJ36ur5f3jJIrmCwUrY67VFhNpA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= +go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= +go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 h1:TwmL3O3fRR80m8EshBrd8YydEZMcUCsZXzOUlnFohwM= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0/go.mod h1:tH98dDv5KPmPThswbXA0fr0Lwfs+OhK8HgaCo7PjRrk= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 h1:SZmDnHcgp3zwlPBS2JX2urGYe/jBKEIT6ZedHRUyCz8= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0/go.mod h1:fdWW0HtZJ7+jNpTKUR0GpMEDP69nR8YBJQxNiVCE3jk= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64= +go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= +go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= +go.opentelemetry.io/otel/sdk/log v0.7.0 h1:dXkeI2S0MLc5g0/AwxTZv6EUEjctiH8aG14Am56NTmQ= +go.opentelemetry.io/otel/sdk/log v0.7.0/go.mod h1:oIRXpW+WD6M8BuGj5rtS0aRu/86cbDV/dAfNaZBIjYM= go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= +go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg= +go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -200,8 +370,12 @@ golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= @@ -224,6 +398,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= +gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= diff --git a/pkg/otelcgen/consts.go b/pkg/otelcgen/consts.go new file mode 100644 index 0000000000..df42fc77d6 --- /dev/null +++ b/pkg/otelcgen/consts.go @@ -0,0 +1,17 @@ +package otelcgen + +const ( + OtlpGrpcPort = 4317 + OtlpHTTPPort = 4318 + + JaegerGrpcPort = 14250 + JaegerThriftBinaryPort = 6832 + JaegerThriftCompactPort = 6831 + JaegerThriftHTTPPort = 14268 + + ZipkinPort = 9411 + + StatsdPort = 8125 + + ExtensionsHealthCheckPort = 13133 +) diff --git a/pkg/otelcgen/exporters.go b/pkg/otelcgen/exporters.go new file mode 100644 index 0000000000..6cbea0be92 --- /dev/null +++ b/pkg/otelcgen/exporters.go @@ -0,0 +1,29 @@ +package otelcgen + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + otlphttp = component.MustNewID("otlphttp") +) + +func (c *Config) buildExporters() map[component.ID]component.Config { + serverConfig := &ServerConfig{ + Endpoint: c.buildEndpointWithoutPort(), + TLSSetting: &TLSSetting{}, + } + + if c.caFile != "" { + serverConfig.TLSSetting.CAFile = c.caFile + } + + if c.apiToken != "" { + serverConfig.Headers = make(map[string]string) + serverConfig.Headers["Authorization"] = "Api-Token " + c.apiToken + } + + return map[component.ID]component.Config{ + otlphttp: serverConfig, + } +} diff --git a/pkg/otelcgen/exporters_test.go b/pkg/otelcgen/exporters_test.go new file mode 100644 index 0000000000..7420c88258 --- /dev/null +++ b/pkg/otelcgen/exporters_test.go @@ -0,0 +1,27 @@ +package otelcgen + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewConfigWithExporters(t *testing.T) { + cfg, err := NewConfig( + "test", + WithCA("/run/opensignals/cacerts/certs"), + WithApiToken("test-token"), + WithExporters(), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "exporters_only.yaml")) + require.NoError(t, err) + + assert.YAMLEq(t, string(expectedOutput), string(c)) +} diff --git a/pkg/otelcgen/extensions.go b/pkg/otelcgen/extensions.go new file mode 100644 index 0000000000..defed7acb4 --- /dev/null +++ b/pkg/otelcgen/extensions.go @@ -0,0 +1,15 @@ +package otelcgen + +import "go.opentelemetry.io/collector/component" + +var ( + healthCheck = component.MustNewID("health_check") +) + +func (c *Config) buildExtensions() map[component.ID]component.Config { + return map[component.ID]component.Config{ + healthCheck: &ServerConfig{ + Endpoint: c.buildEndpoint(ExtensionsHealthCheckPort), + }, + } +} diff --git a/pkg/otelcgen/extensions_test.go b/pkg/otelcgen/extensions_test.go new file mode 100644 index 0000000000..4f02e89595 --- /dev/null +++ b/pkg/otelcgen/extensions_test.go @@ -0,0 +1,25 @@ +package otelcgen + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewConfigWithExtensions(t *testing.T) { + cfg, err := NewConfig( + "test", + WithExtensions(), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "extensions_only.yaml")) + require.NoError(t, err) + + assert.YAMLEq(t, string(expectedOutput), string(c)) +} diff --git a/pkg/otelcgen/otelcgen.go b/pkg/otelcgen/otelcgen.go new file mode 100644 index 0000000000..faba3dd993 --- /dev/null +++ b/pkg/otelcgen/otelcgen.go @@ -0,0 +1,204 @@ +package otelcgen + +import ( + "fmt" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/otelcol" + "gopkg.in/yaml.v3" +) + +// HistogramConfig is based on: +// "go.opentelemetry.io/opentelemetry-collector-contrib/receiver/statsdreceiver/internal/protocol/statsd_parser.go.HistogramConfig" +// with reduced number of attributes to reduce the number of dependencies. +type HistogramConfig struct { + MaxSize int32 `mapstructure:"max_size"` +} + +// TimerHistogramMapping is based on: +// "go.opentelemetry.io/opentelemetry-collector-contrib/receiver/statsdreceiver/internal/protocol/statsd_parser.go.TLSSetting" +// with reduced number of attributes to reduce the number of dependencies. +type TimerHistogramMapping struct { + StatsDType string `mapstructure:"statsd_type"` + ObserverType string `mapstructure:"observer_type"` + Histogram HistogramConfig `mapstructure:"histogram"` +} + +// TLSSetting is based on: +// "go.opentelemetry.io/collector/config/configtls.TLSSetting" +// with reduced number of attributes to reduce the number of dependencies. +type TLSSetting struct { + CAFile string `mapstructure:"ca_file,omitempty"` + KeyFile string `mapstructure:"key_file,omitempty"` + CertFile string `mapstructure:"cert_file,omitempty"` +} + +// ServerConfig is based on "go.opentelemetry.io/collector/config/confighttp.ServerConfig" and +// "go.opentelemetry.io/collector/config/confighttp.ServerConfig" with reduced number of attributes +// to reduce the number of dependencies. +type ServerConfig struct { + // TLSSetting struct exposes TLS client configuration. + TLSSetting *TLSSetting `mapstructure:"tls,omitempty"` + + // Additional headers attached to each HTTP request sent by the client. + // Existing header values are overwritten if collision happens. + // Header values are opaque since they may be sensitive. + Headers map[string]string `mapstructure:"headers,omitempty"` + + // The target URL to send data to (e.g.: http://some.url:9411/v1/traces). + Endpoint string `mapstructure:"endpoint"` +} + +type Protocol string + +type Protocols []Protocol + +const ( + JaegerProtocol Protocol = "jaeger" + ZipkinProtocol Protocol = "zipkin" + OtlpProtocol Protocol = "otlp" + StatsdProtocol Protocol = "statsd" +) + +var ( + JaegerID = component.MustNewID(string(JaegerProtocol)) + OtlpID = component.MustNewID(string(OtlpProtocol)) + StatsdID = component.MustNewID(string(StatsdProtocol)) + ZipkinID = component.MustNewID(string(ZipkinProtocol)) +) + +type Config struct { + cfg *otelcol.Config + tlsKey string + tlsCert string + caFile string + podIP string + apiToken string +} + +type Option func(c *Config) error + +func NewConfig(podIP string, options ...Option) (*Config, error) { + c := Config{ + cfg: &otelcol.Config{}, + podIP: podIP, + } + + for _, opt := range options { + if err := opt(&c); err != nil { + return nil, err + } + } + + return &c, nil +} + +func (c *Config) Marshal() ([]byte, error) { + conf := confmap.New() + + if err := conf.Marshal(c.cfg); err != nil { + return nil, err + } + + return yaml.Marshal(conf.ToStringMap()) +} + +func (c *Config) buildTLSSetting() *TLSSetting { + tls := &TLSSetting{} + if c.tlsCert != "" { + tls.CertFile = c.tlsCert + } + + if c.tlsKey != "" { + tls.KeyFile = c.tlsKey + } + + return tls +} + +func (c *Config) buildEndpoint(port uint) string { + return fmt.Sprintf("%s:%d", c.podIP, port) +} + +func (c *Config) buildEndpointWithoutPort() string { + return c.podIP +} + +func WithProtocols(protocols ...string) Option { + return func(c *Config) error { + receivers, err := c.buildReceivers(protocols) + if err != nil { + return err + } + + c.cfg.Receivers = receivers + + return nil + } +} + +func WithProcessors() Option { + return func(c *Config) error { + processors := c.buildProcessors() + + c.cfg.Processors = processors + + return nil + } +} + +func WithExporters() Option { + return func(c *Config) error { + exporters := c.buildExporters() + + c.cfg.Exporters = exporters + + return nil + } +} + +func WithExtensions() Option { + return func(c *Config) error { + extensions := c.buildExtensions() + + c.cfg.Extensions = extensions + + return nil + } +} + +func WithServices() Option { + return func(c *Config) error { + services := c.buildServices() + + c.cfg.Service = services + + return nil + } +} + +func WithTLS(tlsCert, tlsKey string) Option { + return func(c *Config) error { + c.tlsCert = tlsCert + c.tlsKey = tlsKey + + return nil + } +} + +func WithCA(caFile string) Option { + return func(c *Config) error { + c.caFile = caFile + + return nil + } +} + +func WithApiToken(apiToken string) Option { + return func(c *Config) error { + c.apiToken = apiToken + + return nil + } +} diff --git a/pkg/otelcgen/otelcgen_test.go b/pkg/otelcgen/otelcgen_test.go new file mode 100644 index 0000000000..aa1652f171 --- /dev/null +++ b/pkg/otelcgen/otelcgen_test.go @@ -0,0 +1,32 @@ +package otelcgen + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewConfigFull(t *testing.T) { + cfg, err := NewConfig( + "test", + WithCA("/run/opensignals/cacerts/certs"), + WithApiToken("test-token"), + WithTLS("/run/opensignals/tls/tls.crt", "/run/opensignals/tls/tls.key"), + WithProtocols("otlp", "jaeger", "zipkin", "statsd"), + WithExtensions(), + WithExporters(), + WithServices(), + WithProcessors(), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "full_config.yaml")) + require.NoError(t, err) + + assert.YAMLEq(t, string(expectedOutput), string(c)) +} diff --git a/pkg/otelcgen/processors.go b/pkg/otelcgen/processors.go new file mode 100644 index 0000000000..ff9e57552e --- /dev/null +++ b/pkg/otelcgen/processors.go @@ -0,0 +1,153 @@ +package otelcgen + +import ( + "go.opentelemetry.io/collector/component" +) + +// BatchConfig represents common attributes to config batch processor: +// inspired by +// https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/batchprocessor/config.go#L16 +type BatchConfig struct { + Timeout string `mapstructure:"timeout"` + SendBatchSize uint32 `mapstructure:"send_batch_size"` + SendBatchMaxSize uint32 `mapstructure:"send_batch_max_size"` +} + +// MemoryLimiter represents common attributes for memory limiter +// inspired by +// https://github.com/open-telemetry/opentelemetry-collector/blob/internal/memorylimiter/v0.117.0/internal/memorylimiter/config.go#L23 +type MemoryLimiter struct { + CheckInterval string `mapstructure:"check_interval"` + MemoryLimitPercentage uint32 `mapstructure:"limit_percentage"` + MemorySpikePercentage uint32 `mapstructure:"spike_limit_percentage"` +} + +// More details, about how to configure `processors,` can be found +// https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/batchprocessor/README.md +var ( + k8sattributes = component.MustNewID("k8sattributes") + transform = component.MustNewID("transform") + batch = component.MustNewType("batch") + batchTraces = component.NewIDWithName(batch, "traces") + batchMetrics = component.NewIDWithName(batch, "metrics") + batchLogs = component.NewIDWithName(batch, "logs") + memoryLimiter = component.MustNewID("memory_limiter") + + defaultK8Sattributes = []string{ + "k8s.cluster.uid", + "k8s.node.name", + "k8s.namespace.name", + "k8s.pod.name", + "k8s.pod.uid", + "k8s.pod.ip", + "k8s.deployment.name", + "k8s.replicaset.name", + "k8s.statefulset.name", + "k8s.daemonset.name", + "k8s.cronjob.name", + "k8s.job.name", + } +) + +func (c *Config) buildProcessors() map[component.ID]component.Config { + return map[component.ID]component.Config{ + k8sattributes: map[string]any{ + "extract": map[string]any{ + "metadata": defaultK8Sattributes, + "annotations": []map[string]any{ + { + "from": "pod", + "key_regex": "metadata.dynatrace.com/(.*)", + "tag_name": "$$1", + }, + }, + }, + "pod_association": []map[string]any{ + { + "sources": []map[string]any{ + {"from": "resource_attribute", "name": "k8s.pod.name"}, + {"from": "resource_attribute", "name": "k8s.namespace.name"}, + }, + }, + { + "sources": []map[string]any{ + {"from": "resource_attribute", "name": "k8s.pod.ip"}, + }, + }, + { + "sources": []map[string]any{ + {"from": "resource_attribute", "name": "k8s.pod.uid"}, + }, + }, + { + "sources": []map[string]any{ + {"from": "connection"}, + }, + }, + }, + }, + transform: c.buildTransform(), + batchTraces: &BatchConfig{ + SendBatchSize: 5000, + SendBatchMaxSize: 5000, + Timeout: "60s", + }, + batchMetrics: &BatchConfig{ + SendBatchSize: 3000, + SendBatchMaxSize: 3000, + Timeout: "60s", + }, + batchLogs: &BatchConfig{ + SendBatchSize: 1800, + SendBatchMaxSize: 2000, + Timeout: "60s", + }, + memoryLimiter: &MemoryLimiter{ + CheckInterval: "1s", + MemoryLimitPercentage: 70, + MemorySpikePercentage: 30, + }, + } +} + +func (c *Config) buildTransform() map[string]any { + return map[string]any{ + "error_mode": "ignore", + "log_statements": c.dynatraceTransformations(), + "metric_statements": c.dynatraceTransformations(), + "trace_statements": c.dynatraceTransformations(), + } +} + +func (c *Config) dynatraceTransformations() []map[string]any { + return []map[string]any{ + { + "context": "resource", + "statements": []string{ + "set(attributes[\"k8s.workload.name\"], attributes[\"k8s.statefulset.name\"]) where IsString(attributes[\"k8s.statefulset.name\"])", + "set(attributes[\"k8s.workload.name\"], attributes[\"k8s.replicaset.name\"]) where IsString(attributes[\"k8s.replicaset.name\"])", + "set(attributes[\"k8s.workload.name\"], attributes[\"k8s.job.name\"]) where IsString(attributes[\"k8s.job.name\"])", + "set(attributes[\"k8s.workload.name\"], attributes[\"k8s.deployment.name\"]) where IsString(attributes[\"k8s.deployment.name\"])", + "set(attributes[\"k8s.workload.name\"], attributes[\"k8s.daemonset.name\"]) where IsString(attributes[\"k8s.daemonset.name\"])", + "set(attributes[\"k8s.workload.name\"], attributes[\"k8s.cronjob.name\"]) where IsString(attributes[\"k8s.cronjob.name\"])", + "set(attributes[\"k8s.workload.kind\"], \"statefulset\") where IsString(attributes[\"k8s.statefulset.name\"])", + "set(attributes[\"k8s.workload.kind\"], \"replicaset\") where IsString(attributes[\"k8s.replicaset.name\"])", + "set(attributes[\"k8s.workload.kind\"], \"job\") where IsString(attributes[\"k8s.job.name\"])", + "set(attributes[\"k8s.workload.kind\"], \"deployment\") where IsString(attributes[\"k8s.deployment.name\"])", + "set(attributes[\"k8s.workload.kind\"], \"daemonset\") where IsString(attributes[\"k8s.daemonset.name\"])", + "set(attributes[\"k8s.workload.kind\"], \"cronjob\") where IsString(attributes[\"k8s.cronjob.name\"])", + "set(attributes[\"k8s.cluster.uid\"], \"${env:K8S_CLUSTER_UID}\") where attributes[\"k8s.cluster.uid\"] == nil", + "set(attributes[\"k8s.cluster.name\"], \"${env:K8S_CLUSTER_NAME}\")", + "set(attributes[\"dt.kubernetes.workload.name\"], attributes[\"k8s.workload.name\"])", + "set(attributes[\"dt.kubernetes.workload.kind\"], attributes[\"k8s.workload.kind\"])", + "set(attributes[\"dt.entity.kubernetes_cluster\"], \"${env:DT_ENTITY_KUBERNETES_CLUSTER}\")", + "delete_key(attributes, \"k8s.statefulset.name\")", + "delete_key(attributes, \"k8s.replicaset.name\")", + "delete_key(attributes, \"k8s.job.name\")", + "delete_key(attributes, \"k8s.deployment.name\")", + "delete_key(attributes, \"k8s.daemonset.name\")", + "delete_key(attributes, \"k8s.cronjob.name\")", + }, + }, + } +} diff --git a/pkg/otelcgen/processors_test.go b/pkg/otelcgen/processors_test.go new file mode 100644 index 0000000000..aff42a651a --- /dev/null +++ b/pkg/otelcgen/processors_test.go @@ -0,0 +1,25 @@ +package otelcgen + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewConfigWithProcessors(t *testing.T) { + cfg, err := NewConfig( + "", + WithProcessors(), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "processors_only.yaml")) + require.NoError(t, err) + + assert.YAMLEq(t, string(expectedOutput), string(c)) +} diff --git a/pkg/otelcgen/receivers.go b/pkg/otelcgen/receivers.go new file mode 100644 index 0000000000..d382e0a4b5 --- /dev/null +++ b/pkg/otelcgen/receivers.go @@ -0,0 +1,72 @@ +package otelcgen + +import ( + "fmt" + + "go.opentelemetry.io/collector/component" +) + +func (c *Config) buildReceiverComponent(componentID component.ID) component.Config { + switch componentID { + case OtlpID: + return map[string]any{"protocols": map[string]any{ + "grpc": &ServerConfig{TLSSetting: c.buildTLSSetting(), Endpoint: c.buildEndpoint(OtlpGrpcPort)}, + "http": &ServerConfig{TLSSetting: c.buildTLSSetting(), Endpoint: c.buildEndpoint(OtlpHTTPPort)}, + }} + case JaegerID: + return map[string]any{"protocols": map[string]any{ + "grpc": &ServerConfig{Endpoint: c.buildEndpoint(JaegerGrpcPort), TLSSetting: c.buildTLSSetting()}, + "thrift_binary": &ServerConfig{Endpoint: c.buildEndpoint(JaegerThriftBinaryPort)}, + "thrift_compact": &ServerConfig{Endpoint: c.buildEndpoint(JaegerThriftCompactPort)}, + "thrift_http": &ServerConfig{Endpoint: c.buildEndpoint(JaegerThriftHTTPPort), TLSSetting: c.buildTLSSetting()}, + }} + case ZipkinID: + return &ServerConfig{ + Endpoint: c.buildEndpoint(ZipkinPort), + TLSSetting: c.buildTLSSetting(), + } + case StatsdID: + return map[string]any{ + "endpoint": c.buildEndpoint(StatsdPort), + "timer_histogram_mapping": []TimerHistogramMapping{ + { + StatsDType: "histogram", ObserverType: "histogram", Histogram: HistogramConfig{MaxSize: 10}, + }, + { + StatsDType: "timing", ObserverType: "histogram", Histogram: HistogramConfig{MaxSize: 100}, + }, + { + StatsDType: "distribution", ObserverType: "histogram", Histogram: HistogramConfig{MaxSize: 100}, + }, + }, + } + } + + return nil +} + +func (c *Config) buildReceivers(protocols []string) (map[component.ID]component.Config, error) { + if len(protocols) == 0 { + // means all protocols are enabled + protocols = []string{string(StatsdProtocol), string(ZipkinProtocol), string(JaegerProtocol), string(OtlpProtocol)} + } + + receivers := make(map[component.ID]component.Config) + + for _, p := range protocols { + switch Protocol(p) { + case StatsdProtocol: + receivers[StatsdID] = c.buildReceiverComponent(StatsdID) + case ZipkinProtocol: + receivers[ZipkinID] = c.buildReceiverComponent(ZipkinID) + case JaegerProtocol: + receivers[JaegerID] = c.buildReceiverComponent(JaegerID) + case OtlpProtocol: + receivers[OtlpID] = c.buildReceiverComponent(OtlpID) + default: + return nil, fmt.Errorf("unknown protocol: %s", p) + } + } + + return receivers, nil +} diff --git a/pkg/otelcgen/receivers_test.go b/pkg/otelcgen/receivers_test.go new file mode 100644 index 0000000000..037e51cd49 --- /dev/null +++ b/pkg/otelcgen/receivers_test.go @@ -0,0 +1,83 @@ +package otelcgen + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewConfig(t *testing.T) { + t.Run("with statsd protocol only", func(t *testing.T) { + cfg, err := NewConfig( + "test", + WithProtocols("statsd"), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "receivers_statsd.yaml")) + require.NoError(t, err) + + assert.YAMLEq(t, string(expectedOutput), string(c)) + }) + + t.Run("with zipkin protocol only with tls key and tls cert", func(t *testing.T) { + cfg, err := NewConfig( + "test", + WithTLS("/run/opensignals/tls/tls.crt", "/run/opensignals/tls/tls.key"), + WithProtocols("zipkin"), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "receivers_zipkin_only.yaml")) + require.NoError(t, err) + assert.YAMLEq(t, string(expectedOutput), string(c)) + }) + + t.Run("with jaeger protocol only with tls key and tls cert", func(t *testing.T) { + cfg, err := NewConfig( + "test", + WithTLS("/run/opensignals/tls/tls.crt", "/run/opensignals/tls/tls.key"), + WithProtocols("jaeger"), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "receivers_jaeger_only.yaml")) + require.NoError(t, err) + + assert.YAMLEq(t, string(expectedOutput), string(c)) + }) + + t.Run("with otlp protocol only with tls key and tls cert", func(t *testing.T) { + cfg, err := NewConfig( + "test", + WithTLS("/run/opensignals/tls/tls.crt", "/run/opensignals/tls/tls.key"), + WithProtocols("otlp"), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "receivers_otlp_only.yaml")) + require.NoError(t, err) + + assert.YAMLEq(t, string(expectedOutput), string(c)) + }) + + t.Run("with unknown protocol", func(t *testing.T) { + _, err := NewConfig( + "", + WithProtocols("unknown"), + ) + require.Error(t, err) + assert.Contains(t, err.Error(), "unknown protocol") + }) +} diff --git a/pkg/otelcgen/services.go b/pkg/otelcgen/services.go new file mode 100644 index 0000000000..47afbf08fb --- /dev/null +++ b/pkg/otelcgen/services.go @@ -0,0 +1,64 @@ +package otelcgen + +import ( + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/pipeline" + "go.opentelemetry.io/collector/service" + "go.opentelemetry.io/collector/service/extensions" + "go.opentelemetry.io/collector/service/pipelines" + "go.opentelemetry.io/collector/service/telemetry" +) + +var ( + traces = pipeline.MustNewID("traces") + metrics = pipeline.MustNewID("metrics") + logs = pipeline.MustNewID("logs") + debug = component.MustNewID("debug") +) + +func (c *Config) buildServices() service.Config { + return service.Config{ + Telemetry: telemetry.Config{ + Logs: telemetry.LogsConfig{}, + Metrics: telemetry.MetricsConfig{}, + Traces: telemetry.TracesConfig{}, + Resource: nil, + }, + Extensions: extensions.Config{healthCheck}, + Pipelines: pipelines.Config{ + traces: &pipelines.PipelineConfig{ + Receivers: buildReceivers(), + Processors: append(buildProcessors(), batchTraces), + Exporters: buildExporters(), + }, + metrics: &pipelines.PipelineConfig{ + Receivers: buildReceivers(), + Processors: append(buildProcessors(), batchMetrics), + Exporters: buildExporters(), + }, + logs: &pipelines.PipelineConfig{ + Receivers: buildReceivers(), + Processors: append(buildProcessors(), batchLogs), + Exporters: buildExporters(), + }, + }, + } +} + +func buildReceivers() []component.ID { + return []component.ID{ + OtlpID, JaegerID, ZipkinID, + } +} + +func buildExporters() []component.ID { + return []component.ID{ + otlphttp, debug, + } +} + +func buildProcessors() []component.ID { + return []component.ID{ + memoryLimiter, k8sattributes, transform, + } +} diff --git a/pkg/otelcgen/services_test.go b/pkg/otelcgen/services_test.go new file mode 100644 index 0000000000..2448761062 --- /dev/null +++ b/pkg/otelcgen/services_test.go @@ -0,0 +1,24 @@ +package otelcgen + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewConfigWithServices(t *testing.T) { + cfg, err := NewConfig( + "", + WithServices(), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "services_only.yaml")) + require.NoError(t, err) + assert.YAMLEq(t, string(expectedOutput), string(c)) +} diff --git a/pkg/otelcgen/testdata/exporters_only.yaml b/pkg/otelcgen/testdata/exporters_only.yaml new file mode 100644 index 0000000000..f1a82d9ba4 --- /dev/null +++ b/pkg/otelcgen/testdata/exporters_only.yaml @@ -0,0 +1,35 @@ +connectors: {} +exporters: + otlphttp: + endpoint: "test" + tls: + ca_file: "/run/opensignals/cacerts/certs" + headers: + Authorization: "Api-Token test-token" +extensions: {} +processors: {} +receivers: {} +service: + extensions: [] + pipelines: {} + telemetry: + logs: + development: false + disable_caller: false + disable_stacktrace: false + encoding: "" + error_output_paths: [] + initial_fields: {} + level: info + output_paths: [] + processors: [] + sampling: null + metrics: + address: "" + level: Basic + readers: [] + resource: {} + traces: + level: Basic + processors: [] + propagators: [] diff --git a/pkg/otelcgen/testdata/extensions_only.yaml b/pkg/otelcgen/testdata/extensions_only.yaml new file mode 100644 index 0000000000..7d028089aa --- /dev/null +++ b/pkg/otelcgen/testdata/extensions_only.yaml @@ -0,0 +1,31 @@ +connectors: {} +exporters: {} +extensions: + health_check: + endpoint: test:13133 +processors: {} +receivers: {} +service: + extensions: [] + pipelines: {} + telemetry: + logs: + development: false + disable_caller: false + disable_stacktrace: false + encoding: "" + error_output_paths: [] + initial_fields: {} + level: info + output_paths: [] + processors: [] + sampling: null + metrics: + address: "" + level: Basic + readers: [] + resource: {} + traces: + level: Basic + processors: [] + propagators: [] diff --git a/pkg/otelcgen/testdata/full_config.yaml b/pkg/otelcgen/testdata/full_config.yaml new file mode 100644 index 0000000000..d8a4e74ce2 --- /dev/null +++ b/pkg/otelcgen/testdata/full_config.yaml @@ -0,0 +1,254 @@ +connectors: {} +exporters: + otlphttp: + endpoint: "test" + tls: + ca_file: "/run/opensignals/cacerts/certs" + headers: + Authorization: "Api-Token test-token" +extensions: + health_check: + endpoint: test:13133 +processors: + k8sattributes: + extract: + annotations: + - from: pod + key_regex: metadata.dynatrace.com/(.*) + tag_name: $$1 + metadata: + - k8s.cluster.uid + - k8s.node.name + - k8s.namespace.name + - k8s.pod.name + - k8s.pod.uid + - k8s.pod.ip + - k8s.deployment.name + - k8s.replicaset.name + - k8s.statefulset.name + - k8s.daemonset.name + - k8s.cronjob.name + - k8s.job.name + pod_association: + - sources: + - from: resource_attribute + name: k8s.pod.name + - from: resource_attribute + name: k8s.namespace.name + - sources: + - from: resource_attribute + name: k8s.pod.ip + - sources: + - from: resource_attribute + name: k8s.pod.uid + - sources: + - from: connection + transform: + error_mode: ignore + log_statements: + - context: resource + statements: + - set(attributes["k8s.workload.name"], attributes["k8s.statefulset.name"]) where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.replicaset.name"]) where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.job.name"]) where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.deployment.name"]) where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.daemonset.name"]) where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.cronjob.name"]) where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.workload.kind"], "statefulset") where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.kind"], "replicaset") where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.kind"], "job") where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.kind"], "deployment") where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.kind"], "daemonset") where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.kind"], "cronjob") where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.cluster.uid"], "${env:K8S_CLUSTER_UID}") where attributes["k8s.cluster.uid"] == nil + - set(attributes["k8s.cluster.name"], "${env:K8S_CLUSTER_NAME}") + - set(attributes["dt.kubernetes.workload.name"], attributes["k8s.workload.name"]) + - set(attributes["dt.kubernetes.workload.kind"], attributes["k8s.workload.kind"]) + - set(attributes["dt.entity.kubernetes_cluster"], "${env:DT_ENTITY_KUBERNETES_CLUSTER}") + - delete_key(attributes, "k8s.statefulset.name") + - delete_key(attributes, "k8s.replicaset.name") + - delete_key(attributes, "k8s.job.name") + - delete_key(attributes, "k8s.deployment.name") + - delete_key(attributes, "k8s.daemonset.name") + - delete_key(attributes, "k8s.cronjob.name") + metric_statements: + - context: resource + statements: + - set(attributes["k8s.workload.name"], attributes["k8s.statefulset.name"]) where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.replicaset.name"]) where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.job.name"]) where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.deployment.name"]) where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.daemonset.name"]) where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.cronjob.name"]) where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.workload.kind"], "statefulset") where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.kind"], "replicaset") where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.kind"], "job") where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.kind"], "deployment") where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.kind"], "daemonset") where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.kind"], "cronjob") where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.cluster.uid"], "${env:K8S_CLUSTER_UID}") where attributes["k8s.cluster.uid"] == nil + - set(attributes["k8s.cluster.name"], "${env:K8S_CLUSTER_NAME}") + - set(attributes["dt.kubernetes.workload.name"], attributes["k8s.workload.name"]) + - set(attributes["dt.kubernetes.workload.kind"], attributes["k8s.workload.kind"]) + - set(attributes["dt.entity.kubernetes_cluster"], "${env:DT_ENTITY_KUBERNETES_CLUSTER}") + - delete_key(attributes, "k8s.statefulset.name") + - delete_key(attributes, "k8s.replicaset.name") + - delete_key(attributes, "k8s.job.name") + - delete_key(attributes, "k8s.deployment.name") + - delete_key(attributes, "k8s.daemonset.name") + - delete_key(attributes, "k8s.cronjob.name") + trace_statements: + - context: resource + statements: + - set(attributes["k8s.workload.name"], attributes["k8s.statefulset.name"]) where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.replicaset.name"]) where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.job.name"]) where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.deployment.name"]) where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.daemonset.name"]) where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.cronjob.name"]) where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.workload.kind"], "statefulset") where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.kind"], "replicaset") where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.kind"], "job") where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.kind"], "deployment") where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.kind"], "daemonset") where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.kind"], "cronjob") where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.cluster.uid"], "${env:K8S_CLUSTER_UID}") where attributes["k8s.cluster.uid"] == nil + - set(attributes["k8s.cluster.name"], "${env:K8S_CLUSTER_NAME}") + - set(attributes["dt.kubernetes.workload.name"], attributes["k8s.workload.name"]) + - set(attributes["dt.kubernetes.workload.kind"], attributes["k8s.workload.kind"]) + - set(attributes["dt.entity.kubernetes_cluster"], "${env:DT_ENTITY_KUBERNETES_CLUSTER}") + - delete_key(attributes, "k8s.statefulset.name") + - delete_key(attributes, "k8s.replicaset.name") + - delete_key(attributes, "k8s.job.name") + - delete_key(attributes, "k8s.deployment.name") + - delete_key(attributes, "k8s.daemonset.name") + - delete_key(attributes, "k8s.cronjob.name") + batch/traces: + send_batch_size: 5000 + send_batch_max_size: 5000 + timeout: 60s + batch/metrics: + send_batch_size: 3000 + send_batch_max_size: 3000 + timeout: 60s + batch/logs: + send_batch_size: 1800 + send_batch_max_size: 2000 + timeout: 60s + memory_limiter: + check_interval: 1s + limit_percentage: 70 + spike_limit_percentage: 30 +receivers: + otlp: + protocols: + grpc: + endpoint: test:4317 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + http: + endpoint: test:4318 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + jaeger: + protocols: + grpc: + endpoint: test:14250 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + thrift_binary: + endpoint: test:6832 + thrift_compact: + endpoint: test:6831 + thrift_http: + endpoint: test:14268 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + zipkin: + endpoint: test:9411 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + statsd: + endpoint: test:8125 + timer_histogram_mapping: + - histogram: + max_size: 10 + observer_type: histogram + statsd_type: histogram + - histogram: + max_size: 100 + observer_type: histogram + statsd_type: timing + - histogram: + max_size: 100 + observer_type: histogram + statsd_type: distribution +service: + extensions: + - health_check + pipelines: + logs: + exporters: + - otlphttp + - debug + receivers: + - otlp + - jaeger + - zipkin + processors: + - memory_limiter + - k8sattributes + - transform + - batch/logs + metrics: + exporters: + - otlphttp + - debug + receivers: + - otlp + - jaeger + - zipkin + processors: + - memory_limiter + - k8sattributes + - transform + - batch/metrics + traces: + exporters: + - otlphttp + - debug + receivers: + - otlp + - jaeger + - zipkin + processors: + - memory_limiter + - k8sattributes + - transform + - batch/traces + telemetry: + logs: + development: false + disable_caller: false + disable_stacktrace: false + encoding: "" + error_output_paths: [ ] + initial_fields: { } + level: info + output_paths: [ ] + processors: [ ] + sampling: null + metrics: + address: "" + level: Basic + readers: [ ] + resource: { } + traces: + level: Basic + processors: [ ] + propagators: [ ] diff --git a/pkg/otelcgen/testdata/open-signals.yaml b/pkg/otelcgen/testdata/open-signals.yaml new file mode 100644 index 0000000000..495fee1976 --- /dev/null +++ b/pkg/otelcgen/testdata/open-signals.yaml @@ -0,0 +1,191 @@ +### receiveres ### +receivers: + otlp: + protocols: + grpc: + endpoint: ${env:MY_POD_IP}:4317 + tls: # if .spec.openSignals.tlsRef + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + http: + endpoint: ${env:MY_POD_IP}:4318 + tls: # if .spec.openSignals.tlsRef + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + jaeger: + protocols: + grpc: + endpoint: ${env:MY_POD_IP}:14250 + tls: # if .spec.openSignals.tlsRef + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + thrift_binary: + endpoint: ${env:MY_POD_IP}:6832 + thrift_compact: + endpoint: ${env:MY_POD_IP}:6831 + thrift_http: + endpoint: ${env:MY_POD_IP}:14268 + tls: # if .spec.openSignals.tlsRef + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + zipkin: + endpoint: ${env:MY_POD_IP}:9411 + tls: # if .spec.openSignals.tlsRef + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + statsd: + endpoint: ${env:MY_POD_IP}:8125 + timer_histogram_mapping: + - statsd_type: "histogram" + observer_type: "histogram" + histogram: + max_size: 100 + - statsd_type: "timing" + observer_type: "histogram" + histogram: + max_size: 100 + - statsd_type: "distribution" + observer_type: "histogram" + histogram: + max_size: 100 + +### processors ### +processors: + cumulativetodelta: + k8sattributes: + extract: + metadata: + - k8s.cluster.uid + - k8s.node.name + - k8s.namespace.name + - k8s.pod.name + - k8s.pod.uid + - k8s.pod.ip + - k8s.deployment.name + - k8s.replicaset.name + - k8s.statefulset.name + - k8s.daemonset.name + - k8s.cronjob.name + - k8s.job.name + annotations: + - from: pod + key_regex: metadata.dynatrace.com/(.*) + tag_name: $$1 + pod_association: + - sources: + - from: resource_attribute + name: k8s.pod.name + - from: resource_attribute + name: k8s.namespace.name + - sources: + - from: resource_attribute + name: k8s.pod.ip + - sources: + - from: resource_attribute + name: k8s.pod.uid + - sources: + - from: connection + transform: + error_mode: ignore + trace_statements: &dynatrace_transformations + - context: resource + statements: + - set(attributes["k8s.workload.kind"], "job") where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.job.name"]) where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.kind"], "cronjob") where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.cronjob.name"]) where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.workload.kind"], "daemonset") where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.daemonset.name"]) where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.kind"], "statefulset") where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.statefulset.name"]) where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.kind"], "replicaset") where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.replicaset.name"]) where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.kind"], "deployment") where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.deployment.name"]) where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.cluster.name"], "${env:K8S_CLUSTER_NAME}") + - set(attributes["k8s.cluster.uid"], "${env:K8S_CLUSTER_UID}") where attributes["k8s.cluster.uid"] == nil + - set(attributes["dt.entity.kubernetes_cluster"], "${env:DT_ENTITY_KUBERNETES_CLUSTER}") + - delete_key(attributes, "k8s.deployment.name") + - delete_key(attributes, "k8s.replicaset.name") + - delete_key(attributes, "k8s.statefulset.name") + - delete_key(attributes, "k8s.daemonset.name") + - delete_key(attributes, "k8s.cronjob.name") + - delete_key(attributes, "k8s.job.name") + - set(attributes["dt.kubernetes.workload.name"], attributes["k8s.workload.name"]) + - set(attributes["dt.kubernetes.workload.kind"], attributes["k8s.workload.kind"]) + metric_statements: *dynatrace_transformations + log_statements: *dynatrace_transformations + batch/traces: + send_batch_size: 5000 + send_batch_max_size: 5000 + timeout: 60s + batch/metrics: + send_batch_size: 3000 + send_batch_max_size: 3000 + timeout: 60s + batch/logs: + send_batch_size: 1800 + send_batch_max_size: 2000 + timeout: 60s + memory_limiter: + check_interval: 1s + limit_percentage: 70 + spike_limit_percentage: 30 + +### exporters ### +exporters: + debug: + otlphttp: + endpoint: "${env:DT_ENDPOINT}" + tls: # if in-cluster AG + ca_file: /run/opensignals/cacerts/certs + headers: + Authorization: "Api-Token ${env:DT_API_TOKEN}" + +### extensions ### +extensions: + health_check: + endpoint: ${env:MY_POD_IP}:13133 + +### service ### +service: + extensions: + - health_check + pipelines: + traces: + receivers: + - otlp + - jaeger + - zipkin + processors: + - memory_limiter + - k8sattributes + - transform + - batch/traces + exporters: + - otlphttp + - debug + metrics: + receivers: + - otlp + - statsd + processors: + - memory_limiter + - cumulativetodelta + - k8sattributes + - transform + - batch/metrics + exporters: + - otlphttp + - debug + logs: + receivers: + - otlp + processors: + - memory_limiter + - k8sattributes + - transform + - batch/logs + exporters: + - otlphttp + - debug diff --git a/pkg/otelcgen/testdata/processors_only.yaml b/pkg/otelcgen/testdata/processors_only.yaml new file mode 100644 index 0000000000..24b6e5f747 --- /dev/null +++ b/pkg/otelcgen/testdata/processors_only.yaml @@ -0,0 +1,158 @@ +connectors: {} +exporters: {} +extensions: {} +processors: + k8sattributes: + extract: + annotations: + - from: pod + key_regex: metadata.dynatrace.com/(.*) + tag_name: $$1 + metadata: + - k8s.cluster.uid + - k8s.node.name + - k8s.namespace.name + - k8s.pod.name + - k8s.pod.uid + - k8s.pod.ip + - k8s.deployment.name + - k8s.replicaset.name + - k8s.statefulset.name + - k8s.daemonset.name + - k8s.cronjob.name + - k8s.job.name + pod_association: + - sources: + - from: resource_attribute + name: k8s.pod.name + - from: resource_attribute + name: k8s.namespace.name + - sources: + - from: resource_attribute + name: k8s.pod.ip + - sources: + - from: resource_attribute + name: k8s.pod.uid + - sources: + - from: connection + transform: + error_mode: ignore + log_statements: + - context: resource + statements: + - set(attributes["k8s.workload.name"], attributes["k8s.statefulset.name"]) where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.replicaset.name"]) where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.job.name"]) where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.deployment.name"]) where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.daemonset.name"]) where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.cronjob.name"]) where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.workload.kind"], "statefulset") where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.kind"], "replicaset") where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.kind"], "job") where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.kind"], "deployment") where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.kind"], "daemonset") where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.kind"], "cronjob") where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.cluster.uid"], "${env:K8S_CLUSTER_UID}") where attributes["k8s.cluster.uid"] == nil + - set(attributes["k8s.cluster.name"], "${env:K8S_CLUSTER_NAME}") + - set(attributes["dt.kubernetes.workload.name"], attributes["k8s.workload.name"]) + - set(attributes["dt.kubernetes.workload.kind"], attributes["k8s.workload.kind"]) + - set(attributes["dt.entity.kubernetes_cluster"], "${env:DT_ENTITY_KUBERNETES_CLUSTER}") + - delete_key(attributes, "k8s.statefulset.name") + - delete_key(attributes, "k8s.replicaset.name") + - delete_key(attributes, "k8s.job.name") + - delete_key(attributes, "k8s.deployment.name") + - delete_key(attributes, "k8s.daemonset.name") + - delete_key(attributes, "k8s.cronjob.name") + metric_statements: + - context: resource + statements: + - set(attributes["k8s.workload.name"], attributes["k8s.statefulset.name"]) where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.replicaset.name"]) where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.job.name"]) where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.deployment.name"]) where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.daemonset.name"]) where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.cronjob.name"]) where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.workload.kind"], "statefulset") where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.kind"], "replicaset") where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.kind"], "job") where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.kind"], "deployment") where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.kind"], "daemonset") where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.kind"], "cronjob") where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.cluster.uid"], "${env:K8S_CLUSTER_UID}") where attributes["k8s.cluster.uid"] == nil + - set(attributes["k8s.cluster.name"], "${env:K8S_CLUSTER_NAME}") + - set(attributes["dt.kubernetes.workload.name"], attributes["k8s.workload.name"]) + - set(attributes["dt.kubernetes.workload.kind"], attributes["k8s.workload.kind"]) + - set(attributes["dt.entity.kubernetes_cluster"], "${env:DT_ENTITY_KUBERNETES_CLUSTER}") + - delete_key(attributes, "k8s.statefulset.name") + - delete_key(attributes, "k8s.replicaset.name") + - delete_key(attributes, "k8s.job.name") + - delete_key(attributes, "k8s.deployment.name") + - delete_key(attributes, "k8s.daemonset.name") + - delete_key(attributes, "k8s.cronjob.name") + trace_statements: + - context: resource + statements: + - set(attributes["k8s.workload.name"], attributes["k8s.statefulset.name"]) where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.replicaset.name"]) where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.job.name"]) where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.deployment.name"]) where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.daemonset.name"]) where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.name"], attributes["k8s.cronjob.name"]) where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.workload.kind"], "statefulset") where IsString(attributes["k8s.statefulset.name"]) + - set(attributes["k8s.workload.kind"], "replicaset") where IsString(attributes["k8s.replicaset.name"]) + - set(attributes["k8s.workload.kind"], "job") where IsString(attributes["k8s.job.name"]) + - set(attributes["k8s.workload.kind"], "deployment") where IsString(attributes["k8s.deployment.name"]) + - set(attributes["k8s.workload.kind"], "daemonset") where IsString(attributes["k8s.daemonset.name"]) + - set(attributes["k8s.workload.kind"], "cronjob") where IsString(attributes["k8s.cronjob.name"]) + - set(attributes["k8s.cluster.uid"], "${env:K8S_CLUSTER_UID}") where attributes["k8s.cluster.uid"] == nil + - set(attributes["k8s.cluster.name"], "${env:K8S_CLUSTER_NAME}") + - set(attributes["dt.kubernetes.workload.name"], attributes["k8s.workload.name"]) + - set(attributes["dt.kubernetes.workload.kind"], attributes["k8s.workload.kind"]) + - set(attributes["dt.entity.kubernetes_cluster"], "${env:DT_ENTITY_KUBERNETES_CLUSTER}") + - delete_key(attributes, "k8s.statefulset.name") + - delete_key(attributes, "k8s.replicaset.name") + - delete_key(attributes, "k8s.job.name") + - delete_key(attributes, "k8s.deployment.name") + - delete_key(attributes, "k8s.daemonset.name") + - delete_key(attributes, "k8s.cronjob.name") + batch/traces: + send_batch_size: 5000 + send_batch_max_size: 5000 + timeout: 60s + batch/metrics: + send_batch_size: 3000 + send_batch_max_size: 3000 + timeout: 60s + batch/logs: + send_batch_size: 1800 + send_batch_max_size: 2000 + timeout: 60s + memory_limiter: + check_interval: 1s + limit_percentage: 70 + spike_limit_percentage: 30 +receivers: {} +service: + extensions: [] + pipelines: {} + telemetry: + logs: + development: false + disable_caller: false + disable_stacktrace: false + encoding: "" + error_output_paths: [] + initial_fields: {} + level: info + output_paths: [] + processors: [] + sampling: null + metrics: + address: "" + level: Basic + readers: [] + resource: {} + traces: + level: Basic + processors: [] + propagators: [] diff --git a/pkg/otelcgen/testdata/receivers_jaeger_only.yaml b/pkg/otelcgen/testdata/receivers_jaeger_only.yaml new file mode 100644 index 0000000000..73117b4e28 --- /dev/null +++ b/pkg/otelcgen/testdata/receivers_jaeger_only.yaml @@ -0,0 +1,45 @@ +connectors: {} +exporters: {} +extensions: {} +processors: {} +receivers: + jaeger: + protocols: + grpc: + endpoint: test:14250 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + thrift_binary: + endpoint: test:6832 + thrift_compact: + endpoint: test:6831 + thrift_http: + endpoint: test:14268 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key +service: + extensions: [] + pipelines: {} + telemetry: + logs: + development: false + disable_caller: false + disable_stacktrace: false + encoding: "" + error_output_paths: [] + initial_fields: {} + level: info + output_paths: [] + processors: [] + sampling: null + metrics: + address: "" + level: Basic + readers: [] + resource: {} + traces: + level: Basic + processors: [] + propagators: [] diff --git a/pkg/otelcgen/testdata/receivers_otlp_only.yaml b/pkg/otelcgen/testdata/receivers_otlp_only.yaml new file mode 100644 index 0000000000..0b9b0cb208 --- /dev/null +++ b/pkg/otelcgen/testdata/receivers_otlp_only.yaml @@ -0,0 +1,41 @@ +connectors: {} +exporters: {} +extensions: {} +processors: {} +receivers: + otlp: + protocols: + grpc: + endpoint: test:4317 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key + http: + endpoint: test:4318 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key +service: + extensions: [] + pipelines: {} + telemetry: + logs: + development: false + disable_caller: false + disable_stacktrace: false + encoding: "" + error_output_paths: [] + initial_fields: {} + level: info + output_paths: [] + processors: [] + sampling: null + metrics: + address: "" + level: Basic + readers: [] + resource: {} + traces: + level: Basic + processors: [] + propagators: [] diff --git a/pkg/otelcgen/testdata/receivers_statsd.yaml b/pkg/otelcgen/testdata/receivers_statsd.yaml new file mode 100644 index 0000000000..05579ee114 --- /dev/null +++ b/pkg/otelcgen/testdata/receivers_statsd.yaml @@ -0,0 +1,44 @@ +connectors: {} +exporters: {} +extensions: {} +processors: {} +receivers: + statsd: + endpoint: test:8125 + timer_histogram_mapping: + - histogram: + max_size: 10 + observer_type: histogram + statsd_type: histogram + - histogram: + max_size: 100 + observer_type: histogram + statsd_type: timing + - histogram: + max_size: 100 + observer_type: histogram + statsd_type: distribution +service: + extensions: [] + pipelines: {} + telemetry: + logs: + development: false + disable_caller: false + disable_stacktrace: false + encoding: "" + error_output_paths: [] + initial_fields: {} + level: info + output_paths: [] + processors: [] + sampling: null + metrics: + address: "" + level: Basic + readers: [] + resource: {} + traces: + level: Basic + processors: [] + propagators: [] diff --git a/pkg/otelcgen/testdata/receivers_zipkin_only.yaml b/pkg/otelcgen/testdata/receivers_zipkin_only.yaml new file mode 100644 index 0000000000..d893ba808c --- /dev/null +++ b/pkg/otelcgen/testdata/receivers_zipkin_only.yaml @@ -0,0 +1,34 @@ +connectors: {} +exporters: {} +extensions: {} +processors: {} +receivers: + zipkin: + endpoint: test:9411 + tls: + cert_file: /run/opensignals/tls/tls.crt + key_file: /run/opensignals/tls/tls.key +service: + extensions: [] + pipelines: {} + telemetry: + logs: + development: false + disable_caller: false + disable_stacktrace: false + encoding: "" + error_output_paths: [] + initial_fields: {} + level: info + output_paths: [] + processors: [] + sampling: null + metrics: + address: "" + level: Basic + readers: [] + resource: {} + traces: + level: Basic + processors: [] + propagators: [] diff --git a/pkg/otelcgen/testdata/services_only.yaml b/pkg/otelcgen/testdata/services_only.yaml new file mode 100644 index 0000000000..d6676ee57d --- /dev/null +++ b/pkg/otelcgen/testdata/services_only.yaml @@ -0,0 +1,69 @@ +connectors: {} +exporters: {} +extensions: {} +processors: {} +receivers: {} +service: + extensions: + - health_check + pipelines: + logs: + exporters: + - otlphttp + - debug + receivers: + - otlp + - jaeger + - zipkin + processors: + - memory_limiter + - k8sattributes + - transform + - batch/logs + metrics: + exporters: + - otlphttp + - debug + receivers: + - otlp + - jaeger + - zipkin + processors: + - memory_limiter + - k8sattributes + - transform + - batch/metrics + traces: + exporters: + - otlphttp + - debug + receivers: + - otlp + - jaeger + - zipkin + processors: + - memory_limiter + - k8sattributes + - transform + - batch/traces + telemetry: + logs: + development: false + disable_caller: false + disable_stacktrace: false + encoding: "" + error_output_paths: [ ] + initial_fields: { } + level: info + output_paths: [ ] + processors: [ ] + sampling: null + metrics: + address: "" + level: Basic + readers: [ ] + resource: { } + traces: + level: Basic + processors: [ ] + propagators: [ ] From 3334923dc07cce045845c549173e2f977bc193c2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:01:51 +0000 Subject: [PATCH 195/426] chore(deps): update golangci/golangci-lint-action action to v6.3.2 (main) (#4439) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 43675280c2..20d6a324d9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,7 +86,7 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint - uses: golangci/golangci-lint-action@2e788936b09dd82dc280e845628a40d2ba6b204c # v6.3.1 + uses: golangci/golangci-lint-action@051d91933864810ecd5e2ea2cfd98f6a5bca5347 # v6.3.2 with: # renovate depName=github.com/golangci/golangci-lint version: v1.63.4 From 89609660a3da0922bffa1c63e5a9277a39817629 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:07:34 +0000 Subject: [PATCH 196/426] fix(deps): update module istio.io/api to v1.24.3 (main) (#4440) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ba0fcc0365..780e6c03ce 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( golang.org/x/sys v0.30.0 google.golang.org/grpc v1.70.0 gopkg.in/yaml.v3 v3.0.1 - istio.io/api v1.24.2 + istio.io/api v1.24.3 istio.io/client-go v1.24.2 k8s.io/api v0.32.1 k8s.io/apiextensions-apiserver v0.32.1 diff --git a/go.sum b/go.sum index 7b94a15509..f17d28f726 100644 --- a/go.sum +++ b/go.sum @@ -420,8 +420,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -istio.io/api v1.24.2 h1:jYjcN6Iq0RPtQj/3KMFsybxmfqmjGN/dxhL7FGJEdIM= -istio.io/api v1.24.2/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= +istio.io/api v1.24.3 h1:iwWWPM0uEQ+oxRHvIWoB8MQ4bjF3dRQj+M5IDVczg0M= +istio.io/api v1.24.3/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= istio.io/client-go v1.24.2 h1:JTTfBV6dv+AAW+AfccyrdX4T1f9CpsXd1Yzo1s/IYAI= istio.io/client-go v1.24.2/go.mod h1:dgZ9EmJzh1EECzf6nQhwNL4R6RvlyeH/RXeNeNp/MRg= k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc= From 3fbc28140d7123d8db5417907694446afa682cc8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 14:51:04 +0000 Subject: [PATCH 197/426] fix(deps): update module istio.io/client-go to v1.24.3 (main) (#4441) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 780e6c03ce..8600cb4955 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( google.golang.org/grpc v1.70.0 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.3 - istio.io/client-go v1.24.2 + istio.io/client-go v1.24.3 k8s.io/api v0.32.1 k8s.io/apiextensions-apiserver v0.32.1 k8s.io/apimachinery v0.32.1 diff --git a/go.sum b/go.sum index f17d28f726..3daf57f043 100644 --- a/go.sum +++ b/go.sum @@ -422,8 +422,8 @@ gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= istio.io/api v1.24.3 h1:iwWWPM0uEQ+oxRHvIWoB8MQ4bjF3dRQj+M5IDVczg0M= istio.io/api v1.24.3/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= -istio.io/client-go v1.24.2 h1:JTTfBV6dv+AAW+AfccyrdX4T1f9CpsXd1Yzo1s/IYAI= -istio.io/client-go v1.24.2/go.mod h1:dgZ9EmJzh1EECzf6nQhwNL4R6RvlyeH/RXeNeNp/MRg= +istio.io/client-go v1.24.3 h1:TB8IcM3yyMCDzKRJo0YfFOUGNQmkhwH/JE/Yr3lzVAk= +istio.io/client-go v1.24.3/go.mod h1:zSyw/c4luKQKosFIHQaWAQOA0c3bODu4SahQCAMlKA4= k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc= k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k= k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw= From 671a7e5ba80ab9c91e7c97867a28d7e4da3f5e30 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 16:33:38 +0000 Subject: [PATCH 198/426] chore(deps): update aws-actions/configure-aws-credentials action to v4.1.0 (main) (#4442) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6965481544..9b91e28ee8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -93,7 +93,7 @@ jobs: password: ${{ secrets[matrix.password] }} - name: Configure aws credentials if: ${{ matrix.registry == 'amazon-ecr' }} - uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 + uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 with: role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} aws-region: us-east-1 @@ -161,7 +161,7 @@ jobs: password: ${{ secrets[matrix.password] }} - name: Configure aws credentials if: ${{ matrix.registry == 'amazon-ecr' }} - uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 + uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 with: role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} aws-region: us-east-1 @@ -221,7 +221,7 @@ jobs: password: ${{ secrets[matrix.password] }} - name: Configure aws credentials if: ${{ matrix.registry == 'amazon-ecr' }} - uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 + uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 with: role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} aws-region: us-east-1 @@ -333,7 +333,7 @@ jobs: cosign-private-key: ${{ secrets.COSIGN_PRIVATE_KEY }} cosign-password: ${{ secrets.COSIGN_PASSWORD }} - name: Configure aws credentials - uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 + uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 with: role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} aws-region: us-east-1 From afe825f9724298588f4e3bf4e8de34cc3728d37a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 23:15:37 +0000 Subject: [PATCH 199/426] chore(deps): update module golang.org/x/tools to v0.30.0 (main) (#4443) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index e2613ec20b..8f715f5ad1 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -7,7 +7,7 @@ golang_ci_cmd_version=v1.63.4 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools -golang_tools_version=v0.29.0 +golang_tools_version=v0.30.0 # renovate depName=github.com/vektra/mockery mockery_version=v2.52.1 # renovate depName=github.com/igorshubovych/markdownlint-cli From 23078b787c08998502702f73a76b1ec458465cd6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 02:37:56 +0000 Subject: [PATCH 200/426] chore(deps): update dependency redhat-openshift-ecosystem/openshift-preflight to v1.12.0 (main) (#4450) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/preflight/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/preflight/action.yaml b/.github/actions/preflight/action.yaml index d8cbf1d2d9..d75cdc9b64 100644 --- a/.github/actions/preflight/action.yaml +++ b/.github/actions/preflight/action.yaml @@ -29,7 +29,7 @@ runs: RHCC_APITOKEN: ${{ inputs.pyxis-api-token }} RHCC_PROJECT_ID: ${{ inputs.redhat-project-id }} # renovate depName=redhat-openshift-ecosystem/openshift-preflight - PREFLIGHT_VERSION: 1.11.1 + PREFLIGHT_VERSION: 1.12.0 IMAGE_URI: ${{ inputs.registry }}/${{ inputs.repository }}:${{ inputs.version }} run: | hack/build/ci/preflight.sh "${{ env.PREFLIGHT_VERSION }}" "${{ env.IMAGE_URI}}" "${{ inputs.report-name }}" From a211d78fc7f8cb0a618b08f20e029b5a8af3130a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 07:14:35 +0000 Subject: [PATCH 201/426] fix(deps): update module go.opentelemetry.io/collector/component to v0.119.0 (main) (#4444) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 8600cb4955..d8f7a7a064 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/afero v1.12.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 - go.opentelemetry.io/collector/component v0.118.0 + go.opentelemetry.io/collector/component v0.119.0 go.opentelemetry.io/collector/confmap v1.24.0 go.opentelemetry.io/collector/otelcol v0.118.0 go.opentelemetry.io/collector/pipeline v0.118.0 @@ -108,7 +108,7 @@ require ( go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/collector/component/componentstatus v0.118.0 // indirect go.opentelemetry.io/collector/component/componenttest v0.118.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.118.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.119.0 // indirect go.opentelemetry.io/collector/connector v0.118.0 // indirect go.opentelemetry.io/collector/connector/connectortest v0.118.0 // indirect go.opentelemetry.io/collector/connector/xconnector v0.118.0 // indirect @@ -124,7 +124,7 @@ require ( go.opentelemetry.io/collector/extension/extensiontest v0.118.0 // indirect go.opentelemetry.io/collector/featuregate v1.24.0 // indirect go.opentelemetry.io/collector/internal/fanoutconsumer v0.118.0 // indirect - go.opentelemetry.io/collector/pdata v1.24.0 // indirect + go.opentelemetry.io/collector/pdata v1.25.0 // indirect go.opentelemetry.io/collector/pdata/pprofile v0.118.0 // indirect go.opentelemetry.io/collector/pdata/testdata v0.118.0 // indirect go.opentelemetry.io/collector/pipeline/xpipeline v0.118.0 // indirect @@ -138,7 +138,7 @@ require ( go.opentelemetry.io/contrib/bridges/otelzap v0.6.0 // indirect go.opentelemetry.io/contrib/config v0.10.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.31.0 // indirect - go.opentelemetry.io/otel v1.33.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 // indirect @@ -150,11 +150,11 @@ require ( go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect go.opentelemetry.io/otel/log v0.8.0 // indirect - go.opentelemetry.io/otel/metric v1.33.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/sdk v1.33.0 // indirect go.opentelemetry.io/otel/sdk/log v0.7.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect - go.opentelemetry.io/otel/trace v1.33.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sync v0.10.0 // indirect @@ -165,7 +165,7 @@ require ( gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 3daf57f043..bd1ac88219 100644 --- a/go.sum +++ b/go.sum @@ -208,8 +208,8 @@ go.opentelemetry.io/collector v0.118.0 h1:OBqxppK9Ul6bzEabcHsx11pXwgp05sBpqYxIxi go.opentelemetry.io/collector v0.118.0/go.mod h1:yxfijW5k9dwd9sifTBAEoItE+ahFEtOlyvex1B99uno= go.opentelemetry.io/collector/client v1.24.0 h1:eH7ctqDnRWNH5QVVbAvdYYdkvr8QWLkEm8FUPaaYbWE= go.opentelemetry.io/collector/client v1.24.0/go.mod h1:C/38SYPa0tTL6ikPz/glYz6f3GVzEuT4nlEml6IBDMw= -go.opentelemetry.io/collector/component v0.118.0 h1:sSO/ObxJ+yH77Z4DmT1mlSuxhbgUmY1ztt7xCA1F/8w= -go.opentelemetry.io/collector/component v0.118.0/go.mod h1:LUJ3AL2b+tmFr3hZol3hzKzCMvNdqNq0M5CF3SWdv4M= +go.opentelemetry.io/collector/component v0.119.0 h1:ZVp9myF1Bc4BLa1V4C15Jy/VpqKPPhvbxpe9pP1mPMc= +go.opentelemetry.io/collector/component v0.119.0/go.mod h1:wtuWxFl+Ky9E/5+t2FwHoLyADDiBFFDdx8fN3fEs0n8= go.opentelemetry.io/collector/component/componentstatus v0.118.0 h1:1aCIdUjqz0noKNQr1v04P+lwF89Lkua5U7BhH9IAxkE= go.opentelemetry.io/collector/component/componentstatus v0.118.0/go.mod h1:ynO1Nyj0t1h6x/djIMJy35bhnnWEc2mlQaFgDNUO504= go.opentelemetry.io/collector/component/componenttest v0.118.0 h1:knEHckoiL2fEWSIc0iehg39zP4IXzi9sHa45O+oxKo8= @@ -224,8 +224,8 @@ go.opentelemetry.io/collector/config/configopaque v1.24.0 h1:EPOprMDreZPKyIgT0/e go.opentelemetry.io/collector/config/configopaque v1.24.0/go.mod h1:sW0t0iI/VfRL9VYX7Ik6XzVgPcR+Y5kejTLsYcMyDWs= go.opentelemetry.io/collector/config/configretry v1.24.0 h1:sIPHhNNY2YlHMIJ//63iMxIqlgDeGczId0uUb1njsPM= go.opentelemetry.io/collector/config/configretry v1.24.0/go.mod h1:cleBc9I0DIWpTiiHfu9v83FUaCTqcPXmebpLxjEIqro= -go.opentelemetry.io/collector/config/configtelemetry v0.118.0 h1:UlN46EViG2X42odWtXgWaqY7Y01ZKpsnswSwXTWx5mM= -go.opentelemetry.io/collector/config/configtelemetry v0.118.0/go.mod h1:SlBEwQg0qly75rXZ6W1Ig8jN25KBVBkFIIAUI1GiAAE= +go.opentelemetry.io/collector/config/configtelemetry v0.119.0 h1:gAgMUEVXZKgpASxOrhS55DyA/aYatq0U6gitZI8MLXw= +go.opentelemetry.io/collector/config/configtelemetry v0.119.0/go.mod h1:SlBEwQg0qly75rXZ6W1Ig8jN25KBVBkFIIAUI1GiAAE= go.opentelemetry.io/collector/config/configtls v1.24.0 h1:rOhl8qjIlUVVRHnwQj6/vZe6cuCYImyx7aVDBR35bqI= go.opentelemetry.io/collector/config/configtls v1.24.0/go.mod h1:d0OdfkbuYEMYDBJLSbpH0wPI29lmSiFT3geqh/ygF2k= go.opentelemetry.io/collector/confmap v1.24.0 h1:UUHVhkDCsVw14jPOarug9PDQE2vaB2ELPWMr7ARFBCA= @@ -268,8 +268,8 @@ go.opentelemetry.io/collector/internal/fanoutconsumer v0.118.0 h1:affTj1Qxjbg9dZ go.opentelemetry.io/collector/internal/fanoutconsumer v0.118.0/go.mod h1:9mbE68mYdtTyozr3jTtNMB1RA5F8/dt2aWVYSu6bsQ4= go.opentelemetry.io/collector/otelcol v0.118.0 h1:uSD3wU0sO4vsw5VvWI2yUFLggLdq1BWN/nC1LJXIhMg= go.opentelemetry.io/collector/otelcol v0.118.0/go.mod h1:OdKz/AXj+ewCwXp/acZCBIoMIYiIxeNRNkbqUXvWi+o= -go.opentelemetry.io/collector/pdata v1.24.0 h1:D6j92eAzmAbQgivNBUnt8r9juOl8ugb+ihYynoFZIEg= -go.opentelemetry.io/collector/pdata v1.24.0/go.mod h1:cf3/W9E/uIvPS4MR26SnMFJhraUCattzzM6qusuONuc= +go.opentelemetry.io/collector/pdata v1.25.0 h1:AmgBklQfbfy0lT8qsoJtRuYMZ7ZV3VZvkvhjSDentrg= +go.opentelemetry.io/collector/pdata v1.25.0/go.mod h1:Zs7D4RXOGS7E2faGc/jfWdbmhoiHBxA7QbpuJOioxq8= go.opentelemetry.io/collector/pdata/pprofile v0.118.0 h1:VK/fr65VFOwEhsSGRPj5c3lCv0yIK1Kt0sZxv9WZBb8= go.opentelemetry.io/collector/pdata/pprofile v0.118.0/go.mod h1:eJyP/vBm179EghV3dPSnamGAWQwLyd+4z/3yG54YFoQ= go.opentelemetry.io/collector/pdata/testdata v0.118.0 h1:5N0w1SX9KIRkwvtkrpzQgXy9eGk3vfNG0ds6mhEPMIM= @@ -304,8 +304,8 @@ go.opentelemetry.io/contrib/propagators/b3 v1.31.0 h1:PQPXYscmwbCp76QDvO4hMngF2j go.opentelemetry.io/contrib/propagators/b3 v1.31.0/go.mod h1:jbqfV8wDdqSDrAYxVpXQnpM0XFMq2FtDesblJ7blOwQ= go.opentelemetry.io/contrib/zpages v0.56.0 h1:W7vP6s3juzL5KiHpr41zLNmsJ0QAZudYu8ay0zGAoko= go.opentelemetry.io/contrib/zpages v0.56.0/go.mod h1:IxPRP4TYHw9jLeaEOSDIiA9zmyJNZNO6sbW55iMvSXs= -go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= -go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 h1:mMOmtYie9Fx6TSVzw4W+NTpvoaS1JWWga37oI1a/4qQ= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0/go.mod h1:yy7nDsMMBUkD+jeekJ36ur5f3jJIrmCwUrY67VFhNpA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= @@ -328,16 +328,16 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6Bm go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64= go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= -go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= -go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= go.opentelemetry.io/otel/sdk/log v0.7.0 h1:dXkeI2S0MLc5g0/AwxTZv6EUEjctiH8aG14Am56NTmQ= go.opentelemetry.io/otel/sdk/log v0.7.0/go.mod h1:oIRXpW+WD6M8BuGj5rtS0aRu/86cbDV/dAfNaZBIjYM= go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= -go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= -go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg= go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -406,8 +406,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 349286cb328381486ee099dfe5b7a2b6e3007cc2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 08:20:22 +0000 Subject: [PATCH 202/426] chore(deps): update module github.com/vektra/mockery to v2.52.2 (main) (#4453) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 8f715f5ad1..6d3ee125d2 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.30.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.52.1 +mockery_version=v2.52.2 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest From 3b508d228751045f07f2fc489699102769377c10 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 08:30:00 +0000 Subject: [PATCH 203/426] chore(deps): update module sigs.k8s.io/controller-tools/cmd to v0.17.2 (main) (#4437) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Marcell Sevcsik Co-authored-by: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> --- config/crd/bases/dynatrace.com_dynakubes.yaml | 2 +- config/crd/bases/dynatrace.com_edgeconnects.yaml | 2 +- .../default/templates/Common/crd/dynatrace-operator-crd.yaml | 4 ++-- hack/make/prerequisites.mk | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index 58b94ab4a3..bcc60e4aa5 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.1 + controller-gen.kubebuilder.io/version: v0.17.2 name: dynakubes.dynatrace.com spec: group: dynatrace.com diff --git a/config/crd/bases/dynatrace.com_edgeconnects.yaml b/config/crd/bases/dynatrace.com_edgeconnects.yaml index c13b78df53..83ca131ace 100644 --- a/config/crd/bases/dynatrace.com_edgeconnects.yaml +++ b/config/crd/bases/dynatrace.com_edgeconnects.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.1 + controller-gen.kubebuilder.io/version: v0.17.2 name: edgeconnects.dynatrace.com spec: group: dynatrace.com diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 8c5ea30826..9381971800 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.1 + controller-gen.kubebuilder.io/version: v0.17.2 name: dynakubes.dynatrace.com spec: conversion: @@ -7838,7 +7838,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.1 + controller-gen.kubebuilder.io/version: v0.17.2 name: edgeconnects.dynatrace.com spec: conversion: diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 6d3ee125d2..3e8cf930e0 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -1,7 +1,7 @@ #renovate depName=sigs.k8s.io/kustomize/kustomize/v5 kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd -controller_gen_version=v0.17.1 +controller_gen_version=v0.17.2 # renovate depName=github.com/golangci/golangci-lint golang_ci_cmd_version=v1.63.4 # renovate depName=github.com/daixiang0/gci From 21709000973f8dc838bfb0b1a1869cf210222dd6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 08:47:57 +0000 Subject: [PATCH 204/426] chore(deps): update module github.com/golangci/golangci-lint to v1.64.2 (main) (#4451) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Marcell Sevcsik Co-authored-by: Andrii Soldatenko --- .github/workflows/ci.yaml | 2 +- cmd/certificates/watcher.go | 3 +-- cmd/troubleshoot/image_test.go | 4 +-- hack/make/prerequisites.mk | 2 +- pkg/clients/dynatrace/processmoduleconfig.go | 5 ++-- pkg/clients/dynatrace/send_event.go | 5 ++-- pkg/clients/dynatrace/settings.go | 16 +++++------ pkg/clients/dynatrace/settings_enrichment.go | 5 ++-- pkg/clients/dynatrace/settings_kubernetes.go | 7 +++-- .../dynatrace/settings_logmonitoring.go | 8 +++--- pkg/clients/dynatrace/token.go | 5 ++-- .../edgeconnect/environment_settings.go | 27 +++++++++---------- pkg/controllers/certificates/certs.go | 12 ++++----- pkg/controllers/csi/driver/server.go | 7 ++--- .../internal/statefulset/reconciler_test.go | 3 ++- .../dynakube/apimonitoring/reconciler_test.go | 7 +++-- .../activegate/reconciler_test.go | 4 +-- .../codemodule/installer/image/unpack.go | 3 +-- .../codemodule/installer/zip/gzip.go | 3 +-- pkg/injection/codemodule/installer/zip/zip.go | 3 +-- pkg/injection/startup/run_test.go | 7 ++--- pkg/otelcgen/receivers.go | 5 ++-- pkg/version/semantic.go | 2 +- pkg/webhook/mutation/pod/webhook_test.go | 4 +-- 24 files changed, 70 insertions(+), 79 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 20d6a324d9..5d6bde26ce 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -89,7 +89,7 @@ jobs: uses: golangci/golangci-lint-action@051d91933864810ecd5e2ea2cfd98f6a5bca5347 # v6.3.2 with: # renovate depName=github.com/golangci/golangci-lint - version: v1.63.4 + version: v1.64.2 args: --build-tags e2e --timeout 300s --out-${NO_FUTURE}format colored-line-number - name: Run deadcode id: deadcode diff --git a/cmd/certificates/watcher.go b/cmd/certificates/watcher.go index 21f6c5a772..894075bd38 100644 --- a/cmd/certificates/watcher.go +++ b/cmd/certificates/watcher.go @@ -3,7 +3,6 @@ package certificates import ( "bytes" "context" - "fmt" "os" "path/filepath" "time" @@ -77,7 +76,7 @@ func (watcher *CertificateWatcher) updateCertificatesFromSecret() (bool, error) if _, err = watcher.fs.Stat(watcher.certificateDirectory); os.IsNotExist(err) { err = watcher.fs.MkdirAll(watcher.certificateDirectory, permDirUser) if err != nil { - return false, fmt.Errorf("could not create cert directory: %w", err) + return false, errors.WithMessage(err, "could not create cert directory") } } diff --git a/cmd/troubleshoot/image_test.go b/cmd/troubleshoot/image_test.go index 6331e282c4..28ceb6d567 100644 --- a/cmd/troubleshoot/image_test.go +++ b/cmd/troubleshoot/image_test.go @@ -3,7 +3,6 @@ package troubleshoot import ( "context" "encoding/json" - "fmt" "net/http" "net/http/httptest" "net/url" @@ -17,6 +16,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dtpullsecret" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/Dynatrace/dynatrace-operator/pkg/oci/dockerkeychain" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -366,7 +366,7 @@ func TestImagePullablePullSecret(t *testing.T) { func getPullSecretToken(pullSecret *corev1.Secret) (string, error) { secretBytes, hasPullSecret := pullSecret.Data[dtpullsecret.DockerConfigJson] if !hasPullSecret { - return "", fmt.Errorf("token .dockerconfigjson does not exist in secret '%s'", pullSecret.Name) + return "", errors.Errorf("token .dockerconfigjson does not exist in secret '%s'", pullSecret.Name) } secretStr := string(secretBytes) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 3e8cf930e0..487776440c 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -3,7 +3,7 @@ kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.2 # renovate depName=github.com/golangci/golangci-lint -golang_ci_cmd_version=v1.63.4 +golang_ci_cmd_version=v1.64.2 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools diff --git a/pkg/clients/dynatrace/processmoduleconfig.go b/pkg/clients/dynatrace/processmoduleconfig.go index 5ff169bcc7..060c900a1c 100644 --- a/pkg/clients/dynatrace/processmoduleconfig.go +++ b/pkg/clients/dynatrace/processmoduleconfig.go @@ -3,7 +3,6 @@ package dynatrace import ( "context" "encoding/json" - "fmt" "net/http" "strconv" @@ -163,7 +162,7 @@ func (dtc *dynatraceClient) GetProcessModuleConfig(ctx context.Context, prevRevi } if err != nil { - return nil, fmt.Errorf("error while requesting process module config: %w", err) + return nil, errors.WithMessage(err, "error while requesting process module config") } defer utils.CloseBodyAfterRequest(resp) @@ -179,7 +178,7 @@ func (dtc *dynatraceClient) GetProcessModuleConfig(ctx context.Context, prevRevi func (dtc *dynatraceClient) createProcessModuleConfigRequest(ctx context.Context, prevRevision uint) (*http.Request, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, dtc.getProcessModuleConfigUrl(), nil) if err != nil { - return nil, fmt.Errorf("error initializing http request: %w", err) + return nil, errors.WithMessage(err, "error initializing http request") } query := req.URL.Query() diff --git a/pkg/clients/dynatrace/send_event.go b/pkg/clients/dynatrace/send_event.go index 79ffe6d1b9..2db0d54d10 100644 --- a/pkg/clients/dynatrace/send_event.go +++ b/pkg/clients/dynatrace/send_event.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "net/http" "github.com/Dynatrace/dynatrace-operator/pkg/clients/utils" @@ -45,7 +44,7 @@ func (dtc *dynatraceClient) SendEvent(ctx context.Context, eventData *EventData) req, err := http.NewRequestWithContext(ctx, http.MethodPost, dtc.getEventsUrl(), bytes.NewBuffer(jsonStr)) if err != nil { - return fmt.Errorf("error initializing http request: %w", err) + return errors.WithMessage(err, "error initializing http request") } req.Header.Add("Content-Type", "application/json") @@ -53,7 +52,7 @@ func (dtc *dynatraceClient) SendEvent(ctx context.Context, eventData *EventData) response, err := dtc.httpClient.Do(req) if err != nil { - return fmt.Errorf("error making post request to dynatrace api: %w", err) + return errors.WithMessage(err, "error making post request to dynatrace api") } defer utils.CloseBodyAfterRequest(response) diff --git a/pkg/clients/dynatrace/settings.go b/pkg/clients/dynatrace/settings.go index 79242b1cbd..6c1b010dda 100644 --- a/pkg/clients/dynatrace/settings.go +++ b/pkg/clients/dynatrace/settings.go @@ -83,7 +83,7 @@ func (dtc *dynatraceClient) GetMonitoredEntitiesForKubeSystemUUID(ctx context.Co err = dtc.unmarshalToJson(res, &resDataJson) if err != nil { - return nil, fmt.Errorf("error parsing response body: %w", err) + return nil, errors.WithMessage(err, "error parsing response body") } return resDataJson.Entities, nil @@ -117,7 +117,7 @@ func (dtc *dynatraceClient) GetSettingsForMonitoredEntity(ctx context.Context, m err = dtc.unmarshalToJson(res, &resDataJson) if err != nil { - return GetSettingsResponse{}, fmt.Errorf("error parsing response body: %w", err) + return GetSettingsResponse{}, errors.WithMessage(err, "error parsing response body") } return resDataJson, nil @@ -151,7 +151,7 @@ func (dtc *dynatraceClient) GetSettingsForLogModule(ctx context.Context, monitor err = dtc.unmarshalToJson(res, &resDataJson) if err != nil { - return GetLogMonSettingsResponse{}, fmt.Errorf("error parsing response body: %w", err) + return GetLogMonSettingsResponse{}, errors.WithMessage(err, "error parsing response body") } return resDataJson, nil @@ -160,12 +160,12 @@ func (dtc *dynatraceClient) GetSettingsForLogModule(ctx context.Context, monitor func (dtc *dynatraceClient) unmarshalToJson(res *http.Response, resDataJson any) error { resData, err := dtc.getServerResponseData(res) if err != nil { - return fmt.Errorf("error reading response body: %w", err) + return errors.WithMessage(err, "error reading response body") } err = json.Unmarshal(resData, resDataJson) if err != nil { - return fmt.Errorf("error parsing response body: %w", err) + return errors.WithMessage(err, "error parsing response body") } return nil @@ -175,14 +175,14 @@ func handleErrorArrayResponseFromAPI(response []byte, statusCode int) error { if statusCode == http.StatusForbidden || statusCode == http.StatusUnauthorized { var se serverErrorResponse if err := json.Unmarshal(response, &se); err != nil { - return fmt.Errorf("response error: %d, can't unmarshal json response", statusCode) + return errors.Errorf("response error: %d, can't unmarshal json response", statusCode) } - return fmt.Errorf("response error: %d, %s", statusCode, se.ErrorMessage.Message) + return errors.Errorf("response error: %d, %s", statusCode, se.ErrorMessage.Message) } else { var se []serverErrorResponse if err := json.Unmarshal(response, &se); err != nil { - return fmt.Errorf("response error: %d, can't unmarshal json response", statusCode) + return errors.Errorf("response error: %d, can't unmarshal json response", statusCode) } var sb strings.Builder diff --git a/pkg/clients/dynatrace/settings_enrichment.go b/pkg/clients/dynatrace/settings_enrichment.go index 6b223aca0e..d89f914d6a 100644 --- a/pkg/clients/dynatrace/settings_enrichment.go +++ b/pkg/clients/dynatrace/settings_enrichment.go @@ -2,13 +2,12 @@ package dynatrace import ( "context" - "errors" - "fmt" "net/http" "strings" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/clients/utils" + "github.com/pkg/errors" ) const ( @@ -72,7 +71,7 @@ func (dtc *dynatraceClient) GetRulesSettings(ctx context.Context, kubeSystemUUID return GetRulesSettingsResponse{}, nil } - return GetRulesSettingsResponse{}, errors.New(fmt.Errorf("error parsing response body: %w", err).Error()) + return GetRulesSettingsResponse{}, errors.WithMessage(err, "error parsing response body") } return resDataJson, nil diff --git a/pkg/clients/dynatrace/settings_kubernetes.go b/pkg/clients/dynatrace/settings_kubernetes.go index f60745625e..59b6af2a25 100644 --- a/pkg/clients/dynatrace/settings_kubernetes.go +++ b/pkg/clients/dynatrace/settings_kubernetes.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "net/http" "strconv" @@ -67,12 +66,12 @@ func (dtc *dynatraceClient) performCreateOrUpdateKubernetesSetting(ctx context.C defer utils.CloseBodyAfterRequest(res) if err != nil { - return "", fmt.Errorf("error making post request to dynatrace api: %w", err) + return "", errors.WithMessage(err, "error making post request to dynatrace api") } resData, err := io.ReadAll(res.Body) if err != nil { - return "", fmt.Errorf("error reading response: %w", err) + return "", errors.WithMessage(err, "error reading response") } if res.StatusCode != http.StatusOK && @@ -88,7 +87,7 @@ func (dtc *dynatraceClient) performCreateOrUpdateKubernetesSetting(ctx context.C } if len(resDataJson) != 1 { - return "", fmt.Errorf("response is not containing exactly one entry %s", resData) + return "", errors.Errorf("response is not containing exactly one entry %s", resData) } return resDataJson[0].ObjectId, nil diff --git a/pkg/clients/dynatrace/settings_logmonitoring.go b/pkg/clients/dynatrace/settings_logmonitoring.go index bf6761c702..ebd32f9efa 100644 --- a/pkg/clients/dynatrace/settings_logmonitoring.go +++ b/pkg/clients/dynatrace/settings_logmonitoring.go @@ -4,12 +4,12 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "net/http" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/clients/utils" + "github.com/pkg/errors" ) type IngestRuleMatchers struct { @@ -57,12 +57,12 @@ func (dtc *dynatraceClient) performCreateLogMonSetting(ctx context.Context, body defer utils.CloseBodyAfterRequest(res) if err != nil { - return "", fmt.Errorf("error making post request to dynatrace api: %w", err) + return "", errors.WithMessage(err, "error making post request to dynatrace api") } resData, err := io.ReadAll(res.Body) if err != nil { - return "", fmt.Errorf("error reading response: %w", err) + return "", errors.WithMessage(err, "error reading response") } if res.StatusCode != http.StatusOK && @@ -78,7 +78,7 @@ func (dtc *dynatraceClient) performCreateLogMonSetting(ctx context.Context, body } if len(resDataJson) != 1 { - return "", fmt.Errorf("response is not containing exactly one entry %s", resData) + return "", errors.Errorf("response is not containing exactly one entry %s", resData) } return resDataJson[0].ObjectId, nil diff --git a/pkg/clients/dynatrace/token.go b/pkg/clients/dynatrace/token.go index 69a8202739..ace526a29a 100644 --- a/pkg/clients/dynatrace/token.go +++ b/pkg/clients/dynatrace/token.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "net/http" "github.com/Dynatrace/dynatrace-operator/pkg/clients/utils" @@ -39,7 +38,7 @@ func (dtc *dynatraceClient) GetTokenScopes(ctx context.Context, token string) (T req, err := http.NewRequestWithContext(ctx, http.MethodPost, dtc.getTokensLookupUrl(), bytes.NewBuffer(jsonStr)) if err != nil { - return nil, fmt.Errorf("error initializing http request: %w", err) + return nil, errors.WithMessage(err, "error initializing http request") } req.Header.Add("Content-Type", "application/json") @@ -47,7 +46,7 @@ func (dtc *dynatraceClient) GetTokenScopes(ctx context.Context, token string) (T resp, err := dtc.httpClient.Do(req) if err != nil { - return nil, fmt.Errorf("error making post request to dynatrace api: %w", err) + return nil, errors.WithMessage(err, "error making post request to dynatrace api") } defer utils.CloseBodyAfterRequest(resp) diff --git a/pkg/clients/edgeconnect/environment_settings.go b/pkg/clients/edgeconnect/environment_settings.go index 25bb2bd019..6b9670bd7c 100644 --- a/pkg/clients/edgeconnect/environment_settings.go +++ b/pkg/clients/edgeconnect/environment_settings.go @@ -3,7 +3,6 @@ package edgeconnect import ( "bytes" "encoding/json" - "fmt" "net/http" "github.com/Dynatrace/dynatrace-operator/pkg/clients/utils" @@ -40,7 +39,7 @@ func (c *client) GetConnectionSettings() ([]EnvironmentSetting, error) { req, err := http.NewRequestWithContext(c.ctx, http.MethodGet, settingsObjectsUrl, nil) if err != nil { - return nil, fmt.Errorf("error initializing http request: %w", err) + return nil, errors.WithMessage(err, "error initializing http request") } q := req.URL.Query() @@ -53,19 +52,19 @@ func (c *client) GetConnectionSettings() ([]EnvironmentSetting, error) { defer utils.CloseBodyAfterRequest(response) if err != nil { - return nil, fmt.Errorf("error making post request to dynatrace api: %w", err) + return nil, errors.WithMessage(err, "error making post request to dynatrace api") } responseData, err := c.getSettingsApiResponseData(response) if err != nil { - return nil, fmt.Errorf("error getting server response data: %w", err) + return nil, errors.WithMessage(err, "error getting server response data") } var resDataJson EnvironmentSettingsResponse err = json.Unmarshal(responseData, &resDataJson) if err != nil { - return nil, fmt.Errorf("error parsing response body: %w", err) + return nil, errors.WithMessage(err, "error parsing response body") } return resDataJson.Items, nil @@ -79,7 +78,7 @@ func (c *client) CreateConnectionSetting(es EnvironmentSetting) error { req, err := http.NewRequestWithContext(c.ctx, http.MethodPost, c.getSettingsObjectsUrl(), bytes.NewBuffer(jsonStr)) if err != nil { - return fmt.Errorf("error initializing http request: %w", err) + return errors.WithMessage(err, "error initializing http request") } req.Header.Add("Content-Type", "application/json") @@ -89,13 +88,13 @@ func (c *client) CreateConnectionSetting(es EnvironmentSetting) error { defer utils.CloseBodyAfterRequest(response) if err != nil { - return fmt.Errorf("error making post request to dynatrace api: %w", err) + return errors.WithMessage(err, "error making post request to dynatrace api") } _, err = c.getSettingsApiResponseData(response) if err != nil { - return fmt.Errorf("error reading response data: %w", err) + return errors.WithMessage(err, "error reading response data") } return nil @@ -109,14 +108,14 @@ func (c *client) UpdateConnectionSetting(es EnvironmentSetting) error { req, err := http.NewRequestWithContext(c.ctx, http.MethodPut, c.getSettingsObjectsIdUrl(*es.ObjectId), bytes.NewBuffer(jsonStr)) if err != nil { - return fmt.Errorf("error initializing http request: %w", err) + return errors.WithMessage(err, "error initializing http request") } req.Header.Add("Content-Type", "application/json") response, err := c.httpClient.Do(req) if err != nil { - return fmt.Errorf("error making post request to dynatrace api: %w", err) + return errors.WithMessage(err, "error making post request to dynatrace api") } defer utils.CloseBodyAfterRequest(response) @@ -124,7 +123,7 @@ func (c *client) UpdateConnectionSetting(es EnvironmentSetting) error { _, err = c.getSettingsApiResponseData(response) if err != nil { - return fmt.Errorf("error reading response data: %w", err) + return errors.WithMessage(err, "error reading response data") } return nil @@ -133,7 +132,7 @@ func (c *client) UpdateConnectionSetting(es EnvironmentSetting) error { func (c *client) DeleteConnectionSetting(objectId string) error { req, err := http.NewRequestWithContext(c.ctx, http.MethodDelete, c.getSettingsObjectsIdUrl(objectId), nil) if err != nil { - return fmt.Errorf("error initializing http request: %w", err) + return errors.WithMessage(err, "error initializing http request") } response, err := c.httpClient.Do(req) @@ -141,13 +140,13 @@ func (c *client) DeleteConnectionSetting(objectId string) error { defer utils.CloseBodyAfterRequest(response) if err != nil { - return fmt.Errorf("error making post request to dynatrace api: %w", err) + return errors.WithMessage(err, "error making post request to dynatrace api") } _, err = c.getSettingsApiResponseData(response) if err != nil { - return fmt.Errorf("error reading response data: %w", err) + return errors.WithMessage(err, "error reading response data") } return nil diff --git a/pkg/controllers/certificates/certs.go b/pkg/controllers/certificates/certs.go index b641155c9b..2911e10a8a 100644 --- a/pkg/controllers/certificates/certs.go +++ b/pkg/controllers/certificates/certs.go @@ -7,11 +7,11 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/pem" - "fmt" "math/big" "time" "github.com/Dynatrace/dynatrace-operator/pkg/util/certificates" + "github.com/pkg/errors" ) const intSerialNumberLimit = 128 @@ -136,7 +136,7 @@ func (cs *Certs) generateRootCerts(domain string, now time.Time) error { // Generate CA root certificate serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { - return fmt.Errorf("failed to generate serial number for root certificate: %w", err) + return errors.WithMessage(err, "failed to generate serial number for root certificate") } cs.rootPublicCert = &x509.Certificate{ @@ -166,7 +166,7 @@ func (cs *Certs) generateRootCerts(domain string, now time.Time) error { cs.rootPrivateKey.Public(), cs.rootPrivateKey) if err != nil { - return fmt.Errorf("failed to generate root certificate: %w", err) + return errors.WithMessage(err, "failed to generate root certificate") } cs.Data[RootCertOld] = cs.Data[RootCert] @@ -189,7 +189,7 @@ func (cs *Certs) generateServerCerts(domain string, now time.Time) error { // Generate server certificate serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { - return fmt.Errorf("failed to generate serial number for server certificate: %w", err) + return errors.WithMessage(err, "failed to generate serial number for server certificate") } tpl := &x509.Certificate{ @@ -215,7 +215,7 @@ func (cs *Certs) generateServerCerts(domain string, now time.Time) error { serverPublicCertDER, err := x509.CreateCertificate(rand.Reader, tpl, cs.rootPublicCert, privateKey.Public(), cs.rootPrivateKey) if err != nil { - return fmt.Errorf("failed to generate server certificate: %w", err) + return errors.WithMessage(err, "failed to generate server certificate") } cs.Data[ServerCert] = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: serverPublicCertDER}) @@ -228,7 +228,7 @@ func (cs *Certs) generateServerCerts(domain string, now time.Time) error { func (cs *Certs) generatePrivateKey(dataKey string) (*ecdsa.PrivateKey, error) { privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { - return nil, fmt.Errorf("failed to generate server private key: %w", err) + return nil, errors.WithMessage(err, "failed to generate server private key") } x509Encoded, err := x509.MarshalECPrivateKey(privateKey) diff --git a/pkg/controllers/csi/driver/server.go b/pkg/controllers/csi/driver/server.go index a43287a852..9666017798 100644 --- a/pkg/controllers/csi/driver/server.go +++ b/pkg/controllers/csi/driver/server.go @@ -34,6 +34,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/Dynatrace/dynatrace-operator/pkg/version" "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/pkg/errors" "github.com/spf13/afero" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -78,14 +79,14 @@ func (srv *Server) Start(ctx context.Context) error { endpoint, err := url.Parse(srv.opts.Endpoint) if err != nil { - return fmt.Errorf("failed to parse endpoint '%s': %w", srv.opts.Endpoint, err) + return errors.WithMessage(err, fmt.Sprintf("failed to parse endpoint '%s'", srv.opts.Endpoint)) } addr := endpoint.Host + endpoint.Path if endpoint.Scheme == "unix" { if err := srv.fs.Remove(addr); err != nil && !os.IsNotExist(err) { - return fmt.Errorf("failed to remove old endpoint on '%s': %w", addr, err) + return errors.WithMessage(err, fmt.Sprintf("failed to remove old endpoint on '%s'", addr)) } } @@ -98,7 +99,7 @@ func (srv *Server) Start(ctx context.Context) error { listener, err := net.Listen(endpoint.Scheme, addr) if err != nil { - return fmt.Errorf("failed to start server: %w", err) + return errors.WithMessage(err, "failed to start server") } maxGrpcRequests, err := strconv.Atoi(os.Getenv("GRPC_MAX_REQUESTS_LIMIT")) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler_test.go index 7958d6a965..c128f5558e 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler_test.go @@ -2,6 +2,7 @@ package statefulset import ( "context" + "errors" "fmt" "testing" @@ -141,7 +142,7 @@ func TestReconcile(t *testing.T) { r := createDefaultReconciler(t) fakeClient := dynafake.NewClientWithInterceptors(interceptor.Funcs{ Get: func(ctx context.Context, client client.WithWatch, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { - return fmt.Errorf("BOOM") + return errors.New("BOOM") }, }) r.apiReader = fakeClient diff --git a/pkg/controllers/dynakube/apimonitoring/reconciler_test.go b/pkg/controllers/dynakube/apimonitoring/reconciler_test.go index b07cec8b83..6bc542572b 100644 --- a/pkg/controllers/dynakube/apimonitoring/reconciler_test.go +++ b/pkg/controllers/dynakube/apimonitoring/reconciler_test.go @@ -2,7 +2,6 @@ package apimonitoring import ( "context" - "fmt" "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" @@ -73,11 +72,11 @@ func createReadOnlyReconciler(t *testing.T, dk *dynakube.DynaKube, monitoredEnti mock.AnythingOfType("string")). Return(getSettingsResponse, nil) mockClient.On("CreateOrUpdateKubernetesSetting", mock.AnythingOfType("context.backgroundCtx"), testName, testUID, "KUBERNETES_CLUSTER-119C75CCDA94799F"). - Return("", fmt.Errorf("BOOM, readonly only client is used")) + Return("", errors.New("BOOM, readonly only client is used")) mockClient.On("CreateOrUpdateKubernetesSetting", mock.AnythingOfType("context.backgroundCtx"), testName, testUID, "test-MEID"). - Return("", fmt.Errorf("BOOM, readonly only client is used")) + Return("", errors.New("BOOM, readonly only client is used")) mockClient.On("CreateOrUpdateKubernetesAppSetting", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("string")). - Return("", fmt.Errorf("BOOM, readonly only client is used")) + Return("", errors.New("BOOM, readonly only client is used")) for _, call := range mockClient.ExpectedCalls { call.Maybe() diff --git a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go index 3420b9f7dd..cafe0d8637 100644 --- a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go +++ b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go @@ -2,7 +2,6 @@ package activegate import ( "context" - "fmt" "testing" "time" @@ -15,6 +14,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -154,7 +154,7 @@ func TestReconcile(t *testing.T) { dk := getTestDynakube() fakeClient := fake.NewClientWithInterceptors(interceptor.Funcs{ Get: func(ctx context.Context, client client.WithWatch, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { - return fmt.Errorf("BOOM") + return errors.New("BOOM") }, }) diff --git a/pkg/injection/codemodule/installer/image/unpack.go b/pkg/injection/codemodule/installer/image/unpack.go index 337689c654..aed7ac71ea 100644 --- a/pkg/injection/codemodule/installer/image/unpack.go +++ b/pkg/injection/codemodule/installer/image/unpack.go @@ -3,7 +3,6 @@ package image import ( "context" "encoding/base64" - "fmt" "path" "path/filepath" @@ -118,7 +117,7 @@ func (installer *Installer) unpackOciImage(layers []containerv1.Layer, imageCach case types.OCILayerZStd: return errors.New("OCILayerZStd is not implemented") default: - return fmt.Errorf("media type %s is not implemented", mediaType) + return errors.Errorf("media type %s is not implemented", mediaType) } } diff --git a/pkg/injection/codemodule/installer/zip/gzip.go b/pkg/injection/codemodule/installer/zip/gzip.go index 92635574d9..8e8214af70 100644 --- a/pkg/injection/codemodule/installer/zip/gzip.go +++ b/pkg/injection/codemodule/installer/zip/gzip.go @@ -2,7 +2,6 @@ package zip import ( "archive/tar" - "fmt" "io" "os" "path/filepath" @@ -56,7 +55,7 @@ func extractFilesFromGzip(fs afero.Fs, targetDir string, reader *tar.Reader) err // Check for ZipSlip: https://snyk.io/research/zip-slip-vulnerability if !strings.HasPrefix(target, targetDir) { - return fmt.Errorf("illegal file path: %s", target) + return errors.Errorf("illegal file path: %s", target) } err = extract(fs, targetDir, reader, header, target) diff --git a/pkg/injection/codemodule/installer/zip/zip.go b/pkg/injection/codemodule/installer/zip/zip.go index a8e5803fe8..e9219b3530 100644 --- a/pkg/injection/codemodule/installer/zip/zip.go +++ b/pkg/injection/codemodule/installer/zip/zip.go @@ -1,7 +1,6 @@ package zip import ( - "fmt" "io" "os" "path/filepath" @@ -70,7 +69,7 @@ func extractFilesFromZip(fs afero.Fs, targetDir string, reader *zip.Reader) erro // Check for ZipSlip: https://snyk.io/research/zip-slip-vulnerability if !strings.HasPrefix(path, filepath.Clean(targetDir)+string(os.PathSeparator)) { - return fmt.Errorf("illegal file path: %s", path) + return errors.Errorf("illegal file path: %s", path) } mode := file.Mode() diff --git a/pkg/injection/startup/run_test.go b/pkg/injection/startup/run_test.go index b0369d3e5d..7a0c619b99 100644 --- a/pkg/injection/startup/run_test.go +++ b/pkg/injection/startup/run_test.go @@ -3,6 +3,7 @@ package startup import ( "context" "encoding/json" + "errors" "fmt" "os" "path/filepath" @@ -157,7 +158,7 @@ func TestInstallOneAgent(t *testing.T) { runner := createMockedRunner(t) runner.installer.(*installermock.Installer). On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), consts.AgentBinDirMount). - Return(false, fmt.Errorf("BOOM")) + Return(false, errors.New("BOOM")) err := runner.installOneAgent(ctx) @@ -180,7 +181,7 @@ func TestInstallOneAgent(t *testing.T) { runner := createMockedRunner(t) runner.dtclient.(*dtclientmock.Client). On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), uint(0)). - Return(&dtclient.ProcessModuleConfig{}, fmt.Errorf("BOOM")) + Return(&dtclient.ProcessModuleConfig{}, errors.New("BOOM")) runner.installer.(*installermock.Installer). On("InstallAgent", mock.AnythingOfType("context.backgroundCtx"), consts.AgentBinDirMount). Return(true, nil) @@ -296,7 +297,7 @@ func TestGetProcessModuleConfig(t *testing.T) { runner := createMockedRunner(t) runner.dtclient.(*dtclientmock.Client). On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), uint(0)). - Return(&dtclient.ProcessModuleConfig{}, fmt.Errorf("BOOM")) + Return(&dtclient.ProcessModuleConfig{}, errors.New("BOOM")) config, err := runner.getProcessModuleConfig(ctx) require.Error(t, err) diff --git a/pkg/otelcgen/receivers.go b/pkg/otelcgen/receivers.go index d382e0a4b5..2bb33372fe 100644 --- a/pkg/otelcgen/receivers.go +++ b/pkg/otelcgen/receivers.go @@ -1,8 +1,7 @@ package otelcgen import ( - "fmt" - + "github.com/pkg/errors" "go.opentelemetry.io/collector/component" ) @@ -64,7 +63,7 @@ func (c *Config) buildReceivers(protocols []string) (map[component.ID]component. case OtlpProtocol: receivers[OtlpID] = c.buildReceiverComponent(OtlpID) default: - return nil, fmt.Errorf("unknown protocol: %s", p) + return nil, errors.Errorf("unknown protocol: %s", p) } } diff --git a/pkg/version/semantic.go b/pkg/version/semantic.go index f669e429f3..f4b9401c7e 100644 --- a/pkg/version/semantic.go +++ b/pkg/version/semantic.go @@ -47,7 +47,7 @@ func ExtractSemanticVersion(versionString string) (SemanticVersion, error) { version := versionRegex.FindStringSubmatch(versionString) if len(version) < maxStringSubMatch { - return SemanticVersion{}, fmt.Errorf("version malformed: %s", versionString) + return SemanticVersion{}, errors.Errorf("version malformed: %s", versionString) } major, err := strconv.Atoi(version[1]) diff --git a/pkg/webhook/mutation/pod/webhook_test.go b/pkg/webhook/mutation/pod/webhook_test.go index 18765527fb..59fde68d04 100644 --- a/pkg/webhook/mutation/pod/webhook_test.go +++ b/pkg/webhook/mutation/pod/webhook_test.go @@ -3,7 +3,6 @@ package pod import ( "context" "encoding/json" - "fmt" "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" @@ -17,6 +16,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/metadata" oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" webhookmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/webhook" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -413,7 +413,7 @@ func createFailPodMutatorMock(t *testing.T) *webhookmock.PodMutator { mutator := webhookmock.NewPodMutator(t) mutator.On("Enabled", mock.Anything).Return(true).Maybe() mutator.On("Injected", mock.Anything).Return(false).Maybe() - mutator.On("Mutate", mock.Anything, mock.Anything).Return(fmt.Errorf("BOOM")).Maybe() + mutator.On("Mutate", mock.Anything, mock.Anything).Return(errors.New("BOOM")).Maybe() mutator.On("Reinvoke", mock.Anything).Return(false).Maybe() return mutator From 991cacf3446c41c15f33dcb6979cd7fd65aa2911 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Wed, 12 Feb 2025 10:02:35 +0100 Subject: [PATCH 205/426] Improve csi-server port health declaration (#4438) --- config/helm/chart/default/templates/Common/csi/daemonset.yaml | 4 +--- .../helm/chart/default/tests/Common/csi/daemonset_test.yaml | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/config/helm/chart/default/templates/Common/csi/daemonset.yaml b/config/helm/chart/default/templates/Common/csi/daemonset.yaml index a9379b2ebf..858f575a94 100644 --- a/config/helm/chart/default/templates/Common/csi/daemonset.yaml +++ b/config/helm/chart/default/templates/Common/csi/daemonset.yaml @@ -112,7 +112,7 @@ spec: failureThreshold: 5 httpGet: path: /healthz - port: healthz + port: 9808 scheme: HTTP initialDelaySeconds: 15 periodSeconds: 15 @@ -120,8 +120,6 @@ spec: timeoutSeconds: 10 {{- end }} ports: - - containerPort: 9808 - name: healthz - containerPort: 8080 name: metrics resources: diff --git a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml index 3e8a35a649..98bf79d70f 100644 --- a/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/daemonset_test.yaml @@ -185,7 +185,7 @@ tests: failureThreshold: 5 httpGet: path: "/healthz" - port: healthz + port: 9808 scheme: HTTP initialDelaySeconds: 15 periodSeconds: 15 @@ -193,8 +193,6 @@ tests: timeoutSeconds: 10 name: server ports: - - containerPort: 9808 - name: healthz - containerPort: 8080 name: metrics resources: From 1746abafa556f79e2f1d352124a5958c4e4f5616 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 09:26:25 +0000 Subject: [PATCH 206/426] fix(deps): update module go.opentelemetry.io/collector/confmap to v1.25.0 (main) (#4445) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d8f7a7a064..e159dc5e4d 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v0.119.0 - go.opentelemetry.io/collector/confmap v1.24.0 + go.opentelemetry.io/collector/confmap v1.25.0 go.opentelemetry.io/collector/otelcol v0.118.0 go.opentelemetry.io/collector/pipeline v0.118.0 go.opentelemetry.io/collector/service v0.118.0 diff --git a/go.sum b/go.sum index bd1ac88219..18c1831a9e 100644 --- a/go.sum +++ b/go.sum @@ -228,8 +228,8 @@ go.opentelemetry.io/collector/config/configtelemetry v0.119.0 h1:gAgMUEVXZKgpASx go.opentelemetry.io/collector/config/configtelemetry v0.119.0/go.mod h1:SlBEwQg0qly75rXZ6W1Ig8jN25KBVBkFIIAUI1GiAAE= go.opentelemetry.io/collector/config/configtls v1.24.0 h1:rOhl8qjIlUVVRHnwQj6/vZe6cuCYImyx7aVDBR35bqI= go.opentelemetry.io/collector/config/configtls v1.24.0/go.mod h1:d0OdfkbuYEMYDBJLSbpH0wPI29lmSiFT3geqh/ygF2k= -go.opentelemetry.io/collector/confmap v1.24.0 h1:UUHVhkDCsVw14jPOarug9PDQE2vaB2ELPWMr7ARFBCA= -go.opentelemetry.io/collector/confmap v1.24.0/go.mod h1:Rrhs+MWoaP6AswZp+ReQ2VO9dfOfcUjdjiSHBsG+nec= +go.opentelemetry.io/collector/confmap v1.25.0 h1:dLqd6hF4JqcDHl5GWWhc2jXsHs3hkq3KPvU/2Nw5aN4= +go.opentelemetry.io/collector/confmap v1.25.0/go.mod h1:Rrhs+MWoaP6AswZp+ReQ2VO9dfOfcUjdjiSHBsG+nec= go.opentelemetry.io/collector/connector v0.118.0 h1:amay4UriWrtydaAxjQ8/MTTaVYERlZcYLCAGcjoBejw= go.opentelemetry.io/collector/connector v0.118.0/go.mod h1:R6jbMrHZYg21pZ0nsoo4cSHIn7Lrdpi5R3OWcDEQwhE= go.opentelemetry.io/collector/connector/connectortest v0.118.0 h1:hLMSTqtFWveXa3b1qJMEaWuaX3PHx7dfl8G/bsac2fE= From 0af9d09610021eec5b26f7568195403b44092734 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 10:08:08 +0000 Subject: [PATCH 207/426] fix(deps): update module go.opentelemetry.io/collector/otelcol to v0.119.0 (main) (#4446) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 105 +++++++++++------------ go.sum | 262 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 185 insertions(+), 182 deletions(-) diff --git a/go.mod b/go.mod index e159dc5e4d..e3ecef3485 100644 --- a/go.mod +++ b/go.mod @@ -18,9 +18,9 @@ require ( github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v0.119.0 go.opentelemetry.io/collector/confmap v1.25.0 - go.opentelemetry.io/collector/otelcol v0.118.0 - go.opentelemetry.io/collector/pipeline v0.118.0 - go.opentelemetry.io/collector/service v0.118.0 + go.opentelemetry.io/collector/otelcol v0.119.0 + go.opentelemetry.io/collector/pipeline v0.119.0 + go.opentelemetry.io/collector/service v0.119.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.23.0 @@ -69,7 +69,7 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -93,7 +93,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.61.0 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/shirou/gopsutil/v4 v4.24.12 // indirect github.com/sirupsen/logrus v1.9.3 // indirect @@ -106,56 +106,57 @@ require ( github.com/x448/float16 v0.8.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/collector/component/componentstatus v0.118.0 // indirect - go.opentelemetry.io/collector/component/componenttest v0.118.0 // indirect + go.opentelemetry.io/collector/component/componentstatus v0.119.0 // indirect + go.opentelemetry.io/collector/component/componenttest v0.119.0 // indirect go.opentelemetry.io/collector/config/configtelemetry v0.119.0 // indirect - go.opentelemetry.io/collector/connector v0.118.0 // indirect - go.opentelemetry.io/collector/connector/connectortest v0.118.0 // indirect - go.opentelemetry.io/collector/connector/xconnector v0.118.0 // indirect - go.opentelemetry.io/collector/consumer v1.24.0 // indirect - go.opentelemetry.io/collector/consumer/consumererror v0.118.0 // indirect - go.opentelemetry.io/collector/consumer/consumertest v0.118.0 // indirect - go.opentelemetry.io/collector/consumer/xconsumer v0.118.0 // indirect - go.opentelemetry.io/collector/exporter v0.118.0 // indirect - go.opentelemetry.io/collector/exporter/exportertest v0.118.0 // indirect - go.opentelemetry.io/collector/exporter/xexporter v0.118.0 // indirect - go.opentelemetry.io/collector/extension v0.118.0 // indirect - go.opentelemetry.io/collector/extension/extensioncapabilities v0.118.0 // indirect - go.opentelemetry.io/collector/extension/extensiontest v0.118.0 // indirect - go.opentelemetry.io/collector/featuregate v1.24.0 // indirect - go.opentelemetry.io/collector/internal/fanoutconsumer v0.118.0 // indirect + go.opentelemetry.io/collector/connector v0.119.0 // indirect + go.opentelemetry.io/collector/connector/connectortest v0.119.0 // indirect + go.opentelemetry.io/collector/connector/xconnector v0.119.0 // indirect + go.opentelemetry.io/collector/consumer v1.25.0 // indirect + go.opentelemetry.io/collector/consumer/consumererror v0.119.0 // indirect + go.opentelemetry.io/collector/consumer/consumertest v0.119.0 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.119.0 // indirect + go.opentelemetry.io/collector/exporter v0.119.0 // indirect + go.opentelemetry.io/collector/exporter/exportertest v0.119.0 // indirect + go.opentelemetry.io/collector/exporter/xexporter v0.119.0 // indirect + go.opentelemetry.io/collector/extension v0.119.0 // indirect + go.opentelemetry.io/collector/extension/extensioncapabilities v0.119.0 // indirect + go.opentelemetry.io/collector/extension/extensiontest v0.119.0 // indirect + go.opentelemetry.io/collector/featuregate v1.25.0 // indirect + go.opentelemetry.io/collector/internal/fanoutconsumer v0.119.0 // indirect go.opentelemetry.io/collector/pdata v1.25.0 // indirect - go.opentelemetry.io/collector/pdata/pprofile v0.118.0 // indirect - go.opentelemetry.io/collector/pdata/testdata v0.118.0 // indirect - go.opentelemetry.io/collector/pipeline/xpipeline v0.118.0 // indirect - go.opentelemetry.io/collector/processor v0.118.0 // indirect - go.opentelemetry.io/collector/processor/processortest v0.118.0 // indirect - go.opentelemetry.io/collector/processor/xprocessor v0.118.0 // indirect - go.opentelemetry.io/collector/receiver v0.118.0 // indirect - go.opentelemetry.io/collector/receiver/receivertest v0.118.0 // indirect - go.opentelemetry.io/collector/receiver/xreceiver v0.118.0 // indirect - go.opentelemetry.io/collector/semconv v0.118.0 // indirect - go.opentelemetry.io/contrib/bridges/otelzap v0.6.0 // indirect - go.opentelemetry.io/contrib/config v0.10.0 // indirect - go.opentelemetry.io/contrib/propagators/b3 v1.31.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.119.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.119.0 // indirect + go.opentelemetry.io/collector/pipeline/xpipeline v0.119.0 // indirect + go.opentelemetry.io/collector/processor v0.119.0 // indirect + go.opentelemetry.io/collector/processor/processortest v0.119.0 // indirect + go.opentelemetry.io/collector/processor/xprocessor v0.119.0 // indirect + go.opentelemetry.io/collector/receiver v0.119.0 // indirect + go.opentelemetry.io/collector/receiver/receivertest v0.119.0 // indirect + go.opentelemetry.io/collector/receiver/xreceiver v0.119.0 // indirect + go.opentelemetry.io/collector/semconv v0.119.0 // indirect + go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect + go.opentelemetry.io/contrib/config v0.14.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.54.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect - go.opentelemetry.io/otel/log v0.8.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.56.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect + go.opentelemetry.io/otel/log v0.10.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect - go.opentelemetry.io/otel/sdk v1.33.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.7.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.34.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect - go.opentelemetry.io/proto/otlp v1.4.0 // indirect + go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/term v0.28.0 // indirect @@ -163,8 +164,8 @@ require ( golang.org/x/time v0.8.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/protobuf v1.36.4 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 18c1831a9e..86964b7863 100644 --- a/go.sum +++ b/go.sum @@ -82,8 +82,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -157,8 +157,8 @@ github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+ github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= -github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= @@ -204,142 +204,144 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/collector v0.118.0 h1:OBqxppK9Ul6bzEabcHsx11pXwgp05sBpqYxIxiOkyFo= -go.opentelemetry.io/collector v0.118.0/go.mod h1:yxfijW5k9dwd9sifTBAEoItE+ahFEtOlyvex1B99uno= -go.opentelemetry.io/collector/client v1.24.0 h1:eH7ctqDnRWNH5QVVbAvdYYdkvr8QWLkEm8FUPaaYbWE= -go.opentelemetry.io/collector/client v1.24.0/go.mod h1:C/38SYPa0tTL6ikPz/glYz6f3GVzEuT4nlEml6IBDMw= +go.opentelemetry.io/collector v0.119.0 h1:n8ltRLteaUKjyY3E+3JbiaPG4gwL2pjNIcUvXmRA0Ko= +go.opentelemetry.io/collector v0.119.0/go.mod h1:w+qO3hp/mLR2wL4v06MWonGcj4p2/kPSNcU3R7+06p8= +go.opentelemetry.io/collector/client v1.25.0 h1:7IS+b3Xm2ymgmQj9UbnZmVF4jIw6F7tQjJP7lFc+GoM= +go.opentelemetry.io/collector/client v1.25.0/go.mod h1:IPyOnO7K0ztuZOV1i+WXShvq4tpbLp45tTDdIDvlZvM= go.opentelemetry.io/collector/component v0.119.0 h1:ZVp9myF1Bc4BLa1V4C15Jy/VpqKPPhvbxpe9pP1mPMc= go.opentelemetry.io/collector/component v0.119.0/go.mod h1:wtuWxFl+Ky9E/5+t2FwHoLyADDiBFFDdx8fN3fEs0n8= -go.opentelemetry.io/collector/component/componentstatus v0.118.0 h1:1aCIdUjqz0noKNQr1v04P+lwF89Lkua5U7BhH9IAxkE= -go.opentelemetry.io/collector/component/componentstatus v0.118.0/go.mod h1:ynO1Nyj0t1h6x/djIMJy35bhnnWEc2mlQaFgDNUO504= -go.opentelemetry.io/collector/component/componenttest v0.118.0 h1:knEHckoiL2fEWSIc0iehg39zP4IXzi9sHa45O+oxKo8= -go.opentelemetry.io/collector/component/componenttest v0.118.0/go.mod h1:aHc7t7zVwCpbhrWIWY+GMuaMxMCUP8C8P7pJOt8r/vU= -go.opentelemetry.io/collector/config/configauth v0.118.0 h1:uBH/s9kRw/m7VWuibrkCzbXSCVLf9ElKq9NuKb0wAwk= -go.opentelemetry.io/collector/config/configauth v0.118.0/go.mod h1:uAmSGkihIENoIah6mEQ8S/HX4oiFOHZu3EoZLZwi9OI= -go.opentelemetry.io/collector/config/configcompression v1.24.0 h1:jyM6BX7wYcrh+eVSC0FMbWgy/zb9iP58SerOrvisccE= -go.opentelemetry.io/collector/config/configcompression v1.24.0/go.mod h1:LvYG00tbPTv0NOLoZN0wXq1F5thcxvukO8INq7xyfWU= -go.opentelemetry.io/collector/config/confighttp v0.118.0 h1:ey50dfySOCPgUPJ1x8Kq6CmNcv/TpZHt6cYmPhZItj0= -go.opentelemetry.io/collector/config/confighttp v0.118.0/go.mod h1:4frheVFiIfKUHuD/KAPn+u+d+EUx5GlQTNmoI1ftReA= -go.opentelemetry.io/collector/config/configopaque v1.24.0 h1:EPOprMDreZPKyIgT0/eVBvEGQVvq7ncvBCBVnWerj54= -go.opentelemetry.io/collector/config/configopaque v1.24.0/go.mod h1:sW0t0iI/VfRL9VYX7Ik6XzVgPcR+Y5kejTLsYcMyDWs= -go.opentelemetry.io/collector/config/configretry v1.24.0 h1:sIPHhNNY2YlHMIJ//63iMxIqlgDeGczId0uUb1njsPM= -go.opentelemetry.io/collector/config/configretry v1.24.0/go.mod h1:cleBc9I0DIWpTiiHfu9v83FUaCTqcPXmebpLxjEIqro= +go.opentelemetry.io/collector/component/componentstatus v0.119.0 h1:H8isEInGaWhnDfuG1Ax663dlsPgF4aM20sgraM6HmSI= +go.opentelemetry.io/collector/component/componentstatus v0.119.0/go.mod h1:Hr7scHUFPhyT32IkzKq06cdhRH9jMKvnKbDVYRUEnqE= +go.opentelemetry.io/collector/component/componenttest v0.119.0 h1:nVlBmKSu56zO/qCcNgDYCQsRoWAL+NPkrkIPAbapdQM= +go.opentelemetry.io/collector/component/componenttest v0.119.0/go.mod h1:H6KVzLkNhB/deEijLcq91Kjgs9Oshx2ZsFAwaMcuTLs= +go.opentelemetry.io/collector/config/configauth v0.119.0 h1:w/Ln2l6TSgadtRLEZ7mlmOsW/6Q4ITIrjwxR7Tbnfzg= +go.opentelemetry.io/collector/config/configauth v0.119.0/go.mod h1:B3DFUBTSGdwAjxbWtY/tQ+03QwousCMLM9s26+Kb9Xw= +go.opentelemetry.io/collector/config/configcompression v1.25.0 h1:iYeeYiKbTQu9lqWDpszeAc5gRkWBImDrBVe7u5gnoqw= +go.opentelemetry.io/collector/config/configcompression v1.25.0/go.mod h1:LvYG00tbPTv0NOLoZN0wXq1F5thcxvukO8INq7xyfWU= +go.opentelemetry.io/collector/config/confighttp v0.119.0 h1:slt4Msm2D4qdu2Nvy2E+ccgrAS0T64zl6eTuWiiCxGg= +go.opentelemetry.io/collector/config/confighttp v0.119.0/go.mod h1:Tnfo1UP1OZPVfvYriaP187aS3FHfwVXNLjBZ799AUFk= +go.opentelemetry.io/collector/config/configopaque v1.25.0 h1:raFi+CC8Sn4KzKCPhtnnrnkDQ0eFzJCN8xJpQh9d1sU= +go.opentelemetry.io/collector/config/configopaque v1.25.0/go.mod h1:sW0t0iI/VfRL9VYX7Ik6XzVgPcR+Y5kejTLsYcMyDWs= +go.opentelemetry.io/collector/config/configretry v1.25.0 h1:PelzRkTJ9zGxwdJha7pPtvR91GrgL/OzkY/MwyXYRUE= +go.opentelemetry.io/collector/config/configretry v1.25.0/go.mod h1:cleBc9I0DIWpTiiHfu9v83FUaCTqcPXmebpLxjEIqro= go.opentelemetry.io/collector/config/configtelemetry v0.119.0 h1:gAgMUEVXZKgpASxOrhS55DyA/aYatq0U6gitZI8MLXw= go.opentelemetry.io/collector/config/configtelemetry v0.119.0/go.mod h1:SlBEwQg0qly75rXZ6W1Ig8jN25KBVBkFIIAUI1GiAAE= -go.opentelemetry.io/collector/config/configtls v1.24.0 h1:rOhl8qjIlUVVRHnwQj6/vZe6cuCYImyx7aVDBR35bqI= -go.opentelemetry.io/collector/config/configtls v1.24.0/go.mod h1:d0OdfkbuYEMYDBJLSbpH0wPI29lmSiFT3geqh/ygF2k= +go.opentelemetry.io/collector/config/configtls v1.25.0 h1:x915Us8mhYWGB025LBMH8LT9ZPdvg2WKAyCQ7IDUSfw= +go.opentelemetry.io/collector/config/configtls v1.25.0/go.mod h1:jE4WbJE12AltJ3BZU1R0GnYI8D14bTqbTq4yuaTHdms= go.opentelemetry.io/collector/confmap v1.25.0 h1:dLqd6hF4JqcDHl5GWWhc2jXsHs3hkq3KPvU/2Nw5aN4= go.opentelemetry.io/collector/confmap v1.25.0/go.mod h1:Rrhs+MWoaP6AswZp+ReQ2VO9dfOfcUjdjiSHBsG+nec= -go.opentelemetry.io/collector/connector v0.118.0 h1:amay4UriWrtydaAxjQ8/MTTaVYERlZcYLCAGcjoBejw= -go.opentelemetry.io/collector/connector v0.118.0/go.mod h1:R6jbMrHZYg21pZ0nsoo4cSHIn7Lrdpi5R3OWcDEQwhE= -go.opentelemetry.io/collector/connector/connectortest v0.118.0 h1:hLMSTqtFWveXa3b1qJMEaWuaX3PHx7dfl8G/bsac2fE= -go.opentelemetry.io/collector/connector/connectortest v0.118.0/go.mod h1:hm6TNLiQLe65NpENCFsFoiO8fOf3BbN4UF1heUsT73Q= -go.opentelemetry.io/collector/connector/xconnector v0.118.0 h1:0s6rwZmt8va6xd3BEZs7s2QBNFNjLv0kzYi6l44dKqc= -go.opentelemetry.io/collector/connector/xconnector v0.118.0/go.mod h1:12mJPGWo90iZrrpgOkmSd5TkejweL34V/R6AqwqJnMA= -go.opentelemetry.io/collector/consumer v1.24.0 h1:7DeyBm9qdr1EPuCfPjWyChPK16DbVc0wZeSa9LZprFU= -go.opentelemetry.io/collector/consumer v1.24.0/go.mod h1:0G6jvZprIp4dpKMD1ZxCjriiP9GdFvFMObsQEtTk71s= -go.opentelemetry.io/collector/consumer/consumererror v0.118.0 h1:Cx//ZFDa6wUEoRDRYRZ/Rkb52dWNoHj2e9FdlcM9jCA= -go.opentelemetry.io/collector/consumer/consumererror v0.118.0/go.mod h1:2mhnzzLYR5zS2Zz4h9ZnRM8Uogu9qatcfQwGNenhing= -go.opentelemetry.io/collector/consumer/consumertest v0.118.0 h1:8AAS9ejQapP1zqt0+cI6u+AUBheT3X0171N9WtXWsVY= -go.opentelemetry.io/collector/consumer/consumertest v0.118.0/go.mod h1:spRM2wyGr4QZzqMHlLmZnqRCxqXN4Wd0piogC4Qb5PQ= -go.opentelemetry.io/collector/consumer/xconsumer v0.118.0 h1:guWnzzRqgCInjnYlOQ1BPrimppNGIVvnknAjlIbWXuY= -go.opentelemetry.io/collector/consumer/xconsumer v0.118.0/go.mod h1:C5V2d6Ys/Fi6k3tzjBmbdZ9v3J/rZSAMlhx4KVcMIIg= -go.opentelemetry.io/collector/exporter v0.118.0 h1:PE0vF2U+znOB8OVLPWNw40bGCoT/5QquQ8Xbz4i9Rb0= -go.opentelemetry.io/collector/exporter v0.118.0/go.mod h1:5ST3gxT/RzE/vg2bcGDtWJxlQF1ypwk50UpmdK1kUqY= -go.opentelemetry.io/collector/exporter/exportertest v0.118.0 h1:8gWky42BcJsxoaqWbnqCDUjP3Y84hjC6RD/UWHwR7sI= -go.opentelemetry.io/collector/exporter/exportertest v0.118.0/go.mod h1:UbpQBZvznA8YPqqcKlafVIhB6Qa4fPf2+I67MUGyNqo= -go.opentelemetry.io/collector/exporter/xexporter v0.118.0 h1:PZAo1CFhZHfQwtzUNj+Fwcv/21pWHJHTsrIddD096fw= -go.opentelemetry.io/collector/exporter/xexporter v0.118.0/go.mod h1:x4J+qyrRcp4DfWKqK3DLZomFTIUhedsqCQWqq6Gqps4= -go.opentelemetry.io/collector/extension v0.118.0 h1:9o5jLCTRvs0+rtFDx04zTBuB4WFrE0RvtVCPovYV0sA= -go.opentelemetry.io/collector/extension v0.118.0/go.mod h1:BFwB0WOlse6JnrStO44+k9kwUVjjtseFEHhJLHD7lBg= -go.opentelemetry.io/collector/extension/auth v0.118.0 h1:+eMNUBUK1JK9A3mr95BasbWE90Lxu+WlR9sqS36sJms= -go.opentelemetry.io/collector/extension/auth v0.118.0/go.mod h1:MJpYcRGSERkgOhczqTKoAhkHmcugr+YTlRhc/SpYYYI= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.118.0 h1:I/SjuacUXdBOxa6ZnVMuMKkZX+m40tUm+5YKqWnNv/c= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.118.0/go.mod h1:IxDALY0rMvsENrVui7Y5tvvL/xHNgMKuhfiQiSHMiTQ= -go.opentelemetry.io/collector/extension/extensiontest v0.118.0 h1:rKBUaFS9elGfENG45wANmrwx7mHsmt1+YWCzxjftElg= -go.opentelemetry.io/collector/extension/extensiontest v0.118.0/go.mod h1:CqNXzkIOR32D8EUpptpOXhpFkibs3kFlRyNMEgIW8l4= -go.opentelemetry.io/collector/extension/xextension v0.118.0 h1:P6gvJzqnH9ma2QfnWde/E6Xu9bAzuefzIwm5iupiVPE= -go.opentelemetry.io/collector/extension/xextension v0.118.0/go.mod h1:ne4Q8ZtRlbC0Etr2hTcVkjOpVM2bE2xy1u+R80LUkDw= -go.opentelemetry.io/collector/extension/zpagesextension v0.118.0 h1:XkaLvST4p1/i/dsk5yCwFG4HJUUr6joCbegJc2MEOrE= -go.opentelemetry.io/collector/extension/zpagesextension v0.118.0/go.mod h1:alaAK7I7UeM1Hcs/eNqIjTLIZpqrk3mD1Ua42mJ7JnU= -go.opentelemetry.io/collector/featuregate v1.24.0 h1:DEqDsuJgxjZ3E5JNC9hXCd4sWGFiF7h9kaziODuqwFY= -go.opentelemetry.io/collector/featuregate v1.24.0/go.mod h1:3GaXqflNDVwWndNGBJ1+XJFy3Fv/XrFgjMN60N3z7yg= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.118.0 h1:affTj1Qxjbg9dZ1x2tbV9Rs9/otZQ1lHA++L8qB5KiQ= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.118.0/go.mod h1:9mbE68mYdtTyozr3jTtNMB1RA5F8/dt2aWVYSu6bsQ4= -go.opentelemetry.io/collector/otelcol v0.118.0 h1:uSD3wU0sO4vsw5VvWI2yUFLggLdq1BWN/nC1LJXIhMg= -go.opentelemetry.io/collector/otelcol v0.118.0/go.mod h1:OdKz/AXj+ewCwXp/acZCBIoMIYiIxeNRNkbqUXvWi+o= +go.opentelemetry.io/collector/connector v0.119.0 h1:TWEVa2Iu+YOW/BuqNAoX0iesv4ygocb9v6GKtZEGsSw= +go.opentelemetry.io/collector/connector v0.119.0/go.mod h1:4p/m2G2acL03RjhdeTJpo6afHFnfBU8E+eUxyrz7qd4= +go.opentelemetry.io/collector/connector/connectortest v0.119.0 h1:jfkxP4jrd+CkyM0SnOrwiSiOW0xyahsyUjWqMwVBbBI= +go.opentelemetry.io/collector/connector/connectortest v0.119.0/go.mod h1:W0jLFVqxpWE+Rz6+JoYY6wN6f41862n8PIr+igaECcI= +go.opentelemetry.io/collector/connector/xconnector v0.119.0 h1:00iGiSVJKp82WjWsyPCMfxmyTynGzNkr7dSrb4oMuyQ= +go.opentelemetry.io/collector/connector/xconnector v0.119.0/go.mod h1:8MPaHhN64/METupujKMxuX+2eixLduUHXxMqP4JUUpc= +go.opentelemetry.io/collector/consumer v1.25.0 h1:qCJa7Hh7lY3vYWgwcEgTGSjjITLCn+BSsya8LxjpoPY= +go.opentelemetry.io/collector/consumer v1.25.0/go.mod h1:ToBfr3BexnhHuxC8/XszkKP/YtkgsGd0yjFMQXNwvT8= +go.opentelemetry.io/collector/consumer/consumererror v0.119.0 h1:M6QXK3KLWnNLlUWOBgz+WQI//W9M8r9qVGWUA3mc5LM= +go.opentelemetry.io/collector/consumer/consumererror v0.119.0/go.mod h1:UNnNkr+ZQJhAMNE5v1n86lXbJrSYb+1ePcI98gV6xvo= +go.opentelemetry.io/collector/consumer/consumertest v0.119.0 h1:hZxdlvfOBzy/rl6mIyrannM4M+7zyv7C947f6W9Leio= +go.opentelemetry.io/collector/consumer/consumertest v0.119.0/go.mod h1:pfXxA2CCwbieymnX0ShZuHjwrWzmxJapsb8ZiSqojVc= +go.opentelemetry.io/collector/consumer/xconsumer v0.119.0 h1:s9DrRdb1kYXy2psr34zGG5sI+F4GRBIhjvEsh7C7FtE= +go.opentelemetry.io/collector/consumer/xconsumer v0.119.0/go.mod h1:3fvk+0hd4WMv76+oUUNah0rQ35dZzH3zyMMCg9MtsuY= +go.opentelemetry.io/collector/exporter v0.119.0 h1:eVHmkeB5HQY/FcoP62l7O4Q0cAZ97LwLhZiAQoQeBtU= +go.opentelemetry.io/collector/exporter v0.119.0/go.mod h1:xMF9mT01tXHX2NjfMRV8o9YyhPBZOR4Wt+srkTy1thM= +go.opentelemetry.io/collector/exporter/exportertest v0.119.0 h1:saABJIiyYyqWEBvGe2VVf5rMMpHdwB83nD6feNZ33nA= +go.opentelemetry.io/collector/exporter/exportertest v0.119.0/go.mod h1:S82pMkj1gWdivxVRKqaRJvGMgVRntKVI5dWAgs23KI8= +go.opentelemetry.io/collector/exporter/xexporter v0.119.0 h1:bCUFRa/of+iPrJoXyzJ5cbOv/hWDHw87bnDRFQJ/JVU= +go.opentelemetry.io/collector/exporter/xexporter v0.119.0/go.mod h1:naV2XoiJv8bvOt7Vs9h6aDWmJnuD1SRnDqkIFRINYlI= +go.opentelemetry.io/collector/extension v0.119.0 h1:Itkt3jqYLjkhoX4kWhICuhXQEQz332W7UL6DpmaNHMc= +go.opentelemetry.io/collector/extension v0.119.0/go.mod h1:yMpvs58Z9F3UpSoE4w/1q/EEKlLFZBOQ2muzzikRvO8= +go.opentelemetry.io/collector/extension/auth v0.119.0 h1:URPkjeo3aKmlYGgeFCZK6kLK+D1XGfDUGSAwFaHn+QQ= +go.opentelemetry.io/collector/extension/auth v0.119.0/go.mod h1:8mGcTLfgmf2QNrdumP7g7nnNtyrpHiPRZect1tdXYJQ= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.119.0 h1:OgG2AW0Ra43tbWDUOMC4TRIUXiz5PsVYNhnBtW3muk0= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.119.0/go.mod h1:e+5w+yz9d0KHBZcH1T204IGfEO4IWuAltCSh9L5i8wg= +go.opentelemetry.io/collector/extension/extensiontest v0.119.0 h1:sAdIBRJ6Df7jdkHWY/pSEYTersxURkUz9pENKl73n6s= +go.opentelemetry.io/collector/extension/extensiontest v0.119.0/go.mod h1:XQbUTXneJ//xt58eu5ofHhzWQcQ24GRTbBMWHCEsipA= +go.opentelemetry.io/collector/extension/xextension v0.119.0 h1:uSUvha4yxk5jWevhepsQ56QSAOkk3Z4M0vcPEJeZ6UU= +go.opentelemetry.io/collector/extension/xextension v0.119.0/go.mod h1:2DSTP2IEFfCC+2IFzl1eG9bCKsBkxIQjIphziJ0+vuo= +go.opentelemetry.io/collector/extension/zpagesextension v0.119.0 h1:NUmze3n47EhqWwM/GA0o98OFntsYialinKJABRw2Ri4= +go.opentelemetry.io/collector/extension/zpagesextension v0.119.0/go.mod h1:M2zapnlbhlJbuLU7edsDfokszyDIrqrOpIt0IEWxcJ8= +go.opentelemetry.io/collector/featuregate v1.25.0 h1:3b857fvoY9xBcE5qtLUE1/nlQ65teuW9d8CKr6MykYc= +go.opentelemetry.io/collector/featuregate v1.25.0/go.mod h1:3GaXqflNDVwWndNGBJ1+XJFy3Fv/XrFgjMN60N3z7yg= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.119.0 h1:egWfZjmGZRZ7a/LRJZQWs7MzlpHVo+jctdO+5jHigH8= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.119.0/go.mod h1:0qxt8Lql6prWxCHAl4WguY+sdgyr20imKLgD/M/trjs= +go.opentelemetry.io/collector/otelcol v0.119.0 h1:tHCo07NuSBtl3bPdYIVR78+9XKr/DqX2azPt5/QlcYM= +go.opentelemetry.io/collector/otelcol v0.119.0/go.mod h1:V4uiDdOk8dOVKH0NfTBofvxGtVgx53YrYvv4w+w2wwI= go.opentelemetry.io/collector/pdata v1.25.0 h1:AmgBklQfbfy0lT8qsoJtRuYMZ7ZV3VZvkvhjSDentrg= go.opentelemetry.io/collector/pdata v1.25.0/go.mod h1:Zs7D4RXOGS7E2faGc/jfWdbmhoiHBxA7QbpuJOioxq8= -go.opentelemetry.io/collector/pdata/pprofile v0.118.0 h1:VK/fr65VFOwEhsSGRPj5c3lCv0yIK1Kt0sZxv9WZBb8= -go.opentelemetry.io/collector/pdata/pprofile v0.118.0/go.mod h1:eJyP/vBm179EghV3dPSnamGAWQwLyd+4z/3yG54YFoQ= -go.opentelemetry.io/collector/pdata/testdata v0.118.0 h1:5N0w1SX9KIRkwvtkrpzQgXy9eGk3vfNG0ds6mhEPMIM= -go.opentelemetry.io/collector/pdata/testdata v0.118.0/go.mod h1:UY+GHV5bOC1BnFburOZ0wiHReJj1XbW12mi2Ogbc5Lw= -go.opentelemetry.io/collector/pipeline v0.118.0 h1:RI1DMe7L0+5hGkx0EDGxG00TaJoh96MEQppgOlGx1Oc= -go.opentelemetry.io/collector/pipeline v0.118.0/go.mod h1:qE3DmoB05AW0C3lmPvdxZqd/H4po84NPzd5MrqgtL74= -go.opentelemetry.io/collector/pipeline/xpipeline v0.118.0 h1:ZUVF1MYNQYZvmuL30KfP+QbVGSbFZvldBM9hgCe4J4k= -go.opentelemetry.io/collector/pipeline/xpipeline v0.118.0/go.mod h1:XgG1ktGO9J1f6fasMYPWSXL9Raan/VYB9vddKKWp5hQ= -go.opentelemetry.io/collector/processor v0.118.0 h1:NlqWiTTpPP+EPbrqTcNP9nh/4O4/9U9RGWVB49xo4ws= -go.opentelemetry.io/collector/processor v0.118.0/go.mod h1:Y8OD7wk51oPuBqrbn1qXIK91AbprRHP76hlvEzC24U4= -go.opentelemetry.io/collector/processor/processortest v0.118.0 h1:VfTLHuIaJWGyUmrvAOvf63gPMf1vAW68/jtJClEsKtU= -go.opentelemetry.io/collector/processor/processortest v0.118.0/go.mod h1:ZFWxsSoafGNOEk83FtGz43M5ypUzAOvGnfT0aQTDHdU= -go.opentelemetry.io/collector/processor/xprocessor v0.118.0 h1:M/EMhPRbadHLpv7g99fBjfgyuYexBZmgQqb2vjTXjvM= -go.opentelemetry.io/collector/processor/xprocessor v0.118.0/go.mod h1:lkoQoCv2Cz+C0kf2VHgBUDYWDecZLLeaHEvHDXbBCXU= -go.opentelemetry.io/collector/receiver v0.118.0 h1:X4mspHmbbtwdCQZ7o370kNmdWfxRnK1FrsvEShCCKEc= -go.opentelemetry.io/collector/receiver v0.118.0/go.mod h1:wFyfu6sgrkDPLQoGOGMuChGZzkZnYcI/tPJWV4CRTzs= -go.opentelemetry.io/collector/receiver/receivertest v0.118.0 h1:XlMr2mPsyXJsMUOqCpEoY3uCPsLZQbNA5fmVNDGB7Bw= -go.opentelemetry.io/collector/receiver/receivertest v0.118.0/go.mod h1:dtu/H1RNjhy11hTVf/XUfc02uGufMhYYdhhYBbglcUg= -go.opentelemetry.io/collector/receiver/xreceiver v0.118.0 h1:dzECve9e0H3ot0JWnWPuQr9Y84RhOYSd0+CjvJskx7Y= -go.opentelemetry.io/collector/receiver/xreceiver v0.118.0/go.mod h1:Lv1nD/mSYSP64iV8k+C+mWWZZOMLRubv9d1SUory3/E= -go.opentelemetry.io/collector/semconv v0.118.0 h1:V4vlMIK7TIaemrrn2VawvQPwruIKpj7Xgw9P5+BL56w= -go.opentelemetry.io/collector/semconv v0.118.0/go.mod h1:N6XE8Q0JKgBN2fAhkUQtqK9LT7rEGR6+Wu/Rtbal1iI= -go.opentelemetry.io/collector/service v0.118.0 h1:acZ9LzUbEF5M3G7o5FgenPJVuuM2y8c4HW5JVm648L4= -go.opentelemetry.io/collector/service v0.118.0/go.mod h1:uw3cl3UtkAOrEr8UQV2lXKjyTIbhWxURaQec8kE+Pic= -go.opentelemetry.io/contrib/bridges/otelzap v0.6.0 h1:j8icMXyyqNf6HGuwlYhniPnVsbJIq7n+WirDu3VAJdQ= -go.opentelemetry.io/contrib/bridges/otelzap v0.6.0/go.mod h1:evIOZpl+kAlU5IsaYX2Siw+IbpacAZvXemVsgt70uvw= -go.opentelemetry.io/contrib/config v0.10.0 h1:2JknAzMaYjxrHkTnZh3eOme/Y2P5eHE2SWfhfV6Xd6c= -go.opentelemetry.io/contrib/config v0.10.0/go.mod h1:aND2M6/KfNkntI5cyvHriR/zvZgPf8j9yETdSmvpfmc= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= -go.opentelemetry.io/contrib/propagators/b3 v1.31.0 h1:PQPXYscmwbCp76QDvO4hMngF2j8Bx/OTV86laEl8uqo= -go.opentelemetry.io/contrib/propagators/b3 v1.31.0/go.mod h1:jbqfV8wDdqSDrAYxVpXQnpM0XFMq2FtDesblJ7blOwQ= -go.opentelemetry.io/contrib/zpages v0.56.0 h1:W7vP6s3juzL5KiHpr41zLNmsJ0QAZudYu8ay0zGAoko= -go.opentelemetry.io/contrib/zpages v0.56.0/go.mod h1:IxPRP4TYHw9jLeaEOSDIiA9zmyJNZNO6sbW55iMvSXs= +go.opentelemetry.io/collector/pdata/pprofile v0.119.0 h1:sVtv/MhQ3NDLkgHOWDF9BdTtThNyXdOUiz5+poRkYLQ= +go.opentelemetry.io/collector/pdata/pprofile v0.119.0/go.mod h1:ur4388PjUpmwG5HoSMzrLCPkR0gNVLT4lekcJMRPt8A= +go.opentelemetry.io/collector/pdata/testdata v0.119.0 h1:a3OiuLYx7CaEQQ8LxMhPIM804eIGlNM6Pd0XoACXWMI= +go.opentelemetry.io/collector/pdata/testdata v0.119.0/go.mod h1:stCgL1fKOVp93mI4ocHy/xBMhkW3TXr8VetH4X86q8g= +go.opentelemetry.io/collector/pipeline v0.119.0 h1:NebdPIOBIzU7CdOE36hNrCrUML+XOTR9Zsoy43E7MVk= +go.opentelemetry.io/collector/pipeline v0.119.0/go.mod h1:qE3DmoB05AW0C3lmPvdxZqd/H4po84NPzd5MrqgtL74= +go.opentelemetry.io/collector/pipeline/xpipeline v0.119.0 h1:lX70c+MjXHbOJahU6Xs3yV1rPTV/7bWXlCj/C+CnMLc= +go.opentelemetry.io/collector/pipeline/xpipeline v0.119.0/go.mod h1:m2acg7G5Rb8Srm5aK4rD7mUDQhd1r/qXq1DJxdhMAcQ= +go.opentelemetry.io/collector/processor v0.119.0 h1:mqmdR/f4I/ud2jwODqwPZvJk/TCU+AjoCAyattyKXmE= +go.opentelemetry.io/collector/processor v0.119.0/go.mod h1:N0XxvcnM1EYmZ/NiGNsFpi3bEzZ9+C6bVZKDa7tUduw= +go.opentelemetry.io/collector/processor/processortest v0.119.0 h1:0/mWuyDvELipmEIMVscOAy1vAcwUttym8yb+KLOJXmc= +go.opentelemetry.io/collector/processor/processortest v0.119.0/go.mod h1:JGqoUDWC3aFbyPbpZbdvTTDssvR7Rgfpf72VY5FeDHw= +go.opentelemetry.io/collector/processor/xprocessor v0.119.0 h1:qWWcMgde/2cLBg9MUQk0AcxC/aD34wz2GY3qrWeEHiw= +go.opentelemetry.io/collector/processor/xprocessor v0.119.0/go.mod h1:ZYtJGcZSDEB54vzulS8jdlYBpPbjklEODaVRc27TlxE= +go.opentelemetry.io/collector/receiver v0.119.0 h1:ZatoS4POR+XDkN1WwAv18Ism9f/FUsIjtVT4MIZbQS0= +go.opentelemetry.io/collector/receiver v0.119.0/go.mod h1:JUSsVwyKKQVD/Fy3T98OHOlVHE15Z7juba5RQzG3AXc= +go.opentelemetry.io/collector/receiver/receivertest v0.119.0 h1:thZkyftPCNit/m2bUUC+zaR1+hbXoSkCDtNN/vZIZSg= +go.opentelemetry.io/collector/receiver/receivertest v0.119.0/go.mod h1:DZM70vofnquGkQiTfT5ZSFZlohxANl9XOrVq9h5IKnc= +go.opentelemetry.io/collector/receiver/xreceiver v0.119.0 h1:ZcTO+h+r9TyR1XgMhA7FTSTV9RF+z/IDPrcRIg1l56U= +go.opentelemetry.io/collector/receiver/xreceiver v0.119.0/go.mod h1:AkoWhnYFMygK7Tlzez398ti20NqydX8wxPVWU86+baE= +go.opentelemetry.io/collector/semconv v0.119.0 h1:xo+V3a7hnK0I6fxAWCXT8BIT1PCBYd4emolhoKSDUlI= +go.opentelemetry.io/collector/semconv v0.119.0/go.mod h1:N6XE8Q0JKgBN2fAhkUQtqK9LT7rEGR6+Wu/Rtbal1iI= +go.opentelemetry.io/collector/service v0.119.0 h1:AP2dFx7h0VslEJfc9dt8Bbbggm1iA1iUGLzahvAPZMk= +go.opentelemetry.io/collector/service v0.119.0/go.mod h1:p/kOqK7POtrT9Jz+tAx/UtzlzokSHhFyi7eAETRgmt8= +go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25PkeyWmOcI+SjXWguNw= +go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= +go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= +go.opentelemetry.io/contrib/config v0.14.0/go.mod h1:77rDmFPqBae5jtQ2C78RuDTHz4P27C8LzoN0MZyumYQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/contrib/propagators/b3 v1.34.0 h1:9pQdCEvV/6RWQmag94D6rhU+A4rzUhYBEJ8bpscx5p8= +go.opentelemetry.io/contrib/propagators/b3 v1.34.0/go.mod h1:FwM71WS8i1/mAK4n48t0KU6qUS/OZRBgDrHZv3RlJ+w= +go.opentelemetry.io/contrib/zpages v0.59.0 h1:t0H5zUy8fifIhRuVwm2FrA/D70Kk10SSpAEvvbaNscw= +go.opentelemetry.io/contrib/zpages v0.59.0/go.mod h1:9wo+yUPvHnBQEzoHJ8R3nA/Q5rkef7HjtLlSFI0Tgrc= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 h1:mMOmtYie9Fx6TSVzw4W+NTpvoaS1JWWga37oI1a/4qQ= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0/go.mod h1:yy7nDsMMBUkD+jeekJ36ur5f3jJIrmCwUrY67VFhNpA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= -go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= -go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 h1:TwmL3O3fRR80m8EshBrd8YydEZMcUCsZXzOUlnFohwM= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0/go.mod h1:tH98dDv5KPmPThswbXA0fr0Lwfs+OhK8HgaCo7PjRrk= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 h1:SZmDnHcgp3zwlPBS2JX2urGYe/jBKEIT6ZedHRUyCz8= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0/go.mod h1:fdWW0HtZJ7+jNpTKUR0GpMEDP69nR8YBJQxNiVCE3jk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64= -go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= -go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0/go.mod h1:leO2CSTg0Y+LyvmR7Wm4pUxE8KAmaM2GCVx7O+RATLA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 h1:opwv08VbCZ8iecIWs+McMdHRcAXzjAeda3uG2kI/hcA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0/go.mod h1:oOP3ABpW7vFHulLpE8aYtNBodrHhMTrvfxUXGvqm7Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= +go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E= +go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 h1:GKCEAZLEpEf78cUvudQdTg0aET2ObOZRB2HtXA0qPAI= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0/go.mod h1:9/zqSWLCmHT/9Jo6fYeUDRRogOLL60ABLsHWS99lF8s= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 h1:czJDQwFrMbOr9Kk+BPo1y8WZIIFIK58SA1kykuVeiOU= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0/go.mod h1:lT7bmsxOe58Tq+JIOkTQMCGXdu47oA+VJKLZHbaBKbs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= +go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= +go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= -go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= -go.opentelemetry.io/otel/sdk/log v0.7.0 h1:dXkeI2S0MLc5g0/AwxTZv6EUEjctiH8aG14Am56NTmQ= -go.opentelemetry.io/otel/sdk/log v0.7.0/go.mod h1:oIRXpW+WD6M8BuGj5rtS0aRu/86cbDV/dAfNaZBIjYM= -go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= -go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= +go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= -go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg= -go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -400,10 +402,10 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= From e978a082bf511423a6513d6597f333aacb50ca9e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 10:26:18 +0000 Subject: [PATCH 208/426] fix(deps): update module golang.org/x/net to v0.35.0 (main) (#4452) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index e3ecef3485..797af6b133 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.23.0 - golang.org/x/net v0.34.0 + golang.org/x/net v0.35.0 golang.org/x/oauth2 v0.26.0 golang.org/x/sys v0.30.0 google.golang.org/grpc v1.70.0 @@ -158,9 +158,9 @@ require ( go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/term v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/term v0.29.0 // indirect + golang.org/x/text v0.22.0 // indirect golang.org/x/time v0.8.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect diff --git a/go.sum b/go.sum index 86964b7863..d7df39bcae 100644 --- a/go.sum +++ b/go.sum @@ -361,15 +361,15 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -380,12 +380,12 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 65ca1fc2e40662f71dcd549aa224665164cfe9d8 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Wed, 12 Feb 2025 14:42:58 +0100 Subject: [PATCH 209/426] Move csi dk dirs into sub dir (#4419) --- pkg/controllers/csi/config.go | 7 +--- pkg/controllers/csi/driver/server.go | 17 +++++--- pkg/controllers/csi/metadata/correctness.go | 2 +- pkg/controllers/csi/metadata/path_resolver.go | 32 +++++++++++---- .../csi/provisioner/cleanup/appmounts.go | 2 +- .../csi/provisioner/cleanup/hostmounts.go | 19 +++++---- .../provisioner/cleanup/hostmounts_test.go | 32 ++++++++------- .../csi/provisioner/cleanup/run.go | 39 ++++++++++++++++--- .../csi/provisioner/cleanup/run_test.go | 16 ++++++-- .../codemodule/installer/job/bootstrapper.go | 5 +++ .../codemodule/installer/job/installer.go | 2 + pkg/util/kubeobjects/job/builder.go | 13 +++++++ 12 files changed, 135 insertions(+), 51 deletions(-) diff --git a/pkg/controllers/csi/config.go b/pkg/controllers/csi/config.go index b4ffcebf64..4f27ba2756 100644 --- a/pkg/controllers/csi/config.go +++ b/pkg/controllers/csi/config.go @@ -16,10 +16,6 @@ limitations under the License. package dtcsi -import ( - "path/filepath" -) - const ( DataPath = "/data" DriverName = "csi.oneagent.dynatrace.com" @@ -32,6 +28,7 @@ const ( SharedAgentBinDir = "codemodules" SharedJobWorkDir = "work" SharedAppMountsDir = "appmounts" + SharedDynaKubesDir = "_dynakubes" SharedAgentConfigDir = "config" DaemonSetName = "dynatrace-oneagent-csi-driver" @@ -39,8 +36,6 @@ const ( UnixUmask = 0000 ) -var MetadataAccessPath = filepath.Join(DataPath, "csi.db?_journal=WAL") - type CSIOptions struct { NodeId string Endpoint string diff --git a/pkg/controllers/csi/driver/server.go b/pkg/controllers/csi/driver/server.go index 9666017798..9b71e7dc8d 100644 --- a/pkg/controllers/csi/driver/server.go +++ b/pkg/controllers/csi/driver/server.go @@ -22,6 +22,7 @@ import ( "net" "net/url" "os" + "path/filepath" "runtime" "strconv" "sync/atomic" @@ -224,6 +225,17 @@ func (srv *Server) unmount(volumeInfo csivolumes.VolumeInfo) { } for _, path := range needsCleanUp { + podInfoSymlinkPath := srv.findPodInfoSymlink(volumeInfo) // cleaning up the pod-info symlink here is far more efficient instead of having to walk the whole fs during cleanup + if podInfoSymlinkPath != "" { + _ = srv.fs.Remove(podInfoSymlinkPath) + + podInfoSymlinkDir := filepath.Dir(podInfoSymlinkPath) + + if isEmpty, _ := srv.fs.IsEmpty(podInfoSymlinkDir); isEmpty { + _ = srv.fs.Remove(podInfoSymlinkDir) + } + } + err := srv.fs.RemoveAll(path) // you see correctly, we don't keep the logs of the app mounts, will keep them when they will have a use if err != nil { log.Error(err, "failed to clean up unmounted volume dir", "path", path) @@ -232,11 +244,6 @@ func (srv *Server) unmount(volumeInfo csivolumes.VolumeInfo) { _ = srv.fs.RemoveAll(appMountDir) // try to cleanup fully, but lets not spam the logs with errors } - - podInfoSymlinkPath := srv.findPodInfoSymlink(volumeInfo) // cleaning up the pod-info symlink here is far more efficient instead of having to walk the whole fs during cleanup - if podInfoSymlinkPath != "" { - _ = srv.fs.Remove(podInfoSymlinkPath) - } } func (srv *Server) findPodInfoSymlink(volumeInfo csivolumes.VolumeInfo) string { diff --git a/pkg/controllers/csi/metadata/correctness.go b/pkg/controllers/csi/metadata/correctness.go index 6e5b50f194..3c24bac18b 100644 --- a/pkg/controllers/csi/metadata/correctness.go +++ b/pkg/controllers/csi/metadata/correctness.go @@ -114,7 +114,7 @@ func (checker *CorrectnessChecker) migrateHostMounts(ctx context.Context) { continue } - oldPath := checker.path.OsAgentDir(tenantUUID) + oldPath := checker.path.OldOsAgentDir(tenantUUID) oldExists, err := checker.fs.DirExists(oldPath) if err != nil { diff --git a/pkg/controllers/csi/metadata/path_resolver.go b/pkg/controllers/csi/metadata/path_resolver.go index 2414d57409..93ef2abd51 100644 --- a/pkg/controllers/csi/metadata/path_resolver.go +++ b/pkg/controllers/csi/metadata/path_resolver.go @@ -11,8 +11,16 @@ type PathResolver struct { RootDir string } +func (pr PathResolver) Base(name string) string { + return filepath.Join(pr.RootDir, name) +} + +func (pr PathResolver) DynaKubesBaseDir() string { + return pr.Base(dtcsi.SharedDynaKubesDir) +} + func (pr PathResolver) DynaKubeDir(dynakubeName string) string { - return filepath.Join(pr.RootDir, dynakubeName) + return filepath.Join(pr.DynaKubesBaseDir(), dynakubeName) } func (pr PathResolver) OsAgentDir(dynakubeName string) string { @@ -20,7 +28,7 @@ func (pr PathResolver) OsAgentDir(dynakubeName string) string { } func (pr PathResolver) AgentSharedBinaryDirBase() string { - return filepath.Join(pr.RootDir, dtcsi.SharedAgentBinDir) + return pr.Base(dtcsi.SharedAgentBinDir) } func (pr PathResolver) AgentJobWorkDirBase() string { @@ -40,7 +48,7 @@ func (pr PathResolver) LatestAgentBinaryForDynaKube(dynakubeName string) string } func (pr PathResolver) AgentTempUnzipRootDir() string { - return filepath.Join(pr.RootDir, "tmp_zip") + return pr.Base("tmp_zip") } func (pr PathResolver) AgentTempUnzipDir() string { @@ -65,7 +73,7 @@ func (pr PathResolver) OverlayVarPodInfo(volumeID string) string { // AppMountsBaseDir replaces the AgentRunDir, the base directory where all the volumes for the app-mounts are stored func (pr PathResolver) AppMountsBaseDir() string { - return filepath.Join(pr.RootDir, dtcsi.SharedAppMountsDir) + return pr.Base(dtcsi.SharedAppMountsDir) } // AppMountForID replaces AgentRunDirForVolume, the directory where a given app-mount volume is stored @@ -75,7 +83,7 @@ func (pr PathResolver) AppMountForID(volumeID string) string { // AppMountForDK is a directory where a given app-mount volume is stored under a certain dynakube func (pr PathResolver) AppMountForDK(dkName string) string { - return filepath.Join(pr.RootDir, dkName, dtcsi.SharedAppMountsDir) + return filepath.Join(pr.DynaKubeDir(dkName), dtcsi.SharedAppMountsDir) } // AppMountMappedDir replaces OverlayMappedDir, the directory where the overlay layers combine into @@ -97,9 +105,14 @@ func (pr PathResolver) AppMountPodInfoDir(dkName, podNamespace, podName string) return filepath.Join(pr.AppMountForDK(dkName), podNamespace, podName) } +// Deprecated kept for future migration/cleanup +func (pr PathResolver) TenantDir(tenantUUID string) string { + return pr.Base(tenantUUID) +} + // Deprecated kept for future migration/cleanup func (pr PathResolver) AgentRunDir(dynakubeName string) string { - return filepath.Join(pr.DynaKubeDir(dynakubeName), dtcsi.AgentRunDir) + return filepath.Join(pr.TenantDir(dynakubeName), dtcsi.AgentRunDir) } // Deprecated kept for future migration/cleanup @@ -122,9 +135,14 @@ func (pr PathResolver) OverlayWorkDir(dynakubeName string, volumeId string) stri return filepath.Join(pr.AgentRunDirForVolume(dynakubeName, volumeId), dtcsi.OverlayWorkDirPath) } +// Deprecated kept for future migration/cleanup +func (pr PathResolver) OldOsAgentDir(tenantUUID string) string { + return filepath.Join(pr.TenantDir(tenantUUID), "osagent") +} + // Deprecated kept for future migration/cleanup func (pr PathResolver) OldAgentConfigDir(tenantUUID string, dynakubeName string) string { - return filepath.Join(pr.DynaKubeDir(tenantUUID), dynakubeName, dtcsi.SharedAgentConfigDir) + return filepath.Join(pr.TenantDir(tenantUUID), dynakubeName, dtcsi.SharedAgentConfigDir) } // Deprecated kept for future migration/cleanup diff --git a/pkg/controllers/csi/provisioner/cleanup/appmounts.go b/pkg/controllers/csi/provisioner/cleanup/appmounts.go index 5c5d352814..402fd5be6f 100644 --- a/pkg/controllers/csi/provisioner/cleanup/appmounts.go +++ b/pkg/controllers/csi/provisioner/cleanup/appmounts.go @@ -43,7 +43,7 @@ func (c *Cleaner) removeDeprecatedMounts(fsState fsState) { continue } - tenantDir := c.path.DynaKubeDir(depDir) + tenantDir := c.path.TenantDir(depDir) err = c.fs.RemoveAll(c.path.DynaKubeDir(tenantDir)) if err == nil { diff --git a/pkg/controllers/csi/provisioner/cleanup/hostmounts.go b/pkg/controllers/csi/provisioner/cleanup/hostmounts.go index 4b267f6caf..3f7335024f 100644 --- a/pkg/controllers/csi/provisioner/cleanup/hostmounts.go +++ b/pkg/controllers/csi/provisioner/cleanup/hostmounts.go @@ -32,13 +32,18 @@ func (c *Cleaner) removeHostMounts(dks []dynakube.DynaKube, fsState fsState) { relevantHostDirs := c.collectRelevantHostDirs(dks) for _, hostDk := range fsState.hostDks { - hostDir := c.path.OsAgentDir(hostDk) + possibleHostDirs := []string{ + c.path.OsAgentDir(hostDk), + c.path.OldOsAgentDir(hostDk), + } - isMountPoint, err := c.isMountPoint(hostDir) - if err == nil && !isMountPoint && !relevantHostDirs[hostDir] { - err := c.fs.RemoveAll(hostDir) - if err == nil { - log.Info("removed old host mount directory", "path", hostDir) + for _, hostDir := range possibleHostDirs { + isMountPoint, err := c.isMountPoint(hostDir) + if err == nil && !isMountPoint && !relevantHostDirs[hostDir] { + err := c.fs.RemoveAll(hostDir) + if err == nil { + log.Info("removed old host mount directory", "path", hostDir) + } } } } @@ -65,7 +70,7 @@ func (c *Cleaner) collectRelevantHostDirs(dks []dynakube.DynaKube) map[string]bo continue } - deprecatedHostDirLink := c.path.OsAgentDir(tenantUUID) + deprecatedHostDirLink := c.path.OldOsAgentDir(tenantUUID) c.safeAddRelevantPath(deprecatedHostDirLink, hostDirs) } diff --git a/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go b/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go index 46dcfe9b63..7001be115a 100644 --- a/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go +++ b/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go @@ -2,6 +2,7 @@ package cleanup import ( "fmt" + "os" "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" @@ -47,27 +48,30 @@ func TestRemoveHostMounts(t *testing.T) { createHostMonDk(t, "hostmon", apiUrl1), createCloudNativeDk(t, "cloudnative", apiUrl2), } - hostFolders := []string{tenantUUID1, dks[0].Name, dks[1].Name, "random-name1", "random-name2"} - - for _, folder := range hostFolders { - cleaner.createHostDirs(t, folder) + folders := []string{ + cleaner.path.OldOsAgentDir(tenantUUID1), + cleaner.path.OsAgentDir(dks[0].Name), + cleaner.path.OsAgentDir(dks[1].Name), + cleaner.path.OldOsAgentDir("random-name1"), + cleaner.path.OsAgentDir("random-name2"), + } - expectedDir := cleaner.path.OsAgentDir(folder) - exists, _ := cleaner.fs.Exists(expectedDir) - require.True(t, exists) + for _, folder := range folders { + err := cleaner.fs.MkdirAll(folder, os.ModePerm) + require.NoError(t, err) } cleaner.removeHostMounts(dks, fsState{ - hostDks: hostFolders, + hostDks: []string{dks[0].Name, dks[1].Name, tenantUUID1, "random-name1", "random-name2"}, }) - for _, folder := range hostFolders[:3] { - exists, _ := cleaner.fs.Exists(cleaner.path.OsAgentDir(folder)) + for _, folder := range folders[:3] { + exists, _ := cleaner.fs.Exists(folder) require.True(t, exists) } - for _, folder := range hostFolders[3:] { - exists, _ := cleaner.fs.Exists(cleaner.path.OsAgentDir(folder)) + for _, folder := range folders[3:] { + exists, _ := cleaner.fs.Exists(folder) require.False(t, exists) } }) @@ -155,7 +159,7 @@ func TestCollectRelevantHostDirs(t *testing.T) { createAppMonDk(t, "appmon", apiUrl1), } - cleaner.createHostDirs(t, tenantUUID1) + cleaner.createDeprecatedHostDirs(t, tenantUUID1) cleaner.createHostDirs(t, dks[0].Name) relevantDirs := cleaner.collectRelevantHostDirs(dks) @@ -165,7 +169,7 @@ func TestCollectRelevantHostDirs(t *testing.T) { assert.Contains(t, relevantDirs, cleaner.path.OsAgentDir(dks[0].Name)) assert.Contains(t, relevantDirs, cleaner.path.OsAgentDir(dks[1].Name)) assert.NotContains(t, relevantDirs, cleaner.path.OsAgentDir(dks[2].Name)) - assert.Contains(t, relevantDirs, cleaner.path.OsAgentDir(tenantUUID1)) + assert.Contains(t, relevantDirs, cleaner.path.OldOsAgentDir(tenantUUID1)) assert.NotContains(t, relevantDirs, cleaner.path.OsAgentDir(tenantUUID2)) }) } diff --git a/pkg/controllers/csi/provisioner/cleanup/run.go b/pkg/controllers/csi/provisioner/cleanup/run.go index 035ff2eeab..1840690903 100644 --- a/pkg/controllers/csi/provisioner/cleanup/run.go +++ b/pkg/controllers/csi/provisioner/cleanup/run.go @@ -86,10 +86,18 @@ func (c *Cleaner) getFilesystemState() (fsState fsState, err error) { //nolint:r var unknownDirs []string + defer func() { + for _, unknown := range unknownDirs { + log.Info("removing unknown path", "path", unknown) + _ = c.fs.RemoveAll(unknown) + } + }() + for _, fileInfo := range rootSubDirs { if !fileInfo.IsDir() || fileInfo.Name() == dtcsi.SharedAppMountsDir || fileInfo.Name() == dtcsi.SharedJobWorkDir || + fileInfo.Name() == dtcsi.SharedDynaKubesDir || fileInfo.Name() == dtcsi.SharedAgentBinDir { continue } @@ -99,6 +107,30 @@ func (c *Cleaner) getFilesystemState() (fsState fsState, err error) { //nolint:r fsState.deprecatedDks = append(fsState.deprecatedDks, fileInfo.Name()) } + hostExists, _ := c.fs.Exists(c.path.OldOsAgentDir(fileInfo.Name())) + if hostExists { + fsState.hostDks = append(fsState.hostDks, fileInfo.Name()) + } + + if !deprecatedExists && !hostExists { + unknownDirs = append(unknownDirs, c.path.Base(fileInfo.Name())) + } + } + + dkDirs, err := c.fs.ReadDir(c.path.DynaKubesBaseDir()) + if os.IsNotExist(err) { + return fsState, nil + } else if err != nil { + log.Info("failed to list the contents of the root directory of the csi-provisioner", "rootDir", c.path.RootDir) + + return fsState, err + } + + for _, fileInfo := range dkDirs { + if !fileInfo.IsDir() { + continue + } + binExists, _ := c.fs.Exists(c.path.LatestAgentBinaryForDynaKube(fileInfo.Name())) if binExists { fsState.binDks = append(fsState.binDks, fileInfo.Name()) @@ -109,16 +141,11 @@ func (c *Cleaner) getFilesystemState() (fsState fsState, err error) { //nolint:r fsState.hostDks = append(fsState.hostDks, fileInfo.Name()) } - if !deprecatedExists && !binExists && !hostExists { + if !binExists && !hostExists { unknownDirs = append(unknownDirs, c.path.DynaKubeDir(fileInfo.Name())) } } - for _, unknown := range unknownDirs { - log.Info("removing unknown path", "path", unknown) - _ = c.fs.RemoveAll(unknown) - } - return fsState, nil } diff --git a/pkg/controllers/csi/provisioner/cleanup/run_test.go b/pkg/controllers/csi/provisioner/cleanup/run_test.go index 55c186396d..c2c0e12239 100644 --- a/pkg/controllers/csi/provisioner/cleanup/run_test.go +++ b/pkg/controllers/csi/provisioner/cleanup/run_test.go @@ -24,8 +24,8 @@ func TestGetFilesystemState(t *testing.T) { t.Run("remove unknown dirs", func(t *testing.T) { cleaner := createCleaner(t) - cleaner.fs.Mkdir(cleaner.path.DynaKubeDir("test1"), os.ModePerm) - cleaner.fs.Mkdir(cleaner.path.DynaKubeDir("test2"), os.ModePerm) + cleaner.fs.Mkdir(cleaner.path.Base("test1"), os.ModePerm) + cleaner.fs.Mkdir(cleaner.path.Base("test2"), os.ModePerm) files, err := cleaner.fs.ReadDir(cleaner.path.RootDir) require.NoError(t, err) @@ -43,8 +43,8 @@ func TestGetFilesystemState(t *testing.T) { t.Run("don't touch unknown files, to keep the db intact, just in case", func(t *testing.T) { cleaner := createCleaner(t) - cleaner.fs.Create(cleaner.path.DynaKubeDir("test1")) - cleaner.fs.Create(cleaner.path.DynaKubeDir("test2")) + cleaner.fs.Create(cleaner.path.Base("test1")) + cleaner.fs.Create(cleaner.path.Base("test2")) files, err := cleaner.fs.ReadDir(cleaner.path.RootDir) require.NoError(t, err) @@ -168,3 +168,11 @@ func (c *Cleaner) createHostDirs(t *testing.T, name string) { err := c.fs.MkdirAll(hostDir, os.ModePerm) require.NoError(t, err) } + +func (c *Cleaner) createDeprecatedHostDirs(t *testing.T, tenantUUID string) { + t.Helper() + + hostDir := c.path.OldOsAgentDir(tenantUUID) + err := c.fs.MkdirAll(hostDir, os.ModePerm) + require.NoError(t, err) +} diff --git a/pkg/injection/codemodule/installer/job/bootstrapper.go b/pkg/injection/codemodule/installer/job/bootstrapper.go index 4f3989eb15..678697c4ea 100644 --- a/pkg/injection/codemodule/installer/job/bootstrapper.go +++ b/pkg/injection/codemodule/installer/job/bootstrapper.go @@ -16,6 +16,9 @@ const ( volumeName = "dynatrace-codemodules" codeModuleSource = "/opt/dynatrace/oneagent" + + activeDeadlineSeconds int64 = 600 // 10 min, after which the Job will be put into a Failed state + ttlSecondsAfterFinished int32 = 10 // 10 sec after the Job is put into a Succeeded or Failed state the Job and related Pods will be terminated ) func (inst *Installer) buildJobName() string { @@ -80,6 +83,8 @@ func (inst *Installer) buildJob(name, targetDir string) (*batchv1.Job, error) { jobutil.SetVolumes([]corev1.Volume{hostVolume}), jobutil.SetOnFailureRestartPolicy(), jobutil.SetAutomountServiceAccountToken(false), + jobutil.SetActiveDeadlineSeconds(activeDeadlineSeconds), + jobutil.SetTTLSecondsAfterFinished(ttlSecondsAfterFinished), ) } diff --git a/pkg/injection/codemodule/installer/job/installer.go b/pkg/injection/codemodule/installer/job/installer.go index cd9cd8df14..364bbaa2a5 100644 --- a/pkg/injection/codemodule/installer/job/installer.go +++ b/pkg/injection/codemodule/installer/job/installer.go @@ -78,6 +78,8 @@ func (inst *Installer) isReady(ctx context.Context, targetDir, jobName string) ( if inst.isAlreadyPresent(targetDir) { log.Info("agent already installed", "image", inst.props.ImageUri, "target dir", targetDir) + _ = inst.fs.RemoveAll(inst.props.PathResolver.AgentJobWorkDirForJob(jobName)) + return true, inst.query().DeleteForNamespace(ctx, jobName, inst.props.Owner.GetNamespace(), &client.DeleteOptions{PropagationPolicy: ptr.To(metav1.DeletePropagationBackground)}) } diff --git a/pkg/util/kubeobjects/job/builder.go b/pkg/util/kubeobjects/job/builder.go index 9698b59bb7..ba6e73f541 100644 --- a/pkg/util/kubeobjects/job/builder.go +++ b/pkg/util/kubeobjects/job/builder.go @@ -6,6 +6,7 @@ import ( batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) var ( @@ -77,6 +78,18 @@ func SetPodAnnotations(annotations map[string]string) builder.Option[*batchv1.Jo } } +func SetTTLSecondsAfterFinished(ttl int32) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.Spec.TTLSecondsAfterFinished = ptr.To(ttl) + } +} + +func SetActiveDeadlineSeconds(deadline int64) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.Spec.ActiveDeadlineSeconds = ptr.To(deadline) + } +} + func SetAllLabels(labels, matchLabels, templateLabels, customLabels map[string]string) builder.Option[*batchv1.Job] { return func(s *batchv1.Job) { s.ObjectMeta.Labels = labels From c3a37da9cfc373c52a1ff880061e44fe04f9c3a8 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Wed, 12 Feb 2025 17:25:10 +0100 Subject: [PATCH 210/426] add back ability to trigger ondemand on latest release branch (#4459) --- .github/workflows/e2e-tests-ondemand.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/e2e-tests-ondemand.yaml b/.github/workflows/e2e-tests-ondemand.yaml index 2321a680a9..e94dbb5c83 100644 --- a/.github/workflows/e2e-tests-ondemand.yaml +++ b/.github/workflows/e2e-tests-ondemand.yaml @@ -1,6 +1,7 @@ name: E2E tests ondemand on: + workflow_dispatch: schedule: # At 03:00 UTC on Monday, Wednesday, and Friday. - cron: 0 3 * * 1,3,5 From 29a216d9e009a29b9d31d3ec56dc2f3b6e2ecaff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 21:17:28 +0100 Subject: [PATCH 211/426] [Automatic] Update index for refs/tags/v1.4.1 release (#4460) Co-authored-by: StefanHauth Co-authored-by: StefanHauth <63204425+StefanHauth@users.noreply.github.com> --- config/helm/repos/stable/index.yaml | 24 +++++++++++++++++++- config/helm/repos/stable/index.yaml.previous | 24 +++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/config/helm/repos/stable/index.yaml b/config/helm/repos/stable/index.yaml index ad5f93fb80..9457ef6d58 100644 --- a/config/helm/repos/stable/index.yaml +++ b/config/helm/repos/stable/index.yaml @@ -1,6 +1,28 @@ apiVersion: v1 entries: dynatrace-operator: + - apiVersion: v2 + appVersion: 1.4.1 + created: '2025-02-12T16:45:34.569679796Z' + description: The Dynatrace Operator Helm chart for Kubernetes and OpenShift + digest: 1389f21f5a1b26ef24b6759177a44c5ebd46666ddc1cff8c7c64fdb4dd00f759 + home: https://www.dynatrace.com/ + icon: https://assets.dynatrace.com/global/resources/Signet_Logo_RGB_CP_512x512px.png + kubeVersion: '>=1.19.0-0' + maintainers: + - email: marcell.sevcsik@dynatrace.com + name: 0sewa0 + - email: christoph.muellner@dynatrace.com + name: chrismuellner + - email: stefan.hauth@dynatrace.com + name: StefanHauth + name: dynatrace-operator + sources: + - https://github.com/Dynatrace/dynatrace-operator + type: application + urls: + - https://github.com/Dynatrace/dynatrace-operator/releases/download/v1.4.1/dynatrace-operator-1.4.1.tgz + version: 1.4.1 - apiVersion: v2 appVersion: 1.4.0 created: '2024-12-09T09:04:42.588691061Z' @@ -1060,4 +1082,4 @@ entries: urls: - https://raw.githubusercontent.com/Dynatrace/helm-charts/master/repos/stable/dynatrace-operator-0.1.0.tgz version: 0.1.0 -generated: '2024-12-09T09:04:42.585436968Z' +generated: '2025-02-12T16:45:34.566587927Z' diff --git a/config/helm/repos/stable/index.yaml.previous b/config/helm/repos/stable/index.yaml.previous index 739353b5dc..ad5f93fb80 100644 --- a/config/helm/repos/stable/index.yaml.previous +++ b/config/helm/repos/stable/index.yaml.previous @@ -1,6 +1,28 @@ apiVersion: v1 entries: dynatrace-operator: + - apiVersion: v2 + appVersion: 1.4.0 + created: '2024-12-09T09:04:42.588691061Z' + description: The Dynatrace Operator Helm chart for Kubernetes and OpenShift + digest: d09c178806648400d76955a4c0af249cf769016eda768899f4ba5a700e1cdc58 + home: https://www.dynatrace.com/ + icon: https://assets.dynatrace.com/global/resources/Signet_Logo_RGB_CP_512x512px.png + kubeVersion: '>=1.19.0-0' + maintainers: + - email: marcell.sevcsik@dynatrace.com + name: 0sewa0 + - email: christoph.muellner@dynatrace.com + name: chrismuellner + - email: lukas.hinterreiter@dynatrace.com + name: luhi-DT + name: dynatrace-operator + sources: + - https://github.com/Dynatrace/dynatrace-operator + type: application + urls: + - https://github.com/Dynatrace/dynatrace-operator/releases/download/v1.4.0/dynatrace-operator-1.4.0.tgz + version: 1.4.0 - apiVersion: v2 appVersion: 1.3.2 created: '2024-10-24T11:28:10.332056983Z' @@ -1038,4 +1060,4 @@ entries: urls: - https://raw.githubusercontent.com/Dynatrace/helm-charts/master/repos/stable/dynatrace-operator-0.1.0.tgz version: 0.1.0 -generated: '2024-10-31T07:13:31.055858571Z' +generated: '2024-12-09T09:04:42.585436968Z' From bc56d94396dc35298c6b3ae46b156b37a6c1dad5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 22:29:22 +0000 Subject: [PATCH 212/426] chore(deps): update golang docker tag to v1.24.0 (main) (#4461) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 082337bafc..8a602ef97e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # check=skip=RedundantTargetPlatform # setup build image -FROM --platform=$BUILDPLATFORM golang:1.23.6@sha256:958bd2e45b2d6d166aa0e33ee737093fe0c773c89c3fc142f26ac65ec37507cd AS operator-build +FROM --platform=$BUILDPLATFORM golang:1.24.0@sha256:4546829ecda4404596cf5c9d8936488283910a3564ffc8fe4f32b33ddaeff239 AS operator-build WORKDIR /app From 056d80263755460a9a787e261ae72cde1cd6d743 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 13 Feb 2025 02:56:47 +0000 Subject: [PATCH 213/426] chore(deps): update module github.com/golangci/golangci-lint to v1.64.4 (main) (#4462) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- hack/make/prerequisites.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5d6bde26ce..5895d1af99 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -89,7 +89,7 @@ jobs: uses: golangci/golangci-lint-action@051d91933864810ecd5e2ea2cfd98f6a5bca5347 # v6.3.2 with: # renovate depName=github.com/golangci/golangci-lint - version: v1.64.2 + version: v1.64.4 args: --build-tags e2e --timeout 300s --out-${NO_FUTURE}format colored-line-number - name: Run deadcode id: deadcode diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 487776440c..5d0290e6ad 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -3,7 +3,7 @@ kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.2 # renovate depName=github.com/golangci/golangci-lint -golang_ci_cmd_version=v1.64.2 +golang_ci_cmd_version=v1.64.4 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools From 08c4dcfaea766ec31b7fcd4c9a9f889b0f946ecc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 13 Feb 2025 10:26:13 +0000 Subject: [PATCH 214/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1739421239 (main) (#4463) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8a602ef97e..5265cf8230 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739146154@sha256:4a2052ef4db4fd1a53b45263b5067eb01d5745fdd300b27986952af27887bc27 AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739421239@sha256:995fe59c0358a671b4ad013058866f4cebbd0a9742e248d255520cf7c19e3066 AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1738814488@sha256:be214e191bbe3f4d0f16a5a4f5642e1f32fccd6fae7d2b6c6acb066ba51fb507 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From 57a7c5a27133373731e684d86c034bbff9644dbd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 13 Feb 2025 19:13:49 +0000 Subject: [PATCH 215/426] chore(deps): update golangci/golangci-lint-action action to v6.3.3 (main) (#4467) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5895d1af99..792f2bfacc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,7 +86,7 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint - uses: golangci/golangci-lint-action@051d91933864810ecd5e2ea2cfd98f6a5bca5347 # v6.3.2 + uses: golangci/golangci-lint-action@e0ebdd245eea59746bb0b28ea6a9871d3e35fbc9 # v6.3.3 with: # renovate depName=github.com/golangci/golangci-lint version: v1.64.4 From bee86f549819b9e1ad9d7956b7632cf8debfc8fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Feb 2025 00:15:16 +0000 Subject: [PATCH 216/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1739449058 (main) (#4468) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5265cf8230..dbd6347449 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739421239@sha256:995fe59c0358a671b4ad013058866f4cebbd0a9742e248d255520cf7c19e3066 AS base -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1738814488@sha256:be214e191bbe3f4d0f16a5a4f5642e1f32fccd6fae7d2b6c6acb066ba51fb507 AS dependency +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1739449058@sha256:4495380286c97b9c2635b0b5d6f227bbd9003628be8383a37ff99984eefa42ed AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From a7889f58a37440969ed9e83afb2be7c6d5683d69 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Feb 2025 01:40:30 +0000 Subject: [PATCH 217/426] chore(deps): update module github.com/golangci/golangci-lint to v1.64.5 (main) (#4471) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- hack/make/prerequisites.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 792f2bfacc..eec95521e3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -89,7 +89,7 @@ jobs: uses: golangci/golangci-lint-action@e0ebdd245eea59746bb0b28ea6a9871d3e35fbc9 # v6.3.3 with: # renovate depName=github.com/golangci/golangci-lint - version: v1.64.4 + version: v1.64.5 args: --build-tags e2e --timeout 300s --out-${NO_FUTURE}format colored-line-number - name: Run deadcode id: deadcode diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 5d0290e6ad..0ee8b9e203 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -3,7 +3,7 @@ kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.2 # renovate depName=github.com/golangci/golangci-lint -golang_ci_cmd_version=v1.64.4 +golang_ci_cmd_version=v1.64.5 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools From 3dcb3c8ee4de59d4d8624bd3abd41b5e2cc788c6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Feb 2025 07:46:37 +0000 Subject: [PATCH 218/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1739467664 (main) (#4469) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index dbd6347449..8c63391b0a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739421239@sha256:995fe59c0358a671b4ad013058866f4cebbd0a9742e248d255520cf7c19e3066 AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739467664@sha256:e01d3109d55b6cc4e5a58911e979f91ae29f30e50124563d277a6f29be08397f AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1739449058@sha256:4495380286c97b9c2635b0b5d6f227bbd9003628be8383a37ff99984eefa42ed AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From a3a95b91d22e50ae51f6c12be2fc00e47266ed28 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Feb 2025 10:56:06 +0000 Subject: [PATCH 219/426] fix(deps): update kubernetes packages to v0.32.2 (main) (#4470) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 797af6b133..f03d538d2a 100644 --- a/go.mod +++ b/go.mod @@ -31,11 +31,11 @@ require ( gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.24.3 istio.io/client-go v1.24.3 - k8s.io/api v0.32.1 - k8s.io/apiextensions-apiserver v0.32.1 - k8s.io/apimachinery v0.32.1 - k8s.io/client-go v0.32.1 - k8s.io/mount-utils v0.32.1 + k8s.io/api v0.32.2 + k8s.io/apiextensions-apiserver v0.32.2 + k8s.io/apimachinery v0.32.2 + k8s.io/client-go v0.32.2 + k8s.io/mount-utils v0.32.2 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.20.1 sigs.k8s.io/e2e-framework v0.3.0 diff --git a/go.sum b/go.sum index d7df39bcae..92663a87ba 100644 --- a/go.sum +++ b/go.sum @@ -426,20 +426,20 @@ istio.io/api v1.24.3 h1:iwWWPM0uEQ+oxRHvIWoB8MQ4bjF3dRQj+M5IDVczg0M= istio.io/api v1.24.3/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= istio.io/client-go v1.24.3 h1:TB8IcM3yyMCDzKRJo0YfFOUGNQmkhwH/JE/Yr3lzVAk= istio.io/client-go v1.24.3/go.mod h1:zSyw/c4luKQKosFIHQaWAQOA0c3bODu4SahQCAMlKA4= -k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc= -k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k= -k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw= -k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto= -k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs= -k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU= -k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg= +k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= +k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= +k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4= +k8s.io/apiextensions-apiserver v0.32.2/go.mod h1:GPwf8sph7YlJT3H6aKUWtd0E+oyShk/YHWQHf/OOgCA= +k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= +k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= +k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/mount-utils v0.32.1 h1:RJOD6xXzEJT/OOJoG1KstfVa8ZXJJPlHb+t2MoulPHM= -k8s.io/mount-utils v0.32.1/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= +k8s.io/mount-utils v0.32.2 h1:aDwp+ucWiVnDr/LpRg88/dsXf/vm6gI1VZkYH3+3+Vw= +k8s.io/mount-utils v0.32.2/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE= From e9e98c13bb048295089ebf93ded52b938b0b38fd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Feb 2025 18:41:51 +0000 Subject: [PATCH 220/426] chore(deps): update golangci/golangci-lint-action action to v6.4.1 (main) (#4472) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index eec95521e3..ba85f90320 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,7 +86,7 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint - uses: golangci/golangci-lint-action@e0ebdd245eea59746bb0b28ea6a9871d3e35fbc9 # v6.3.3 + uses: golangci/golangci-lint-action@818ec4d51a1feacefc42ff1b3ec25d4962690f39 # v6.4.1 with: # renovate depName=github.com/golangci/golangci-lint version: v1.64.5 From ffd32ee549827eae1331aae6eb5add3f03fbef71 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Feb 2025 23:01:37 +0000 Subject: [PATCH 221/426] fix(deps): update module sigs.k8s.io/controller-runtime to v0.20.2 (main) (#4476) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index f03d538d2a..63f9c77669 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( k8s.io/client-go v0.32.2 k8s.io/mount-utils v0.32.2 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - sigs.k8s.io/controller-runtime v0.20.1 + sigs.k8s.io/controller-runtime v0.20.2 sigs.k8s.io/e2e-framework v0.3.0 sigs.k8s.io/yaml v1.4.0 ) @@ -52,7 +52,7 @@ require ( github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/ebitengine/purego v0.8.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect diff --git a/go.sum b/go.sum index 92663a87ba..b704fc075c 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxER github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= @@ -136,10 +136,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= -github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= -github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= -github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= +github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= +github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -442,8 +442,8 @@ k8s.io/mount-utils v0.32.2 h1:aDwp+ucWiVnDr/LpRg88/dsXf/vm6gI1VZkYH3+3+Vw= k8s.io/mount-utils v0.32.2/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE= -sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= +sigs.k8s.io/controller-runtime v0.20.2 h1:/439OZVxoEc02psi1h4QO3bHzTgu49bb347Xp4gW1pc= +sigs.k8s.io/controller-runtime v0.20.2/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= From aebdd14058b8596e1756c773674702e3bd6e9f53 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 16 Feb 2025 01:23:19 +0000 Subject: [PATCH 222/426] fix(deps): update module github.com/spf13/cobra to v1.9.0 (main) (#4478) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 63f9c77669..e7e4c00999 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.5 github.com/spf13/afero v1.12.0 - github.com/spf13/cobra v1.8.1 + github.com/spf13/cobra v1.9.0 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v0.119.0 go.opentelemetry.io/collector/confmap v1.25.0 @@ -97,7 +97,7 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/shirou/gopsutil/v4 v4.24.12 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/pflag v1.0.6 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect diff --git a/go.sum b/go.sum index b704fc075c..b0c01655fc 100644 --- a/go.sum +++ b/go.sum @@ -10,7 +10,7 @@ github.com/container-storage-interface/spec v1.11.0 h1:H/YKTOeUZwHtyPOr9raR+HgFm github.com/container-storage-interface/spec v1.11.0/go.mod h1:DtUvaQszPml1YJfIK7c00mlv6/g4wNMLanLgiUbKFRI= github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8= github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -172,10 +172,10 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/cobra v1.9.0 h1:Py5fIuq/lJsRYxcxfOtsJqpmwJWCMOUy2tMJYV8TNHE= +github.com/spf13/cobra v1.9.0/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= From e0bdde79cf9ba0361fb2ad576469599d7ec81828 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 05:52:44 +0000 Subject: [PATCH 223/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1739751568 (main) (#4479) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8c63391b0a..02feef922f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739467664@sha256:e01d3109d55b6cc4e5a58911e979f91ae29f30e50124563d277a6f29be08397f AS base -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1739449058@sha256:4495380286c97b9c2635b0b5d6f227bbd9003628be8383a37ff99984eefa42ed AS dependency +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1739751568@sha256:d342aa80781bf41c4c73485c41d8f1e2dbc40ee491633d9cafe787c361dd44ff AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 0e5e7b0f35078f19a47500e910d5887b6292aec1 Mon Sep 17 00:00:00 2001 From: barblin Date: Mon, 17 Feb 2025 10:12:20 +0100 Subject: [PATCH 224/426] feat: sbom dependency relationship transparency. ref: QSP-15724 (#4424) --- .github/actions/build-image/action.yaml | 4 ++++ .github/workflows/release.yaml | 5 +++++ .gitignore | 1 + Dockerfile | 2 ++ Makefile | 1 + hack/build/build_image.sh | 2 ++ hack/make/prerequisites.mk | 6 ++++++ hack/make/release/release.mk | 3 +++ 8 files changed, 24 insertions(+) create mode 100644 hack/make/release/release.mk diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 782d5b8e5b..b664a7ed67 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -30,6 +30,10 @@ runs: shell: bash run: | hack/build/ci/third-party-licenses.sh + - name: Create empty SBOM file + shell: bash + run: | + touch dynatrace-operator-bin-sbom.cdx.json - name: Build target uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 with: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9b91e28ee8..b79da54587 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -44,6 +44,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Prepare SBOM + id: sbom + run: | + make release/gen-sbom - name: Build image uses: ./.github/actions/build-image with: @@ -238,6 +242,7 @@ jobs: format: 'cyclonedx' output: 'result.json' skip-dirs: '/usr/share/dynatrace-operator/third_party_licenses' + skip-files: '/usr/local/bin/dynatrace-operator' - name: Upload sbom to ${{matrix.registry}} uses: ./.github/actions/upload-sbom with: diff --git a/.gitignore b/.gitignore index 603b886772..9be34577e4 100644 --- a/.gitignore +++ b/.gitignore @@ -106,3 +106,4 @@ test/testdata/secrets/* local/ permissions.md +dynatrace-operator-bin-sbom.cdx.json diff --git a/Dockerfile b/Dockerfile index 02feef922f..ce0813011a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,6 +57,8 @@ COPY --from=registry.k8s.io/sig-storage/livenessprobe:v2.15.0@sha256:2c5f9dc4ea5 COPY ./third_party_licenses /usr/share/dynatrace-operator/third_party_licenses COPY LICENSE /licenses/ +COPY ./dynatrace-operator-bin-sbom.cdx.json ./dynatrace-operator-bin-sbom.cdx.json + # custom scripts COPY hack/build/bin /usr/local/bin diff --git a/Makefile b/Makefile index 640f2c6efc..4ac1a8744e 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,7 @@ SHELL ?= bash -include hack/make/helm/*.mk -include hack/make/manifests/*.mk -include hack/make/tests/*.mk +-include hack/make/release/*.mk ## Builds the operator image and pushes it to quay with a snapshot tag build: images/build/push diff --git a/hack/build/build_image.sh b/hack/build/build_image.sh index 71dfcdf5e8..fdfe2091d4 100755 --- a/hack/build/build_image.sh +++ b/hack/build/build_image.sh @@ -21,6 +21,7 @@ out_image="${image}:${tag}" # directory required by docker copy command mkdir -p third_party_licenses +touch dynatrace-operator-bin-sbom.cdx.json if ! command -v docker 2>/dev/null; then CONTAINER_CMD=podman @@ -41,3 +42,4 @@ ${CONTAINER_CMD} build "${OPERATOR_BUILD_PLATFORM}" . -f ./Dockerfile -t "${out_ --label "quay.expires-after=14d" rm -rf third_party_licenses +rm dynatrace-operator-bin-sbom.cdx.json diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 0ee8b9e203..2ef3886596 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -16,6 +16,8 @@ markdownlint_cli_version=v0.44.0 helmunittest_version=v0.7.2 # renovate depName=github.com/princjef/gomarkdoc gomarkdoc_version=v1.1.0 +# renovate depName=github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod +cyclonedx_gomod_version=v1.9.0 # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) @@ -81,3 +83,7 @@ prerequisites/gomarkdoc: ## Install python dependencies prerequisites/python: python3 -m venv local/.venv && source local/.venv/bin/activate && pip3 install -r hack/requirements.txt + +## Install 'cyclonedx-gomod' if it is missing +prerequisites/cyclonedx-gomod: + go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@$(cyclonedx_gomod_version) diff --git a/hack/make/release/release.mk b/hack/make/release/release.mk new file mode 100644 index 0000000000..5e6abf3a6c --- /dev/null +++ b/hack/make/release/release.mk @@ -0,0 +1,3 @@ +## Generates SBOM of binary +release/gen-sbom: prerequisites/cyclonedx-gomod + cyclonedx-gomod app -licenses -assert-licenses -json -main cmd/ -output dynatrace-operator-bin-sbom.cdx.json From 73fb339ad9873e2ef29d93608a017f645d64fda8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:19:42 +0000 Subject: [PATCH 225/426] chore(deps): update golangci/golangci-lint-action action to v6.5.0 (main) (#4477) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Marcell Sevcsik --- .github/workflows/ci.yaml | 2 +- .golangci.yml | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ba85f90320..d4c8684a55 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,7 +86,7 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint - uses: golangci/golangci-lint-action@818ec4d51a1feacefc42ff1b3ec25d4962690f39 # v6.4.1 + uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0 with: # renovate depName=github.com/golangci/golangci-lint version: v1.64.5 diff --git a/.golangci.yml b/.golangci.yml index 84bc92a34c..f640ff5373 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -298,10 +298,6 @@ linters: # - tagliatelle # Checks the struct tags. # - testpackage # Linter that makes you use a separate _test package. - -service: - golangci-lint-version: 1.55.x # use the fixed version to not introduce new linters unexpectedly - issues: exclude-dirs: - pkg/api/v1alpha1/dynakube # legacy version, should not be changed From 12ef55bfd922a742d7afdaf68190c6eb6540ec96 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Mon, 17 Feb 2025 10:29:06 +0100 Subject: [PATCH 226/426] Improve warnings for missing Kubernetes-monitoring and custom image without CSI driver (#4457) --- pkg/api/validation/dynakube/extensions.go | 4 +-- .../validation/dynakube/extensions_test.go | 7 ++-- pkg/api/validation/dynakube/kspm.go | 10 +++--- pkg/api/validation/dynakube/kspm_test.go | 25 +++++++++---- pkg/api/validation/dynakube/logmonitoring.go | 8 ++--- .../validation/dynakube/logmonitoring_test.go | 6 ++-- pkg/api/validation/dynakube/oneagent.go | 12 +++++-- pkg/api/validation/dynakube/oneagent_test.go | 35 ++++++++++++++++--- pkg/api/validation/dynakube/validation.go | 6 ++-- 9 files changed, 80 insertions(+), 33 deletions(-) diff --git a/pkg/api/validation/dynakube/extensions.go b/pkg/api/validation/dynakube/extensions.go index 730b6de61e..54bd30e255 100644 --- a/pkg/api/validation/dynakube/extensions.go +++ b/pkg/api/validation/dynakube/extensions.go @@ -7,12 +7,12 @@ import ( ) const ( - errorExtensionsWithoutK8SMonitoring = "The Dynakube's specification enables extensions without an ActiveGate which has Kubernetes monitoring enabled. This is not feasible, as the cluster will not be visible in Dynatrace without the Kubernetes monitoring feature." + warningExtensionsWithoutK8SMonitoring = "The Dynakube is configured with extensions without an ActiveGate with `kubernetes-monitoring` enabled or the `automatic-kubernetes-monitoring` feature flag. You need to ensure that Kubernetes monitoring is setup for this cluster." ) func extensionsWithoutK8SMonitoring(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { if dk.IsExtensionsEnabled() && (!dk.ActiveGate().IsKubernetesMonitoringEnabled() || !dk.FeatureAutomaticKubernetesApiMonitoring()) { - return errorExtensionsWithoutK8SMonitoring + return warningExtensionsWithoutK8SMonitoring } return "" diff --git a/pkg/api/validation/dynakube/extensions_test.go b/pkg/api/validation/dynakube/extensions_test.go index a07a411309..03c5760477 100644 --- a/pkg/api/validation/dynakube/extensions_test.go +++ b/pkg/api/validation/dynakube/extensions_test.go @@ -22,8 +22,7 @@ func TestExtensionsWithoutK8SMonitoring(t *testing.T) { assertAllowed(t, dk) }) t.Run("error if extensions are enabled without activegate with k8s-monitoring", func(t *testing.T) { - assertDenied(t, - []string{errorExtensionsWithoutK8SMonitoring}, + assertAllowedWithWarnings(t, 2, createStandaloneExtensionsDynakube(testDynakubeName, testApiUrl)) }) t.Run("error if extensions are enabled with activegate with k8s-monitoring but automatic Kuberenetes API monitoring is disabled", func(t *testing.T) { @@ -36,14 +35,14 @@ func TestExtensionsWithoutK8SMonitoring(t *testing.T) { activegate.KubeMonCapability.DisplayName, }, } - assertDenied(t, []string{errorExtensionsWithoutK8SMonitoring}, dk) + assertAllowedWithWarnings(t, 2, dk) }) t.Run("error if extensions are enabled but automatic Kuberenetes API monitoring is disabled and without activgate k8s-monitoring", func(t *testing.T) { dk := createStandaloneExtensionsDynakube(testDynakubeName, testApiUrl) dk.ObjectMeta.Annotations = map[string]string{ dynakube.AnnotationFeatureAutomaticK8sApiMonitoring: "false", } - assertDenied(t, []string{errorExtensionsWithoutK8SMonitoring}, dk) + assertAllowedWithWarnings(t, 2, dk) }) } diff --git a/pkg/api/validation/dynakube/kspm.go b/pkg/api/validation/dynakube/kspm.go index 1dc653a765..2a005f339a 100644 --- a/pkg/api/validation/dynakube/kspm.go +++ b/pkg/api/validation/dynakube/kspm.go @@ -7,9 +7,9 @@ import ( ) const ( - errorTooManyAGReplicas = `The Dynakube's specification specifies KSPM, but has more than one ActiveGate replica. Only one ActiveGate replica is allowed in combination with KSPM.` - errorKSPMMissingKubemon = `The Dynakube's specification specifies KSPM, but "kubernetes-monitoring" is not enabled on the Activegate.` - errorKSPMMissingImage = `The Dynakube's specification specifies KSPM, but no image repository/tag is configured.` + errorTooManyAGReplicas = `The Dynakube's specification specifies KSPM, but has more than one ActiveGate replica. Only one ActiveGate replica is allowed in combination with KSPM.` + warningKSPMMissingKubemon = "The Dynakube is configured with KSPM without an ActiveGate with `kubernetes-monitoring` enabled or the `automatic-kubernetes-monitoring` feature flag. You need to ensure that Kubernetes monitoring is setup for this cluster." + errorKSPMMissingImage = `The Dynakube's specification specifies KSPM, but no image repository/tag is configured.` ) func tooManyAGReplicas(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { @@ -20,9 +20,9 @@ func tooManyAGReplicas(_ context.Context, _ *Validator, dk *dynakube.DynaKube) s return "" } -func missingKSPMDependency(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { +func kspmWithoutK8SMonitoring(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { if dk.KSPM().IsEnabled() && (!dk.ActiveGate().IsKubernetesMonitoringEnabled() || !dk.FeatureAutomaticKubernetesApiMonitoring()) { - return errorKSPMMissingKubemon + return warningKSPMMissingKubemon } return "" diff --git a/pkg/api/validation/dynakube/kspm_test.go b/pkg/api/validation/dynakube/kspm_test.go index df4ee9c2fe..39810516fe 100644 --- a/pkg/api/validation/dynakube/kspm_test.go +++ b/pkg/api/validation/dynakube/kspm_test.go @@ -91,21 +91,27 @@ func TestMissingKSPMDependency(t *testing.T) { }) t.Run("missing kubemon but kspm enabled", func(t *testing.T) { - assertDenied(t, - []string{errorKSPMMissingKubemon}, + assertAllowedWithWarnings(t, 1, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, Kspm: &kspm.Spec{}, ActiveGate: activegate.Spec{}, + Templates: dynakube.TemplatesSpec{ + KspmNodeConfigurationCollector: kspm.NodeConfigurationCollectorSpec{ + ImageRef: image.Ref{ + Repository: "repo/image", + Tag: "version", + }, + }, + }, }, }) }) t.Run("both kspm and kubemon enabled, automatic k8s monitoring disabled", func(t *testing.T) { - assertDenied(t, - []string{errorKSPMMissingKubemon}, + assertAllowedWithWarnings(t, 2, &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Name: testName, @@ -135,8 +141,7 @@ func TestMissingKSPMDependency(t *testing.T) { }) t.Run("missing kubemon, automatic k8s monitoring disabled, but kspm enabled", func(t *testing.T) { - assertDenied(t, - []string{errorKSPMMissingKubemon}, + assertAllowedWithWarnings(t, 1, &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Name: testName, @@ -149,6 +154,14 @@ func TestMissingKSPMDependency(t *testing.T) { APIURL: testApiUrl, Kspm: &kspm.Spec{}, ActiveGate: activegate.Spec{}, + Templates: dynakube.TemplatesSpec{ + KspmNodeConfigurationCollector: kspm.NodeConfigurationCollectorSpec{ + ImageRef: image.Ref{ + Repository: "repo/image", + Tag: "version", + }, + }, + }, }, }) }) diff --git a/pkg/api/validation/dynakube/logmonitoring.go b/pkg/api/validation/dynakube/logmonitoring.go index e7fb0d0e28..1607668633 100644 --- a/pkg/api/validation/dynakube/logmonitoring.go +++ b/pkg/api/validation/dynakube/logmonitoring.go @@ -7,14 +7,14 @@ import ( ) const ( - warningLogMonitoringIgnoredTemplate = "The Dynakube's `spec.templates.logMonitoring` section is skipped as the `spec.oneagent` section is also configured." - errorLogMonitoringMissingImage = `The Dynakube's specification specifies standalone Log monitoring, but no image repository/tag is configured.` - errorLogMonitoringWithoutK8SMonitoring = "The Dynakube's specification specifies Log monitoring without an ActiveGate with kubernetes-monitoring enabled or the automatic-kubernetes-monitoring feature flag. This is not allowed as Kubernetes settings are needed for Log monitoring." + warningLogMonitoringIgnoredTemplate = "The Dynakube's `spec.templates.logMonitoring` section is skipped as the `spec.oneagent` section is also configured." + warningLogMonitoringWithoutK8SMonitoring = "The Dynakube is configured for Log monitoring without an ActiveGate with `kubernetes-monitoring` enabled or the `automatic-kubernetes-monitoring` feature flag. You need to ensure that Kubernetes monitoring is setup for this cluster." + errorLogMonitoringMissingImage = `The Dynakube's specification specifies standalone Log monitoring, but no image repository/tag is configured.` ) func logMonitoringWithoutK8SMonitoring(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { if dk.LogMonitoring().IsEnabled() && (!dk.ActiveGate().IsKubernetesMonitoringEnabled() || !dk.FeatureAutomaticKubernetesApiMonitoring()) { - return errorLogMonitoringWithoutK8SMonitoring + return warningLogMonitoringWithoutK8SMonitoring } return "" diff --git a/pkg/api/validation/dynakube/logmonitoring_test.go b/pkg/api/validation/dynakube/logmonitoring_test.go index b6ac286888..0abd6b1341 100644 --- a/pkg/api/validation/dynakube/logmonitoring_test.go +++ b/pkg/api/validation/dynakube/logmonitoring_test.go @@ -39,7 +39,7 @@ func TestLogMonitoringWithoutK8SMonitoring(t *testing.T) { LogMonitoring: &logmonitoring.Spec{}, }, } - assertDenied(t, []string{errorLogMonitoringWithoutK8SMonitoring}, dk) + assertAllowedWithWarnings(t, 1, dk) }) t.Run("error if logMonitoring is enabled with activegate with k8s-monitoring but automatic-kubernetes-monitoring disables", func(t *testing.T) { dk := &dynakube.DynaKube{ @@ -66,10 +66,10 @@ func TestLogMonitoringWithoutK8SMonitoring(t *testing.T) { }, }, } - assertDenied(t, []string{errorLogMonitoringWithoutK8SMonitoring}, dk) + assertAllowedWithWarnings(t, 2, dk) }) t.Run("error if logMonitoring is enabled without activegate with k8s-monitoring and automatic-kubernetes-monitoring disabled", func(t *testing.T) { - assertDenied(t, []string{errorLogMonitoringWithoutK8SMonitoring}, &dynakube.DynaKube{ + assertAllowedWithWarnings(t, 1, &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ dynakube.AnnotationFeatureAutomaticK8sApiMonitoring: "false", diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index dc77d9b94f..7aef8184aa 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -24,7 +24,7 @@ Use a nodeSelector to avoid this conflict. Conflicting DynaKubes: %s` errorVolumeStorageReadOnlyModeConflict = `The DynaKube specification specifies a read-only host file system while OneAgent has volume storage enabled.` - warningPublicImageWithWrongConfig = `Custom OneAgent image is only supported when CSI Driver is used.` + warningPublicImageWithWrongConfig = `You are using a custom OneAgent image without CSI driver. Only images from the tenant registry are supported."` warningOneAgentInstallerEnvVars = `The environment variables ONEAGENT_INSTALLER_SCRIPT_URL and ONEAGENT_INSTALLER_TOKEN are only relevant for an unsupported image type. Please ensure you are using a supported image.` @@ -128,7 +128,15 @@ func mapKeysToString(m map[string]bool, sep string) string { } func publicImageSetWithoutReadOnlyMode(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { - if !dk.OneAgent().IsReadOnlyOneAgentsMode() && dk.OneAgent().GetCustomImage() != "" { + if dk.OneAgent().GetCustomImage() != "" { + if dk.OneAgent().IsReadOnlyOneAgentsMode() { + return "" + } + + if dk.OneAgent().IsClassicFullStackMode() { + return "" + } + return warningPublicImageWithWrongConfig } diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index bfbd05a4b0..c730ce2223 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -478,14 +478,14 @@ func TestIsOneAgentVersionValid(t *testing.T) { } for _, validVersion := range validVersions { - dk.Spec.OneAgent.ClassicFullStack.Version = validVersion + dk.OneAgent().ClassicFullStack.Version = validVersion t.Run(fmt.Sprintf("OneAgent custom version %s is allowed", validVersion), func(t *testing.T) { assertAllowed(t, &dk) }) } for _, invalidVersion := range invalidVersions { - dk.Spec.OneAgent.ClassicFullStack.Version = invalidVersion + dk.OneAgent().ClassicFullStack.Version = invalidVersion t.Run(fmt.Sprintf("OneAgent custom version %s is not allowed", invalidVersion), func(t *testing.T) { assertDenied(t, []string{versionInvalidMessage}, &dk) }) @@ -510,7 +510,7 @@ func TestPublicImageSetWithReadOnlyMode(t *testing.T) { }) t.Run("allow dk with hostMon without csi and no custom image", func(t *testing.T) { setupDisabledCSIEnv(t) - assertAllowed(t, + assertAllowedWithoutWarnings(t, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ @@ -522,7 +522,7 @@ func TestPublicImageSetWithReadOnlyMode(t *testing.T) { }) }) t.Run("allow dk with hostMon with csi and custom image", func(t *testing.T) { - assertAllowed(t, &dynakube.DynaKube{ + assertAllowedWithoutWarnings(t, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, @@ -534,6 +534,33 @@ func TestPublicImageSetWithReadOnlyMode(t *testing.T) { }, }) }) + t.Run("allow dk with classicFullStack without csi and custom image", func(t *testing.T) { + setupDisabledCSIEnv(t) + assertAllowedWithoutWarnings(t, &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ + Image: "test/image/test-image:some-tag", + }, + }, + }, + }) + }) + t.Run("allow dk with classicFullStack with csi and custom image", func(t *testing.T) { + assertAllowedWithoutWarnings(t, &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{ + Image: "test/image/test-image:some-tag", + }, + }, + }, + }) + }) } func TestOneAgentArguments(t *testing.T) { diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 562c1965af..3a9a0db898 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -53,15 +53,12 @@ var ( extensionControllerImage, extensionControllerPVCStorageDevice, tooManyAGReplicas, - missingKSPMDependency, missingKSPMImage, missingLogMonitoringImage, - logMonitoringWithoutK8SMonitoring, emptyTelemetryServiceProtocolsList, unknownTelemetryServiceProtocols, duplicatedTelemetryServiceProtocols, invalidTelemetryServiceName, - extensionsWithoutK8SMonitoring, } validatorWarningFuncs = []validatorFunc{ missingActiveGateMemoryLimit, @@ -71,6 +68,9 @@ var ( ignoredLogMonitoringTemplate, conflictingApiUrlForExtensions, publicImageSetWithoutReadOnlyMode, + logMonitoringWithoutK8SMonitoring, + kspmWithoutK8SMonitoring, + extensionsWithoutK8SMonitoring, } updateValidatorErrorFuncs = []updateValidatorFunc{ IsMutatedApiUrl, From 1177c8bc09137d94dcf7e84e9081a6b4ad52cc25 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 15:51:09 +0000 Subject: [PATCH 227/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1739776878 (main) (#4482) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ce0813011a..8239171837 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739467664@sha256:e01d3109d55b6cc4e5a58911e979f91ae29f30e50124563d277a6f29be08397f AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739776878@sha256:d115f8aad9c4ae7ee21ae75bbcb3dc2c5dbf9b57bf6dad6dcb5aac5c02003bde AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1739751568@sha256:d342aa80781bf41c4c73485c41d8f1e2dbc40ee491633d9cafe787c361dd44ff AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From 455f6d75d5c6d93c83f3c0be1a1520bae740ecb3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 18:19:53 +0000 Subject: [PATCH 228/426] fix(deps): update module github.com/spf13/cobra to v1.9.1 (main) (#4480) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e7e4c00999..2998799a10 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.5 github.com/spf13/afero v1.12.0 - github.com/spf13/cobra v1.9.0 + github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v0.119.0 go.opentelemetry.io/collector/confmap v1.25.0 diff --git a/go.sum b/go.sum index b0c01655fc..026b9d7a73 100644 --- a/go.sum +++ b/go.sum @@ -172,8 +172,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= -github.com/spf13/cobra v1.9.0 h1:Py5fIuq/lJsRYxcxfOtsJqpmwJWCMOUy2tMJYV8TNHE= -github.com/spf13/cobra v1.9.0/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 957a93cadc207a45652a3d92f274129831af0294 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2025 06:45:19 +0000 Subject: [PATCH 229/426] fix(deps): update module go.opentelemetry.io/collector/confmap to v1.26.0 (main) (#4485) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2998799a10..5f7196bbf4 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v0.119.0 - go.opentelemetry.io/collector/confmap v1.25.0 + go.opentelemetry.io/collector/confmap v1.26.0 go.opentelemetry.io/collector/otelcol v0.119.0 go.opentelemetry.io/collector/pipeline v0.119.0 go.opentelemetry.io/collector/service v0.119.0 diff --git a/go.sum b/go.sum index 026b9d7a73..a5b99a3f26 100644 --- a/go.sum +++ b/go.sum @@ -228,8 +228,8 @@ go.opentelemetry.io/collector/config/configtelemetry v0.119.0 h1:gAgMUEVXZKgpASx go.opentelemetry.io/collector/config/configtelemetry v0.119.0/go.mod h1:SlBEwQg0qly75rXZ6W1Ig8jN25KBVBkFIIAUI1GiAAE= go.opentelemetry.io/collector/config/configtls v1.25.0 h1:x915Us8mhYWGB025LBMH8LT9ZPdvg2WKAyCQ7IDUSfw= go.opentelemetry.io/collector/config/configtls v1.25.0/go.mod h1:jE4WbJE12AltJ3BZU1R0GnYI8D14bTqbTq4yuaTHdms= -go.opentelemetry.io/collector/confmap v1.25.0 h1:dLqd6hF4JqcDHl5GWWhc2jXsHs3hkq3KPvU/2Nw5aN4= -go.opentelemetry.io/collector/confmap v1.25.0/go.mod h1:Rrhs+MWoaP6AswZp+ReQ2VO9dfOfcUjdjiSHBsG+nec= +go.opentelemetry.io/collector/confmap v1.26.0 h1:+EVk0RaCBHs+7dYTwawd5n5tJiiUtErIy3YS3NIFP8o= +go.opentelemetry.io/collector/confmap v1.26.0/go.mod h1:tmOa6iw3FJsEgfBHKALqvcdfRtf71JZGor0wSM5MoH8= go.opentelemetry.io/collector/connector v0.119.0 h1:TWEVa2Iu+YOW/BuqNAoX0iesv4ygocb9v6GKtZEGsSw= go.opentelemetry.io/collector/connector v0.119.0/go.mod h1:4p/m2G2acL03RjhdeTJpo6afHFnfBU8E+eUxyrz7qd4= go.opentelemetry.io/collector/connector/connectortest v0.119.0 h1:jfkxP4jrd+CkyM0SnOrwiSiOW0xyahsyUjWqMwVBbBI= From dfa757a88b71dcb251d4c44792aa44c61512cefd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2025 11:14:29 +0000 Subject: [PATCH 230/426] fix(deps): update module go.opentelemetry.io/collector/otelcol to v0.120.0 (main) (#4486) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 74 +++++++++++----------- go.sum | 192 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 136 insertions(+), 130 deletions(-) diff --git a/go.mod b/go.mod index 5f7196bbf4..4eb7e2d925 100644 --- a/go.mod +++ b/go.mod @@ -16,11 +16,11 @@ require ( github.com/spf13/afero v1.12.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 - go.opentelemetry.io/collector/component v0.119.0 + go.opentelemetry.io/collector/component v0.120.0 go.opentelemetry.io/collector/confmap v1.26.0 - go.opentelemetry.io/collector/otelcol v0.119.0 - go.opentelemetry.io/collector/pipeline v0.119.0 - go.opentelemetry.io/collector/service v0.119.0 + go.opentelemetry.io/collector/otelcol v0.120.0 + go.opentelemetry.io/collector/pipeline v0.120.0 + go.opentelemetry.io/collector/service v0.120.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.23.0 @@ -50,7 +50,7 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect - github.com/ebitengine/purego v0.8.1 // indirect + github.com/ebitengine/purego v0.8.2 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect @@ -95,7 +95,7 @@ require ( github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/shirou/gopsutil/v4 v4.24.12 // indirect + github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/stretchr/objx v0.5.2 // indirect @@ -106,35 +106,37 @@ require ( github.com/x448/float16 v0.8.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/collector/component/componentstatus v0.119.0 // indirect - go.opentelemetry.io/collector/component/componenttest v0.119.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.119.0 // indirect - go.opentelemetry.io/collector/connector v0.119.0 // indirect - go.opentelemetry.io/collector/connector/connectortest v0.119.0 // indirect - go.opentelemetry.io/collector/connector/xconnector v0.119.0 // indirect - go.opentelemetry.io/collector/consumer v1.25.0 // indirect - go.opentelemetry.io/collector/consumer/consumererror v0.119.0 // indirect - go.opentelemetry.io/collector/consumer/consumertest v0.119.0 // indirect - go.opentelemetry.io/collector/consumer/xconsumer v0.119.0 // indirect - go.opentelemetry.io/collector/exporter v0.119.0 // indirect - go.opentelemetry.io/collector/exporter/exportertest v0.119.0 // indirect - go.opentelemetry.io/collector/exporter/xexporter v0.119.0 // indirect - go.opentelemetry.io/collector/extension v0.119.0 // indirect - go.opentelemetry.io/collector/extension/extensioncapabilities v0.119.0 // indirect - go.opentelemetry.io/collector/extension/extensiontest v0.119.0 // indirect - go.opentelemetry.io/collector/featuregate v1.25.0 // indirect - go.opentelemetry.io/collector/internal/fanoutconsumer v0.119.0 // indirect - go.opentelemetry.io/collector/pdata v1.25.0 // indirect - go.opentelemetry.io/collector/pdata/pprofile v0.119.0 // indirect - go.opentelemetry.io/collector/pdata/testdata v0.119.0 // indirect - go.opentelemetry.io/collector/pipeline/xpipeline v0.119.0 // indirect - go.opentelemetry.io/collector/processor v0.119.0 // indirect - go.opentelemetry.io/collector/processor/processortest v0.119.0 // indirect - go.opentelemetry.io/collector/processor/xprocessor v0.119.0 // indirect - go.opentelemetry.io/collector/receiver v0.119.0 // indirect - go.opentelemetry.io/collector/receiver/receivertest v0.119.0 // indirect - go.opentelemetry.io/collector/receiver/xreceiver v0.119.0 // indirect - go.opentelemetry.io/collector/semconv v0.119.0 // indirect + go.opentelemetry.io/collector/component/componentstatus v0.120.0 // indirect + go.opentelemetry.io/collector/component/componenttest v0.120.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.120.0 // indirect + go.opentelemetry.io/collector/confmap/xconfmap v0.120.0 // indirect + go.opentelemetry.io/collector/connector v0.120.0 // indirect + go.opentelemetry.io/collector/connector/connectortest v0.120.0 // indirect + go.opentelemetry.io/collector/connector/xconnector v0.120.0 // indirect + go.opentelemetry.io/collector/consumer v1.26.0 // indirect + go.opentelemetry.io/collector/consumer/consumererror v0.120.0 // indirect + go.opentelemetry.io/collector/consumer/consumertest v0.120.0 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.120.0 // indirect + go.opentelemetry.io/collector/exporter v0.120.0 // indirect + go.opentelemetry.io/collector/exporter/exportertest v0.120.0 // indirect + go.opentelemetry.io/collector/exporter/xexporter v0.120.0 // indirect + go.opentelemetry.io/collector/extension v0.120.0 // indirect + go.opentelemetry.io/collector/extension/extensioncapabilities v0.120.0 // indirect + go.opentelemetry.io/collector/extension/extensiontest v0.120.0 // indirect + go.opentelemetry.io/collector/featuregate v1.26.0 // indirect + go.opentelemetry.io/collector/internal/fanoutconsumer v0.120.0 // indirect + go.opentelemetry.io/collector/internal/telemetry v0.120.0 // indirect + go.opentelemetry.io/collector/pdata v1.26.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.120.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.120.0 // indirect + go.opentelemetry.io/collector/pipeline/xpipeline v0.120.0 // indirect + go.opentelemetry.io/collector/processor v0.120.0 // indirect + go.opentelemetry.io/collector/processor/processortest v0.120.0 // indirect + go.opentelemetry.io/collector/processor/xprocessor v0.120.0 // indirect + go.opentelemetry.io/collector/receiver v0.120.0 // indirect + go.opentelemetry.io/collector/receiver/receivertest v0.120.0 // indirect + go.opentelemetry.io/collector/receiver/xreceiver v0.120.0 // indirect + go.opentelemetry.io/collector/semconv v0.120.0 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect go.opentelemetry.io/contrib/config v0.14.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect @@ -166,7 +168,7 @@ require ( gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/protobuf v1.36.4 // indirect + google.golang.org/protobuf v1.36.5 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index a5b99a3f26..ce81b5c15e 100644 --- a/go.sum +++ b/go.sum @@ -22,8 +22,8 @@ github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBi github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= -github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE= -github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= +github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= @@ -166,8 +166,8 @@ github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWN github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shirou/gopsutil/v4 v4.24.12 h1:qvePBOk20e0IKA1QXrIIU+jmk+zEiYVVx06WjBRlZo4= -github.com/shirou/gopsutil/v4 v4.24.12/go.mod h1:DCtMPAad2XceTeIAbGyVfycbYQNBGk2P8cvDi7/VN9o= +github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= +github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= @@ -204,96 +204,100 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/collector v0.119.0 h1:n8ltRLteaUKjyY3E+3JbiaPG4gwL2pjNIcUvXmRA0Ko= -go.opentelemetry.io/collector v0.119.0/go.mod h1:w+qO3hp/mLR2wL4v06MWonGcj4p2/kPSNcU3R7+06p8= -go.opentelemetry.io/collector/client v1.25.0 h1:7IS+b3Xm2ymgmQj9UbnZmVF4jIw6F7tQjJP7lFc+GoM= -go.opentelemetry.io/collector/client v1.25.0/go.mod h1:IPyOnO7K0ztuZOV1i+WXShvq4tpbLp45tTDdIDvlZvM= -go.opentelemetry.io/collector/component v0.119.0 h1:ZVp9myF1Bc4BLa1V4C15Jy/VpqKPPhvbxpe9pP1mPMc= -go.opentelemetry.io/collector/component v0.119.0/go.mod h1:wtuWxFl+Ky9E/5+t2FwHoLyADDiBFFDdx8fN3fEs0n8= -go.opentelemetry.io/collector/component/componentstatus v0.119.0 h1:H8isEInGaWhnDfuG1Ax663dlsPgF4aM20sgraM6HmSI= -go.opentelemetry.io/collector/component/componentstatus v0.119.0/go.mod h1:Hr7scHUFPhyT32IkzKq06cdhRH9jMKvnKbDVYRUEnqE= -go.opentelemetry.io/collector/component/componenttest v0.119.0 h1:nVlBmKSu56zO/qCcNgDYCQsRoWAL+NPkrkIPAbapdQM= -go.opentelemetry.io/collector/component/componenttest v0.119.0/go.mod h1:H6KVzLkNhB/deEijLcq91Kjgs9Oshx2ZsFAwaMcuTLs= -go.opentelemetry.io/collector/config/configauth v0.119.0 h1:w/Ln2l6TSgadtRLEZ7mlmOsW/6Q4ITIrjwxR7Tbnfzg= -go.opentelemetry.io/collector/config/configauth v0.119.0/go.mod h1:B3DFUBTSGdwAjxbWtY/tQ+03QwousCMLM9s26+Kb9Xw= -go.opentelemetry.io/collector/config/configcompression v1.25.0 h1:iYeeYiKbTQu9lqWDpszeAc5gRkWBImDrBVe7u5gnoqw= -go.opentelemetry.io/collector/config/configcompression v1.25.0/go.mod h1:LvYG00tbPTv0NOLoZN0wXq1F5thcxvukO8INq7xyfWU= -go.opentelemetry.io/collector/config/confighttp v0.119.0 h1:slt4Msm2D4qdu2Nvy2E+ccgrAS0T64zl6eTuWiiCxGg= -go.opentelemetry.io/collector/config/confighttp v0.119.0/go.mod h1:Tnfo1UP1OZPVfvYriaP187aS3FHfwVXNLjBZ799AUFk= -go.opentelemetry.io/collector/config/configopaque v1.25.0 h1:raFi+CC8Sn4KzKCPhtnnrnkDQ0eFzJCN8xJpQh9d1sU= -go.opentelemetry.io/collector/config/configopaque v1.25.0/go.mod h1:sW0t0iI/VfRL9VYX7Ik6XzVgPcR+Y5kejTLsYcMyDWs= -go.opentelemetry.io/collector/config/configretry v1.25.0 h1:PelzRkTJ9zGxwdJha7pPtvR91GrgL/OzkY/MwyXYRUE= -go.opentelemetry.io/collector/config/configretry v1.25.0/go.mod h1:cleBc9I0DIWpTiiHfu9v83FUaCTqcPXmebpLxjEIqro= -go.opentelemetry.io/collector/config/configtelemetry v0.119.0 h1:gAgMUEVXZKgpASxOrhS55DyA/aYatq0U6gitZI8MLXw= -go.opentelemetry.io/collector/config/configtelemetry v0.119.0/go.mod h1:SlBEwQg0qly75rXZ6W1Ig8jN25KBVBkFIIAUI1GiAAE= -go.opentelemetry.io/collector/config/configtls v1.25.0 h1:x915Us8mhYWGB025LBMH8LT9ZPdvg2WKAyCQ7IDUSfw= -go.opentelemetry.io/collector/config/configtls v1.25.0/go.mod h1:jE4WbJE12AltJ3BZU1R0GnYI8D14bTqbTq4yuaTHdms= +go.opentelemetry.io/collector v0.120.0 h1:RmEFc4rPB0wg7fEDY0k8OenXznAtsVGzgAkjTAF44WQ= +go.opentelemetry.io/collector v0.120.0/go.mod h1:uNDaRieHl04oQCvGFY4KzpDRqejgMNbea0u2+vk7P3k= +go.opentelemetry.io/collector/client v1.26.0 h1:m/rXHfGzHx4RcETswnm5Y2r1uPv6q0lY+M4btNxbLnE= +go.opentelemetry.io/collector/client v1.26.0/go.mod h1:H7dkvh+4BbglV1QiyI+AD/aWuqJ3iE5oiYr5oDKtBLw= +go.opentelemetry.io/collector/component v0.120.0 h1:YHEQ6NuBI6FQHKW24OwrNg2IJ0EUIg4RIuwV5YQ6PSI= +go.opentelemetry.io/collector/component v0.120.0/go.mod h1:Ya5O+5NWG9XdhJPnOVhKtBrNXHN3hweQbB98HH4KPNU= +go.opentelemetry.io/collector/component/componentstatus v0.120.0 h1:hzKjI9+AIl8A/saAARb47JqabWsge0kMp8NSPNiCNOQ= +go.opentelemetry.io/collector/component/componentstatus v0.120.0/go.mod h1:kbuAEddxvcyjGLXGmys3nckAj4jTGC0IqDIEXAOr3Ag= +go.opentelemetry.io/collector/component/componenttest v0.120.0 h1:vKX85d3lpxj/RoiFQNvmIpX9lOS80FY5svzOYUyeYX0= +go.opentelemetry.io/collector/component/componenttest v0.120.0/go.mod h1:QDLboWF2akEqAGyvje8Hc7GfXcrZvQ5FhmlWvD5SkzY= +go.opentelemetry.io/collector/config/configauth v0.120.0 h1:5yJd4fYAxdbMnuEkTyfnKtZKEqNJVPyt+roDYDPdWIk= +go.opentelemetry.io/collector/config/configauth v0.120.0/go.mod h1:n1rj/cJ+wi+4Cr7q9Z87sF2izYown4/ADDiPZMdLd6g= +go.opentelemetry.io/collector/config/configcompression v1.26.0 h1:90J6ePTWwZbN6QRPawuGOmJG5H84KB4DzHdbd/kUZM4= +go.opentelemetry.io/collector/config/configcompression v1.26.0/go.mod h1:QwbNpaOl6Me+wd0EdFuEJg0Cc+WR42HNjJtdq4TwE6w= +go.opentelemetry.io/collector/config/confighttp v0.120.0 h1:ZOA59E7VsYSmMLGkNke6uOGq3yYK1hJ9OUa/swNeVtI= +go.opentelemetry.io/collector/config/confighttp v0.120.0/go.mod h1:9GpKCdtmypk+DpuoJlAyV5LppiWazFahuJby+L5Rz2Q= +go.opentelemetry.io/collector/config/configopaque v1.26.0 h1:lM9+fDvr5RWkTupoq8xi7qt0kvXoUX7UFN8D7Wb4zRI= +go.opentelemetry.io/collector/config/configopaque v1.26.0/go.mod h1:GYQiC8IejBcwE8z0O4DwbBR/Hf6U7d8DTf+cszyqwFs= +go.opentelemetry.io/collector/config/configretry v1.26.0 h1:DGuaZYkGXCr+Wd6+D65xZv7E9z/nyt/F//XbC4B/7M4= +go.opentelemetry.io/collector/config/configretry v1.26.0/go.mod h1:8gzFQ0qzKLYvzP2sNPwsB9gwzKSEls649yANmt/d6yE= +go.opentelemetry.io/collector/config/configtelemetry v0.120.0 h1:YPXMpfMd9PhngFXiwi3Lmze/Rs0nGS5wQOX16Elev+8= +go.opentelemetry.io/collector/config/configtelemetry v0.120.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= +go.opentelemetry.io/collector/config/configtls v1.26.0 h1:aBNqX3Q3WpO20SG/CF6sKxD1rJllKom7gCOW6SeGcq4= +go.opentelemetry.io/collector/config/configtls v1.26.0/go.mod h1:ppoLSWiwovldy4R9KCs6+XCWhvvBaF8eBhkUL460lxw= go.opentelemetry.io/collector/confmap v1.26.0 h1:+EVk0RaCBHs+7dYTwawd5n5tJiiUtErIy3YS3NIFP8o= go.opentelemetry.io/collector/confmap v1.26.0/go.mod h1:tmOa6iw3FJsEgfBHKALqvcdfRtf71JZGor0wSM5MoH8= -go.opentelemetry.io/collector/connector v0.119.0 h1:TWEVa2Iu+YOW/BuqNAoX0iesv4ygocb9v6GKtZEGsSw= -go.opentelemetry.io/collector/connector v0.119.0/go.mod h1:4p/m2G2acL03RjhdeTJpo6afHFnfBU8E+eUxyrz7qd4= -go.opentelemetry.io/collector/connector/connectortest v0.119.0 h1:jfkxP4jrd+CkyM0SnOrwiSiOW0xyahsyUjWqMwVBbBI= -go.opentelemetry.io/collector/connector/connectortest v0.119.0/go.mod h1:W0jLFVqxpWE+Rz6+JoYY6wN6f41862n8PIr+igaECcI= -go.opentelemetry.io/collector/connector/xconnector v0.119.0 h1:00iGiSVJKp82WjWsyPCMfxmyTynGzNkr7dSrb4oMuyQ= -go.opentelemetry.io/collector/connector/xconnector v0.119.0/go.mod h1:8MPaHhN64/METupujKMxuX+2eixLduUHXxMqP4JUUpc= -go.opentelemetry.io/collector/consumer v1.25.0 h1:qCJa7Hh7lY3vYWgwcEgTGSjjITLCn+BSsya8LxjpoPY= -go.opentelemetry.io/collector/consumer v1.25.0/go.mod h1:ToBfr3BexnhHuxC8/XszkKP/YtkgsGd0yjFMQXNwvT8= -go.opentelemetry.io/collector/consumer/consumererror v0.119.0 h1:M6QXK3KLWnNLlUWOBgz+WQI//W9M8r9qVGWUA3mc5LM= -go.opentelemetry.io/collector/consumer/consumererror v0.119.0/go.mod h1:UNnNkr+ZQJhAMNE5v1n86lXbJrSYb+1ePcI98gV6xvo= -go.opentelemetry.io/collector/consumer/consumertest v0.119.0 h1:hZxdlvfOBzy/rl6mIyrannM4M+7zyv7C947f6W9Leio= -go.opentelemetry.io/collector/consumer/consumertest v0.119.0/go.mod h1:pfXxA2CCwbieymnX0ShZuHjwrWzmxJapsb8ZiSqojVc= -go.opentelemetry.io/collector/consumer/xconsumer v0.119.0 h1:s9DrRdb1kYXy2psr34zGG5sI+F4GRBIhjvEsh7C7FtE= -go.opentelemetry.io/collector/consumer/xconsumer v0.119.0/go.mod h1:3fvk+0hd4WMv76+oUUNah0rQ35dZzH3zyMMCg9MtsuY= -go.opentelemetry.io/collector/exporter v0.119.0 h1:eVHmkeB5HQY/FcoP62l7O4Q0cAZ97LwLhZiAQoQeBtU= -go.opentelemetry.io/collector/exporter v0.119.0/go.mod h1:xMF9mT01tXHX2NjfMRV8o9YyhPBZOR4Wt+srkTy1thM= -go.opentelemetry.io/collector/exporter/exportertest v0.119.0 h1:saABJIiyYyqWEBvGe2VVf5rMMpHdwB83nD6feNZ33nA= -go.opentelemetry.io/collector/exporter/exportertest v0.119.0/go.mod h1:S82pMkj1gWdivxVRKqaRJvGMgVRntKVI5dWAgs23KI8= -go.opentelemetry.io/collector/exporter/xexporter v0.119.0 h1:bCUFRa/of+iPrJoXyzJ5cbOv/hWDHw87bnDRFQJ/JVU= -go.opentelemetry.io/collector/exporter/xexporter v0.119.0/go.mod h1:naV2XoiJv8bvOt7Vs9h6aDWmJnuD1SRnDqkIFRINYlI= -go.opentelemetry.io/collector/extension v0.119.0 h1:Itkt3jqYLjkhoX4kWhICuhXQEQz332W7UL6DpmaNHMc= -go.opentelemetry.io/collector/extension v0.119.0/go.mod h1:yMpvs58Z9F3UpSoE4w/1q/EEKlLFZBOQ2muzzikRvO8= -go.opentelemetry.io/collector/extension/auth v0.119.0 h1:URPkjeo3aKmlYGgeFCZK6kLK+D1XGfDUGSAwFaHn+QQ= -go.opentelemetry.io/collector/extension/auth v0.119.0/go.mod h1:8mGcTLfgmf2QNrdumP7g7nnNtyrpHiPRZect1tdXYJQ= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.119.0 h1:OgG2AW0Ra43tbWDUOMC4TRIUXiz5PsVYNhnBtW3muk0= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.119.0/go.mod h1:e+5w+yz9d0KHBZcH1T204IGfEO4IWuAltCSh9L5i8wg= -go.opentelemetry.io/collector/extension/extensiontest v0.119.0 h1:sAdIBRJ6Df7jdkHWY/pSEYTersxURkUz9pENKl73n6s= -go.opentelemetry.io/collector/extension/extensiontest v0.119.0/go.mod h1:XQbUTXneJ//xt58eu5ofHhzWQcQ24GRTbBMWHCEsipA= -go.opentelemetry.io/collector/extension/xextension v0.119.0 h1:uSUvha4yxk5jWevhepsQ56QSAOkk3Z4M0vcPEJeZ6UU= -go.opentelemetry.io/collector/extension/xextension v0.119.0/go.mod h1:2DSTP2IEFfCC+2IFzl1eG9bCKsBkxIQjIphziJ0+vuo= -go.opentelemetry.io/collector/extension/zpagesextension v0.119.0 h1:NUmze3n47EhqWwM/GA0o98OFntsYialinKJABRw2Ri4= -go.opentelemetry.io/collector/extension/zpagesextension v0.119.0/go.mod h1:M2zapnlbhlJbuLU7edsDfokszyDIrqrOpIt0IEWxcJ8= -go.opentelemetry.io/collector/featuregate v1.25.0 h1:3b857fvoY9xBcE5qtLUE1/nlQ65teuW9d8CKr6MykYc= -go.opentelemetry.io/collector/featuregate v1.25.0/go.mod h1:3GaXqflNDVwWndNGBJ1+XJFy3Fv/XrFgjMN60N3z7yg= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.119.0 h1:egWfZjmGZRZ7a/LRJZQWs7MzlpHVo+jctdO+5jHigH8= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.119.0/go.mod h1:0qxt8Lql6prWxCHAl4WguY+sdgyr20imKLgD/M/trjs= -go.opentelemetry.io/collector/otelcol v0.119.0 h1:tHCo07NuSBtl3bPdYIVR78+9XKr/DqX2azPt5/QlcYM= -go.opentelemetry.io/collector/otelcol v0.119.0/go.mod h1:V4uiDdOk8dOVKH0NfTBofvxGtVgx53YrYvv4w+w2wwI= -go.opentelemetry.io/collector/pdata v1.25.0 h1:AmgBklQfbfy0lT8qsoJtRuYMZ7ZV3VZvkvhjSDentrg= -go.opentelemetry.io/collector/pdata v1.25.0/go.mod h1:Zs7D4RXOGS7E2faGc/jfWdbmhoiHBxA7QbpuJOioxq8= -go.opentelemetry.io/collector/pdata/pprofile v0.119.0 h1:sVtv/MhQ3NDLkgHOWDF9BdTtThNyXdOUiz5+poRkYLQ= -go.opentelemetry.io/collector/pdata/pprofile v0.119.0/go.mod h1:ur4388PjUpmwG5HoSMzrLCPkR0gNVLT4lekcJMRPt8A= -go.opentelemetry.io/collector/pdata/testdata v0.119.0 h1:a3OiuLYx7CaEQQ8LxMhPIM804eIGlNM6Pd0XoACXWMI= -go.opentelemetry.io/collector/pdata/testdata v0.119.0/go.mod h1:stCgL1fKOVp93mI4ocHy/xBMhkW3TXr8VetH4X86q8g= -go.opentelemetry.io/collector/pipeline v0.119.0 h1:NebdPIOBIzU7CdOE36hNrCrUML+XOTR9Zsoy43E7MVk= -go.opentelemetry.io/collector/pipeline v0.119.0/go.mod h1:qE3DmoB05AW0C3lmPvdxZqd/H4po84NPzd5MrqgtL74= -go.opentelemetry.io/collector/pipeline/xpipeline v0.119.0 h1:lX70c+MjXHbOJahU6Xs3yV1rPTV/7bWXlCj/C+CnMLc= -go.opentelemetry.io/collector/pipeline/xpipeline v0.119.0/go.mod h1:m2acg7G5Rb8Srm5aK4rD7mUDQhd1r/qXq1DJxdhMAcQ= -go.opentelemetry.io/collector/processor v0.119.0 h1:mqmdR/f4I/ud2jwODqwPZvJk/TCU+AjoCAyattyKXmE= -go.opentelemetry.io/collector/processor v0.119.0/go.mod h1:N0XxvcnM1EYmZ/NiGNsFpi3bEzZ9+C6bVZKDa7tUduw= -go.opentelemetry.io/collector/processor/processortest v0.119.0 h1:0/mWuyDvELipmEIMVscOAy1vAcwUttym8yb+KLOJXmc= -go.opentelemetry.io/collector/processor/processortest v0.119.0/go.mod h1:JGqoUDWC3aFbyPbpZbdvTTDssvR7Rgfpf72VY5FeDHw= -go.opentelemetry.io/collector/processor/xprocessor v0.119.0 h1:qWWcMgde/2cLBg9MUQk0AcxC/aD34wz2GY3qrWeEHiw= -go.opentelemetry.io/collector/processor/xprocessor v0.119.0/go.mod h1:ZYtJGcZSDEB54vzulS8jdlYBpPbjklEODaVRc27TlxE= -go.opentelemetry.io/collector/receiver v0.119.0 h1:ZatoS4POR+XDkN1WwAv18Ism9f/FUsIjtVT4MIZbQS0= -go.opentelemetry.io/collector/receiver v0.119.0/go.mod h1:JUSsVwyKKQVD/Fy3T98OHOlVHE15Z7juba5RQzG3AXc= -go.opentelemetry.io/collector/receiver/receivertest v0.119.0 h1:thZkyftPCNit/m2bUUC+zaR1+hbXoSkCDtNN/vZIZSg= -go.opentelemetry.io/collector/receiver/receivertest v0.119.0/go.mod h1:DZM70vofnquGkQiTfT5ZSFZlohxANl9XOrVq9h5IKnc= -go.opentelemetry.io/collector/receiver/xreceiver v0.119.0 h1:ZcTO+h+r9TyR1XgMhA7FTSTV9RF+z/IDPrcRIg1l56U= -go.opentelemetry.io/collector/receiver/xreceiver v0.119.0/go.mod h1:AkoWhnYFMygK7Tlzez398ti20NqydX8wxPVWU86+baE= -go.opentelemetry.io/collector/semconv v0.119.0 h1:xo+V3a7hnK0I6fxAWCXT8BIT1PCBYd4emolhoKSDUlI= -go.opentelemetry.io/collector/semconv v0.119.0/go.mod h1:N6XE8Q0JKgBN2fAhkUQtqK9LT7rEGR6+Wu/Rtbal1iI= -go.opentelemetry.io/collector/service v0.119.0 h1:AP2dFx7h0VslEJfc9dt8Bbbggm1iA1iUGLzahvAPZMk= -go.opentelemetry.io/collector/service v0.119.0/go.mod h1:p/kOqK7POtrT9Jz+tAx/UtzlzokSHhFyi7eAETRgmt8= +go.opentelemetry.io/collector/confmap/xconfmap v0.120.0 h1:wt+9H/TLXhY6q40AVx+fn2XK/FhjXuwInwFq9X9+aik= +go.opentelemetry.io/collector/confmap/xconfmap v0.120.0/go.mod h1:wkzt6fVdLqBP+ZvbJWCLbo68nedvmoK09wFpR17awgs= +go.opentelemetry.io/collector/connector v0.120.0 h1:t6/2wOhm2UAgOPRKhMhybna8UjvoJI4hX305CIA2hWU= +go.opentelemetry.io/collector/connector v0.120.0/go.mod h1:REneUxc1SnH07DlNXCvh0ZBBi67wAT4HpzAPRmIt378= +go.opentelemetry.io/collector/connector/connectortest v0.120.0 h1:Blh4QsVBoPoT9dR4GC6f1oGrzotkOOElevTQOk9Wn7c= +go.opentelemetry.io/collector/connector/connectortest v0.120.0/go.mod h1:NPyD5TVRND637kd+5nTeik8ZDl82MNJXln3mY80sY2M= +go.opentelemetry.io/collector/connector/xconnector v0.120.0 h1:waYzmPSRr9BwDJxFO2wYgfPIttPhaIdyKj2xRTYLXZo= +go.opentelemetry.io/collector/connector/xconnector v0.120.0/go.mod h1:wpy9ab9AAZiekNPKZoaEmXWDmzIdQ2o2xNSgx6Otamg= +go.opentelemetry.io/collector/consumer v1.26.0 h1:0MwuzkWFLOm13qJvwW85QkoavnGpR4ZObqCs9g1XAvk= +go.opentelemetry.io/collector/consumer v1.26.0/go.mod h1:I/ZwlWM0sbFLhbStpDOeimjtMbWpMFSoGdVmzYxLGDg= +go.opentelemetry.io/collector/consumer/consumererror v0.120.0 h1:f46ZnKCGBdvkjtJBT0ruA9cxDnvuR1jeR0amq9qc6Mc= +go.opentelemetry.io/collector/consumer/consumererror v0.120.0/go.mod h1:2Cx8948nywlM1MFJgqLrIJ7N/pfxZsMF0qq+n9oFJz0= +go.opentelemetry.io/collector/consumer/consumertest v0.120.0 h1:iPFmXygDsDOjqwdQ6YZcTmpiJeQDJX+nHvrjTPsUuv4= +go.opentelemetry.io/collector/consumer/consumertest v0.120.0/go.mod h1:HeSnmPfAEBnjsRR5UY1fDTLlSrYsMsUjufg1ihgnFJ0= +go.opentelemetry.io/collector/consumer/xconsumer v0.120.0 h1:dzM/3KkFfMBIvad+NVXDV+mA+qUpHyu5c70TFOjDg68= +go.opentelemetry.io/collector/consumer/xconsumer v0.120.0/go.mod h1:eOf7RX9CYC7bTZQFg0z2GHdATpQDxI0DP36F9gsvXOQ= +go.opentelemetry.io/collector/exporter v0.120.0 h1:8PIJTV0VW1gyr8XuiEMi/aq+baCMdk1hjSrAYiG8aKk= +go.opentelemetry.io/collector/exporter v0.120.0/go.mod h1:JZCNkv0K+Gwdnfwby7Nxc1/gsmy468SBIjI/6fQdxuk= +go.opentelemetry.io/collector/exporter/exportertest v0.120.0 h1:7ABriAYXGxvUdCXxe0LpsrMGQ+BP5z/gadm1gRWbD4o= +go.opentelemetry.io/collector/exporter/exportertest v0.120.0/go.mod h1:t0hONsvJp5MM1EF1l83voJHcharIPdnpUBP42UhCoCY= +go.opentelemetry.io/collector/exporter/xexporter v0.120.0 h1:HSe3a+0lt/o/g8GgNKgkw9y9vULN4QeY6NeKms8j/GI= +go.opentelemetry.io/collector/exporter/xexporter v0.120.0/go.mod h1:P/87SRTCd/PnQhwAQbELAxotp5gIewT/vpOfEWJZPLk= +go.opentelemetry.io/collector/extension v0.120.0 h1:CA2e6jF5Sz6PE+yxGbJUn0QTMwTo28MO8FNBhdKAABw= +go.opentelemetry.io/collector/extension v0.120.0/go.mod h1:o2/Kk61I1G9XOdD8W4Tbrg05jD4P/QF0ecxYTcT8OZ8= +go.opentelemetry.io/collector/extension/auth v0.120.0 h1:Z4mgQay67BC43F3yK50V/hLdmegBNyMt1upJRV6YW4g= +go.opentelemetry.io/collector/extension/auth v0.120.0/go.mod h1:2DyrUZYNlO3ExAVhflUwvifpxb077Q2aLndcPfkZIzM= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.120.0 h1:RaXVtUOiRNuPA5mr8cgieuY1O7M0sVWn2Gvhe24n51c= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.120.0/go.mod h1:3PBL7XUwQIzEhnMn12w6XC7sSh9JRUvmdlWs3KJ9KLc= +go.opentelemetry.io/collector/extension/extensiontest v0.120.0 h1:DSN2cuuQ+CUVEgEStX04lG4rg/6oZeM2zyeX5wXeGWg= +go.opentelemetry.io/collector/extension/extensiontest v0.120.0/go.mod h1:MTFigcQ7hblDUv12b3RbfYvtmzUNZzLiDoug11ezJWQ= +go.opentelemetry.io/collector/extension/xextension v0.120.0 h1:2lwasSQI3Fk6zto7u1uaMqDHESZtdq6a9kaAdCPwwO8= +go.opentelemetry.io/collector/extension/xextension v0.120.0/go.mod h1:9QT+Rq6YniuuKklpeAYpvp9ezPn2bjLOqzsBiFk55DE= +go.opentelemetry.io/collector/extension/zpagesextension v0.120.0 h1:Oc8F0o3jLzKw5wlB7eqK6vc4K4eF5wSDZfN175qmfTo= +go.opentelemetry.io/collector/extension/zpagesextension v0.120.0/go.mod h1:7BuJXALIFukILETkzGcFhxPQFaYkvXLPpwbtOTMY6DI= +go.opentelemetry.io/collector/featuregate v1.26.0 h1:NIZdJby6jL9tEHI25ddeUNgc09Q0Fof31YHF1CSVp4Y= +go.opentelemetry.io/collector/featuregate v1.26.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.120.0 h1:vcY46z2WnYs0bcFulJX51O2dXc2sgWDymR91u/tV5EE= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.120.0/go.mod h1:qUcJqy4Us/pxnWJTqloDmlAz8wGUIZDe/RMSmzfymdo= +go.opentelemetry.io/collector/internal/telemetry v0.120.0 h1:JsHTY2/9+EYGgg6sqb85KU5iSZow373Z3IZywYTgiUA= +go.opentelemetry.io/collector/internal/telemetry v0.120.0/go.mod h1:5F/UCo4WlIjobkypTWgoWTvyIM2AN2INR5/HmvXdilQ= +go.opentelemetry.io/collector/otelcol v0.120.0 h1:iCUzunaztU69MlA+fe1/5VLIuufAFo53psghgaEdamo= +go.opentelemetry.io/collector/otelcol v0.120.0/go.mod h1:nNELe3quKRa4Ra3zTsCOkC7IXii0Z2E2wureB1SW1OA= +go.opentelemetry.io/collector/pdata v1.26.0 h1:o7nP0RTQOG0LXk55ZZjLrxwjX8x3wHF7Z7xPeOaskEA= +go.opentelemetry.io/collector/pdata v1.26.0/go.mod h1:18e8/xDZsqyj00h/5HM5GLdJgBzzG9Ei8g9SpNoiMtI= +go.opentelemetry.io/collector/pdata/pprofile v0.120.0 h1:lQl74z41MN9a0M+JFMZbJVesjndbwHXwUleVrVcTgc8= +go.opentelemetry.io/collector/pdata/pprofile v0.120.0/go.mod h1:4zwhklS0qhjptF5GUJTWoCZSTYE+2KkxYrQMuN4doVI= +go.opentelemetry.io/collector/pdata/testdata v0.120.0 h1:Zp0LBOv3yzv/lbWHK1oht41OZ4WNbaXb70ENqRY7HnE= +go.opentelemetry.io/collector/pdata/testdata v0.120.0/go.mod h1:PfezW5Rzd13CWwrElTZRrjRTSgMGUOOGLfHeBjj+LwY= +go.opentelemetry.io/collector/pipeline v0.120.0 h1:QQQbnLCYiuOqmxIRQ11cvFGt+SXq0rypK3fW8qMkzqQ= +go.opentelemetry.io/collector/pipeline v0.120.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= +go.opentelemetry.io/collector/pipeline/xpipeline v0.120.0 h1:klY22BaRMO1+JmjUu0Af961hpHA5qnOTAVR7tN+UTW8= +go.opentelemetry.io/collector/pipeline/xpipeline v0.120.0/go.mod h1:K/7Ki7toZQpNV0GF7TbrOEoo8dP3dDXKKSRNnTyEsBE= +go.opentelemetry.io/collector/processor v0.120.0 h1:No+I65ybBLVy4jc7CxcsfduiBrm7Z6kGfTnekW3hx1A= +go.opentelemetry.io/collector/processor v0.120.0/go.mod h1:4zaJGLZCK8XKChkwlGC/gn0Dj4Yke04gQCu4LGbJGro= +go.opentelemetry.io/collector/processor/processortest v0.120.0 h1:R+VSVSU59W0/mPAcyt8/h1d0PfWN6JI2KY5KeMICXvo= +go.opentelemetry.io/collector/processor/processortest v0.120.0/go.mod h1:me+IVxPsj4IgK99I0pgKLX34XnJtcLwqtgTuVLhhYDI= +go.opentelemetry.io/collector/processor/xprocessor v0.120.0 h1:mBznj/1MtNqmu6UpcoXz6a63tU0931oWH2pVAt2+hzo= +go.opentelemetry.io/collector/processor/xprocessor v0.120.0/go.mod h1:Nsp0sDR3gE+GAhi9d0KbN0RhOP+BK8CGjBRn8+9d/SY= +go.opentelemetry.io/collector/receiver v0.120.0 h1:JTnPqmBLRXpOyLPh8Kch/5C8SivnpYK9Lzy4PvtEnLQ= +go.opentelemetry.io/collector/receiver v0.120.0/go.mod h1:jpYY55wTVE0FqiBIJrNv2HrvSUnGEjLS/3CWGA+CeL4= +go.opentelemetry.io/collector/receiver/receivertest v0.120.0 h1:Op9yCT0kGvqPF0BB83+iOcsxJJHPCLeL4f4/Op1MBoI= +go.opentelemetry.io/collector/receiver/receivertest v0.120.0/go.mod h1:lpFA4FzcHWki7rLzsNncYmDZ4f7Eik8JY1Mmsaw5uMw= +go.opentelemetry.io/collector/receiver/xreceiver v0.120.0 h1:+gHYd9rTBRKSQfWsTzV2wlwfaVL/LZSz5wu4sygZH7w= +go.opentelemetry.io/collector/receiver/xreceiver v0.120.0/go.mod h1:dkHpL1QqLi/G+60VZnfFpZQf9qoxDVnp6G9FuAcMgfk= +go.opentelemetry.io/collector/semconv v0.120.0 h1:iG9N78c2IZN4XOH7ZSdAQJBbaHDTuPnTlbQjKV9uIPY= +go.opentelemetry.io/collector/semconv v0.120.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= +go.opentelemetry.io/collector/service v0.120.0 h1:7E0ILhOYP72qZBNmprsJxLFozEuXlF0Evy5e4HinTJI= +go.opentelemetry.io/collector/service v0.120.0/go.mod h1:hRVK2Tvgm6W+8zb6NZ4fKuhMot3jzz6tu9YHDgwIQ8E= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25PkeyWmOcI+SjXWguNw= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= @@ -408,8 +412,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From e86b0f96029f30c9449ef1bc73e1c4bf0e513bc3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2025 16:02:34 +0000 Subject: [PATCH 231/426] chore(deps): update azure/setup-helm action to v4.3.0 (main) (#4487) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-helm/action.yaml | 2 +- .github/actions/run-e2e/action.yaml | 2 +- .github/workflows/ci.yaml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/build-helm/action.yaml b/.github/actions/build-helm/action.yaml index b7f0ba3a58..63fdcbf495 100644 --- a/.github/actions/build-helm/action.yaml +++ b/.github/actions/build-helm/action.yaml @@ -21,7 +21,7 @@ runs: using: "composite" steps: - name: Set up Helm - uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 + uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 with: token: ${{ inputs.github-token }} - name: Generate helm-package diff --git a/.github/actions/run-e2e/action.yaml b/.github/actions/run-e2e/action.yaml index d835b4a326..5f4254a17c 100644 --- a/.github/actions/run-e2e/action.yaml +++ b/.github/actions/run-e2e/action.yaml @@ -54,7 +54,7 @@ runs: with: go-version-file: "${{ github.workspace }}/target/go.mod" - name: Set up helm - uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 + uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 with: token: ${{ inputs.github-token }} - name: Install gotestsum diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d4c8684a55..50a6a36f10 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,7 +24,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Helm - uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 + uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Run Unit tests @@ -39,7 +39,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Helm - uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 + uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Run Linting @@ -106,7 +106,7 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Set up Helm - uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 + uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 with: token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 From fa7ba8db6ff416280ce7b87c1373441c5febb888 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Feb 2025 17:11:56 +0000 Subject: [PATCH 232/426] fix(deps): update module github.com/prometheus/client_golang to v1.21.0 (main) (#4489) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4eb7e2d925..e1b9338cc0 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/klauspost/compress v1.17.11 github.com/opencontainers/go-digest v1.0.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/client_golang v1.21.0 github.com/spf13/afero v1.12.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 diff --git a/go.sum b/go.sum index ce81b5c15e..6c0425b3b3 100644 --- a/go.sum +++ b/go.sum @@ -153,8 +153,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA= +github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= From 6d17bac63b7722bdd5051b67a143ca76d738e1e8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Feb 2025 22:51:41 +0000 Subject: [PATCH 233/426] chore(deps): update docker/build-push-action action to v6.14.0 (main) (#4490) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index b664a7ed67..c2e394952f 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -35,7 +35,7 @@ runs: run: | touch dynatrace-operator-bin-sbom.cdx.json - name: Build target - uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 + uses: docker/build-push-action@0adf9959216b96bec444f325f1e493d4aa344497 # v6.14.0 with: builder: ${{ steps.buildx.outputs.name }} build-args: | From 76da4fe67808303fdc5fad217ca242476683a2fc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Feb 2025 02:12:54 +0000 Subject: [PATCH 234/426] fix(deps): update module github.com/klauspost/compress to v1.18.0 (main) (#4491) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e1b9338cc0..c0779f7ee8 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.3 github.com/google/uuid v1.6.0 - github.com/klauspost/compress v1.17.11 + github.com/klauspost/compress v1.18.0 github.com/opencontainers/go-digest v1.0.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.21.0 diff --git a/go.sum b/go.sum index 6c0425b3b3..c711114cd4 100644 --- a/go.sum +++ b/go.sum @@ -94,8 +94,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= From 148f491f7c85f10169b47b69468dc9e8f65892fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Feb 2025 06:30:18 +0000 Subject: [PATCH 235/426] fix(deps): update module github.com/docker/cli to v28 (main) (#4492) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c0779f7ee8..802debb632 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.3 require ( github.com/container-storage-interface/spec v1.11.0 - github.com/docker/cli v27.5.1+incompatible + github.com/docker/cli v28.0.0+incompatible github.com/evanphx/json-patch v5.9.11+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.3 diff --git a/go.sum b/go.sum index c711114cd4..88bd3d0c93 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docker/cli v27.5.1+incompatible h1:JB9cieUT9YNiMITtIsguaN55PLOHhBSz3LKVc6cqWaY= github.com/docker/cli v27.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v28.0.0+incompatible h1:ido37VmLUqEp+5NFb9icd6BuBB+SNDgCn+5kPCr2buA= +github.com/docker/cli v28.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= From 5a23b065f5a92af9d70c4522d1de769974099b1c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Feb 2025 19:08:43 +0000 Subject: [PATCH 236/426] chore(deps): update sigstore/cosign-installer action to v3.8.1 (main) (#4493) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/sign-image/action.yaml | 2 +- .github/actions/upload-sbom/action.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/sign-image/action.yaml b/.github/actions/sign-image/action.yaml index bb3a4ef8b7..31215bc6a4 100644 --- a/.github/actions/sign-image/action.yaml +++ b/.github/actions/sign-image/action.yaml @@ -14,7 +14,7 @@ runs: using: "composite" steps: - name: Install Cosign - uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0 + uses: sigstore/cosign-installer@d7d6bc7722e3daa8354c50bcb52f4837da5e9b6a # v3.8.1 - name: Sign image with a key shell: bash run: | diff --git a/.github/actions/upload-sbom/action.yaml b/.github/actions/upload-sbom/action.yaml index 01e18b37e0..11e5edc00a 100644 --- a/.github/actions/upload-sbom/action.yaml +++ b/.github/actions/upload-sbom/action.yaml @@ -17,7 +17,7 @@ runs: using: "composite" steps: - name: Install Cosign - uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0 + uses: sigstore/cosign-installer@d7d6bc7722e3daa8354c50bcb52f4837da5e9b6a # v3.8.1 - name: Attach sbom attestation to image shell: bash run: | From f31881e9a4782d4a6a5baa2f6b6004c863fe3e08 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Fri, 21 Feb 2025 12:14:28 +0100 Subject: [PATCH 237/426] Fix helm upgrade if debug field is string (#4495) --- config/helm/chart/default/templates/_helpers.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/helm/chart/default/templates/_helpers.tpl b/config/helm/chart/default/templates/_helpers.tpl index 92610022ff..e27c8d9f6b 100644 --- a/config/helm/chart/default/templates/_helpers.tpl +++ b/config/helm/chart/default/templates/_helpers.tpl @@ -42,19 +42,19 @@ Check if default image or imageref is used {{- end -}} {{- define "webhook.securityContext" -}} - {{- if ne .Values.debug true -}} + {{- if not .Values.debug -}} {{- toYaml .Values.webhook.securityContext -}} {{- end -}} {{- end -}} {{- define "csidriver.provisioner.resources" -}} - {{- if ne .Values.debug true -}} + {{- if not .Values.debug -}} {{- toYaml .Values.csidriver.provisioner.resources -}} {{- end -}} {{- end -}} {{- define "csidriver.server.resources" -}} - {{- if ne .Values.debug true -}} + {{- if not .Values.debug -}} {{- toYaml .Values.csidriver.server.resources -}} {{- end -}} {{- end -}} From 56d01dafb9f2966794cf737379449ac6407efb95 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Fri, 21 Feb 2025 14:11:33 +0100 Subject: [PATCH 238/426] Add background information to used operator roles (#4488) --- .../Common/operator/clusterrole-operator.yaml | 3 ++ .../Common/operator/role-operator.yaml | 47 ++----------------- .../Common/operator/role-operator_test.yaml | 44 +---------------- doc/roles/operator-roles.md | 39 +++++++++++++++ 4 files changed, 49 insertions(+), 84 deletions(-) create mode 100644 doc/roles/operator-roles.md diff --git a/config/helm/chart/default/templates/Common/operator/clusterrole-operator.yaml b/config/helm/chart/default/templates/Common/operator/clusterrole-operator.yaml index a9098dd3df..b9d5c46c1d 100644 --- a/config/helm/chart/default/templates/Common/operator/clusterrole-operator.yaml +++ b/config/helm/chart/default/templates/Common/operator/clusterrole-operator.yaml @@ -11,6 +11,9 @@ # 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. + +# For more information why the individual permissions are required see +# https://github.com/Dynatrace/dynatrace-operator/blob/main/doc/roles/operator-roles.md apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/config/helm/chart/default/templates/Common/operator/role-operator.yaml b/config/helm/chart/default/templates/Common/operator/role-operator.yaml index 5f0b851443..58bb8e3f5e 100644 --- a/config/helm/chart/default/templates/Common/operator/role-operator.yaml +++ b/config/helm/chart/default/templates/Common/operator/role-operator.yaml @@ -11,6 +11,9 @@ # 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. + +# For more information why the individual permissions are required see +# https://github.com/Dynatrace/dynatrace-operator/blob/main/doc/roles/operator-roles.md apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: @@ -42,27 +45,7 @@ rules: - apps resources: - statefulsets - verbs: - - get - - list - - watch - - create - - update - - delete - - apiGroups: - - apps - resources: - daemonsets - verbs: - - get - - list - - watch - - create - - update - - delete - - apiGroups: - - apps - resources: - replicasets - deployments verbs: @@ -82,6 +65,8 @@ rules: - "" resources: - configmaps + - secrets + - services verbs: - get - list @@ -97,17 +82,6 @@ rules: - get - list - watch - - apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch - - create - - update - - delete - apiGroups: - "" resources: @@ -116,17 +90,6 @@ rules: - create - get - list - - apiGroups: - - "" - resources: - - services - verbs: - - create - - update - - delete - - get - - list - - watch - apiGroups: - networking.istio.io resources: diff --git a/config/helm/chart/default/tests/Common/operator/role-operator_test.yaml b/config/helm/chart/default/tests/Common/operator/role-operator_test.yaml index 9352fc658e..9c6bd13c26 100644 --- a/config/helm/chart/default/tests/Common/operator/role-operator_test.yaml +++ b/config/helm/chart/default/tests/Common/operator/role-operator_test.yaml @@ -39,27 +39,7 @@ tests: - apps resources: - statefulsets - verbs: - - get - - list - - watch - - create - - update - - delete - - apiGroups: - - apps - resources: - daemonsets - verbs: - - get - - list - - watch - - create - - update - - delete - - apiGroups: - - apps - resources: - replicasets - deployments verbs: @@ -79,6 +59,8 @@ tests: - "" resources: - configmaps + - secrets + - services verbs: - get - list @@ -94,17 +76,6 @@ tests: - get - list - watch - - apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch - - create - - update - - delete - apiGroups: - "" resources: @@ -113,17 +84,6 @@ tests: - create - get - list - - apiGroups: - - "" - resources: - - services - verbs: - - create - - update - - delete - - get - - list - - watch - apiGroups: - networking.istio.io resources: diff --git a/doc/roles/operator-roles.md b/doc/roles/operator-roles.md new file mode 100644 index 0000000000..12d36d01ea --- /dev/null +++ b/doc/roles/operator-roles.md @@ -0,0 +1,39 @@ +# Permissions required by the Operator Pod + +**Permissions for Operator:** + +| Resources | Verbs | Comments | +| ------------------------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| events | create, get, list | Required by operator SDK | +| services | create, update, delete, get, list, watch | Required for ActiveGate, OTEL Collector Operator TelemetryService, Extensions | +| serviceentries.networking.istio.io | get, list, create, update, delete | Required by Istio Reconciler | +| virtualservices.networking.istio.io | get, list, create, update, delete | Required by Istio Reconciler | +| configmaps | get, list, watch, create, update, delete | Required to access trustedCAs, edgeConnect CA certs, ActiveGate/OneAgent Connection Info, Extension Custom Configuration, NodesController cache | +| secrets | get, list, watch, create, update, delete | Required for webhook certificates, OneAgent/ActiveGate AuthToken, ProcessModuleConfig; To access ActiveGate TLS, CustomPullSecret; | +| daemonsets.apps | get, list, watch, create, update, delete | Required by KSPM, LogMonitoring, All Monitoring modes that require host agents | +| deployments.apps | get, list, watch, create, update, delete | Required by our unit & E2E tests | +| replicasets.apps | get, list, watch, create, update, delete | Required by the nodes controller to check the owner | +| statefulsets.apps | get, list, watch, create, update, delete | Required by Extensions, OtelCollector, ActiveGate | +| dynakubes.dynatrace.com | get, list, watch, update | Required for reconciliation | +| edgeconnects.dynatrace.com | get, list, watch, update | Required for reconciliation | +| pods | get, list, watch | Required for operator pod to check if deployed via olm | +| leases.coordination.k8s.io | get, update, create | Required by Operator to guarantee, that only one is running at the same time | +| deployments.apps/finalizers | update | | +| dynakubes.dynatrace.com/finalizers | update | Required for reconciliation | +| dynakubes.dynatrace.com/status | update | Required for reconciliation | +| edgeconnects.dynatrace.com/finalizers | update | Required for reconciliation | +| edgeconnects.dynatrace.com/status | update | Required for reconciliation | + +**ClusterRole Permissions for Operator:** + +| Resources | Resource Names | Verbs | Comments | +| ------------------------------------------------------------ | -------------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| secrets | | create | Required to create init secret in every namespace for CNFS and application monitoring / metadata enrichment | +| namespaces | | get, list, watch, update | Required for setting the injection labels; Required as soon as a DynaKube is reconciled.; Required by EdgeConnect and DynaKube for requesting the kubeSystem UID | +| nodes | | get, list, watch | Required by nodes controller for node cache and mark for termination handling | +| secrets | dynatrace-dynakube-config | get, update, delete, list | Required to create init secret in every namespace for CNFS and application monitoring / metadata enrichment | +| secrets | dynatrace-metadata-enrichment-endpoint | get, update, delete, list | Required to create init secret in every namespace for CNFS and application monitoring / metadata enrichment | +| mutatingwebhookconfigurations.admissionregistration.k8s.io | dynatrace-webhook | get, update | Required for setting the CABundles aka. public cert created by our webhook cert controller. These certs are used by the API-Server to create a secure connection to the webhook. | +| validatingwebhookconfigurations.admissionregistration.k8s.io | dynatrace-webhook | get, update | Required for setting the CABundles aka. public cert created by our webhook cert controller. These certs are used by the API-Server to create a secure connection to the webhook. | +| customresourcedefinitions.apiextensions.k8s.io | dynakubes.dynatrace.com | get, update | Required for webhook cert controller. | +| customresourcedefinitions.apiextensions.k8s.io | edgeconnects.dynatrace.com | get, update | Required for webhook cert controller. | From e519ea6671ea72b0afd1e5921135ef7f06fa4f55 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 21 Feb 2025 21:49:57 +0000 Subject: [PATCH 239/426] chore(deps): update actions/upload-artifact action to v4.6.1 (main) (#4496) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- .github/actions/preflight/action.yaml | 2 +- .github/workflows/openssf-scorecards.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index c2e394952f..5b35b7a1d5 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -49,7 +49,7 @@ runs: labels: ${{ inputs.labels }} outputs: type=docker,dest=/tmp/operator-${{ inputs.platform }}.tar - name: Upload artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 with: name: operator-${{ inputs.platform }} path: /tmp/operator-${{ inputs.platform }}.tar diff --git a/.github/actions/preflight/action.yaml b/.github/actions/preflight/action.yaml index d75cdc9b64..56adf6fce8 100644 --- a/.github/actions/preflight/action.yaml +++ b/.github/actions/preflight/action.yaml @@ -34,7 +34,7 @@ runs: run: | hack/build/ci/preflight.sh "${{ env.PREFLIGHT_VERSION }}" "${{ env.IMAGE_URI}}" "${{ inputs.report-name }}" - name: Upload report - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 with: name: preflight-report path: ${{ inputs.report-name }} diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 8d2936e26f..97f148271d 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -48,7 +48,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 with: name: SARIF file path: results.sarif From 0ecdab7e85f5496a72646bb1773ae2dca0d47eed Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 22 Feb 2025 02:55:52 +0000 Subject: [PATCH 240/426] chore(deps): update github/codeql-action action to v3.28.10 (main) (#4497) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index ea69f8c94b..4bef96e574 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9 + uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9 + uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9 + uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 97f148271d..1675c1e507 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9 + uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 with: sarif_file: results.sarif From 205167dc50e60be82c5db1a662a1b9b2d2bb42b6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 22 Feb 2025 07:11:48 +0000 Subject: [PATCH 241/426] chore(deps): update module github.com/vektra/mockery to v2.52.3 (main) (#4498) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 2ef3886596..c0c88fec3e 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.30.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.52.2 +mockery_version=v2.52.3 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest From 03212654f4bfb3bda204caef39c8a65a51878327 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 22 Feb 2025 10:37:22 +0000 Subject: [PATCH 242/426] chore(deps): update ossf/scorecard-action action to v2.4.1 (main) (#4499) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/openssf-scorecards.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 1675c1e507..a6555eb42e 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -29,7 +29,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 with: results_file: results.sarif results_format: sarif From a012ea5b61e2858b9c7d19854a68afd171b6bed7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 21:47:13 +0000 Subject: [PATCH 243/426] chore(deps): update peter-evans/create-pull-request action to v7.0.7 (main) (#4504) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b79da54587..fae4f5b65c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -408,7 +408,7 @@ jobs: hack/build/ci/generate-new-helm-index-yaml.sh "helm-pkg" ${{ needs.prepare.outputs.version_without_prefix }} - name: Create pull request for adding helm index to main branch if: ${{ !contains(github.ref, '-rc.') }} - uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 + uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 # v7.0.7 with: base: main delete-branch: true From e32edf06da08882c734c5e35596d6c1f51ff3cf6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 03:31:44 +0000 Subject: [PATCH 244/426] fix(deps): update module golang.org/x/oauth2 to v0.27.0 (main) (#4506) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 802debb632..cd50824c45 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.23.0 golang.org/x/net v0.35.0 - golang.org/x/oauth2 v0.26.0 + golang.org/x/oauth2 v0.27.0 golang.org/x/sys v0.30.0 google.golang.org/grpc v1.70.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 88bd3d0c93..c93d7210c8 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v27.5.1+incompatible h1:JB9cieUT9YNiMITtIsguaN55PLOHhBSz3LKVc6cqWaY= -github.com/docker/cli v27.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v28.0.0+incompatible h1:ido37VmLUqEp+5NFb9icd6BuBB+SNDgCn+5kPCr2buA= github.com/docker/cli v28.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= @@ -369,8 +367,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= -golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= -golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From c0a2ae64e251165d0d72f79485c1f820ebfa2d5d Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Tue, 25 Feb 2025 11:14:32 +0100 Subject: [PATCH 245/426] Support OCI `codeModulesImage` as well (#4503) --- pkg/injection/codemodule/installer/image/unpack.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/injection/codemodule/installer/image/unpack.go b/pkg/injection/codemodule/installer/image/unpack.go index aed7ac71ea..d9c2a39898 100644 --- a/pkg/injection/codemodule/installer/image/unpack.go +++ b/pkg/injection/codemodule/installer/image/unpack.go @@ -104,7 +104,7 @@ func (installer *Installer) unpackOciImage(layers []containerv1.Layer, imageCach for _, layer := range layers { mediaType, _ := layer.MediaType() switch mediaType { - case types.DockerLayer: + case types.DockerLayer, types.OCILayer: digest, _ := layer.Digest() sourcePath := filepath.Join(imageCacheDir, "blobs", digest.Algorithm, digest.Hex) log.Info("unpackOciImage", "sourcePath", sourcePath) @@ -112,8 +112,6 @@ func (installer *Installer) unpackOciImage(layers []containerv1.Layer, imageCach if err := installer.extractor.ExtractGzip(sourcePath, targetDir); err != nil { return err } - case types.OCILayer: - return errors.New("OCILayer is not implemented") case types.OCILayerZStd: return errors.New("OCILayerZStd is not implemented") default: From 28d11373942b6464b1528cd7d7685d472b31badf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2025 02:59:52 +0000 Subject: [PATCH 246/426] chore(deps): update actions/download-artifact action to v4.1.9 (main) (#4510) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/upload-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/upload-image/action.yaml b/.github/actions/upload-image/action.yaml index 56ea77ecc4..106b6c9843 100644 --- a/.github/actions/upload-image/action.yaml +++ b/.github/actions/upload-image/action.yaml @@ -29,7 +29,7 @@ runs: using: "composite" steps: - name: Download artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 with: name: operator-${{ inputs.platform }} path: /tmp From c3675e21a881113a362d4bbf85a7ef87144013b1 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Wed, 26 Feb 2025 07:19:52 +0100 Subject: [PATCH 247/426] Fix/multiple set host property arguments (#4508) --- pkg/api/v1beta3/dynakube/oneagent/props.go | 16 +-- .../v1beta3/dynakube/oneagent/props_test.go | 126 ++++++++++++++++++ pkg/api/validation/dynakube/oneagent_test.go | 42 ++++-- .../oneagent/daemonset/arguments_test.go | 30 +++++ 4 files changed, 193 insertions(+), 21 deletions(-) diff --git a/pkg/api/v1beta3/dynakube/oneagent/props.go b/pkg/api/v1beta3/dynakube/oneagent/props.go index 59b0037c99..3e65f767cd 100644 --- a/pkg/api/v1beta3/dynakube/oneagent/props.go +++ b/pkg/api/v1beta3/dynakube/oneagent/props.go @@ -252,19 +252,13 @@ func (oa *OneAgent) GetHostGroupAsParam() string { return hostGroup } -func splitArg(arg string) (key, value string) { - split := strings.Split(arg, "=") - - const expectedLen = 2 - - if len(split) != expectedLen { - return +func splitArg(arg string) (string, string) { + key, value, found := strings.Cut(arg, "=") + if !found { + return arg, "" } - key = split[0] - value = split[1] - - return + return key, value } func (oa *OneAgent) IsCommunicationRouteClear() bool { diff --git a/pkg/api/v1beta3/dynakube/oneagent/props_test.go b/pkg/api/v1beta3/dynakube/oneagent/props_test.go index 6dd51a8505..00987176f8 100644 --- a/pkg/api/v1beta3/dynakube/oneagent/props_test.go +++ b/pkg/api/v1beta3/dynakube/oneagent/props_test.go @@ -246,6 +246,132 @@ func TestOneAgentHostGroup(t *testing.T) { }) } +func TestOneAgentArgumentsMap(t *testing.T) { + t.Run("straight forward argument list", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-id-source=k8s-node-name", + "--set-host-property=OperatorVersion=$(DT_OPERATOR_VERSION)", + "--set-host-property=dt.security_context=kubernetes_clusters", + "--set-host-property=dynakube-name=$(CUSTOM_CRD_NAME)", + "--set-no-proxy=", + "--set-proxy=", + "--set-tenant=$(DT_TENANT)", + "--set-server=dynatrace.com", + "--set-host-property=prop1=val1", + "--set-host-property=prop2=val2", + "--set-host-property=prop3=val3", + "--set-host-tag=tag1", + "--set-host-tag=tag2", + "--set-host-tag=tag3", + }, + }, + }, + HostGroup: "field", + }, + } + argMap := dk.GetArgumentsMap() + require.Len(t, argMap, 7) + + require.Len(t, argMap["--set-host-id-source"], 1) + assert.Equal(t, "k8s-node-name", argMap["--set-host-id-source"][0]) + + require.Len(t, argMap["--set-host-property"], 6) + assert.Equal(t, "OperatorVersion=$(DT_OPERATOR_VERSION)", argMap["--set-host-property"][0]) + assert.Equal(t, "dt.security_context=kubernetes_clusters", argMap["--set-host-property"][1]) + assert.Equal(t, "dynakube-name=$(CUSTOM_CRD_NAME)", argMap["--set-host-property"][2]) + assert.Equal(t, "prop1=val1", argMap["--set-host-property"][3]) + assert.Equal(t, "prop2=val2", argMap["--set-host-property"][4]) + assert.Equal(t, "prop3=val3", argMap["--set-host-property"][5]) + + require.Len(t, argMap["--set-no-proxy"], 1) + assert.Equal(t, "", argMap["--set-no-proxy"][0]) + + require.Len(t, argMap["--set-proxy"], 1) + assert.Equal(t, "", argMap["--set-proxy"][0]) + + require.Len(t, argMap["--set-tenant"], 1) + assert.Equal(t, "$(DT_TENANT)", argMap["--set-tenant"][0]) + + require.Len(t, argMap["--set-server"], 1) + assert.Equal(t, "dynatrace.com", argMap["--set-server"][0]) + }) + + t.Run("multiple --set-host-property arguments", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-property=prop1=val1", + "--set-host-property=prop2=val2", + "--set-host-property=prop3=val3", + "--set-host-property=prop3=val3", + }, + }, + }, + HostGroup: "field", + }, + } + argMap := dk.GetArgumentsMap() + require.Len(t, argMap, 1) + require.Len(t, argMap["--set-host-property"], 4) + + assert.Equal(t, "prop1=val1", argMap["--set-host-property"][0]) + assert.Equal(t, "prop2=val2", argMap["--set-host-property"][1]) + assert.Equal(t, "prop3=val3", argMap["--set-host-property"][2]) + }) + + t.Run("multiple --set-host-tag arguments", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-tag=tag1=1", + "--set-host-tag=tag1=2", + "--set-host-tag=tag1=3", + "--set-host-tag=tag2", + "--set-host-tag=tag3", + }, + }, + }, + HostGroup: "field", + }, + } + argMap := dk.GetArgumentsMap() + require.Len(t, argMap, 1) + require.Len(t, argMap["--set-host-tag"], 5) + + assert.Equal(t, "tag1=1", argMap["--set-host-tag"][0]) + assert.Equal(t, "tag1=2", argMap["--set-host-tag"][1]) + assert.Equal(t, "tag1=3", argMap["--set-host-tag"][2]) + assert.Equal(t, "tag2", argMap["--set-host-tag"][3]) + assert.Equal(t, "tag3", argMap["--set-host-tag"][4]) + }) + + t.Run("arguments without value", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--enable-feature-a", + "--enable-feature-b", + "--enable-feature-c", + }, + }, + }, + HostGroup: "field", + }, + } + argMap := dk.GetArgumentsMap() + require.Len(t, argMap, 3) + require.Len(t, argMap["--enable-feature-a"], 1) + require.Len(t, argMap["--enable-feature-b"], 1) + require.Len(t, argMap["--enable-feature-c"], 1) + }) +} + func setupDisabledCSIEnv(t *testing.T) { t.Helper() installconfig.SetModulesOverride(t, installconfig.Modules{ diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index c730ce2223..37e0a3251b 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -599,9 +599,12 @@ func TestOneAgentArguments(t *testing.T) { testName: "duplicate host property", arguments: []string{ "--set-server=foo", - "--set-host-property=foo", - "--set-host-property=bar", - "--set-host-property=dow", + "--set-host-property=foo1=bar1", + "--set-host-property=foo2=bar2", + "--set-host-property=foo3=bar3", + "--set-host-property=foo3=bar3", + "--set-host-property=foo2=bar2", + "--set-host-property=foo1=bar1", }, expectedError: "", }, @@ -609,24 +612,43 @@ func TestOneAgentArguments(t *testing.T) { testName: "duplicate host tag", arguments: []string{ "--set-server=foo", - "--set-host-tag=foo", - "--set-host-tag=bar", - "--set-host-tag=dow", + "--set-host-tag=foo=1", + "--set-host-tag=bar=1", + "--set-host-tag=dow=1", }, expectedError: "", }, { testName: "duplicate host tag with same value", arguments: []string{ - "--set-host-tag=foo", + "--set-host-tag=foo=1", "--set-host-tag=bar", - "--set-host-tag=foo", + "--set-host-tag=foo=1", "--set-host-tag=bar", "--set-host-tag=doh", "--set-host-tag=bar", - "--set-host-tag=foo", + "--set-host-tag=foo=1", + }, + expectedError: fmt.Sprintf(errorSameHostTagMultipleTimes, "[foo=1 bar]"), + }, + { + testName: "arguments without value", + arguments: []string{ + "--enable-feature-a", + "--enable-feature-b", + "--enable-feature-c", + }, + expectedError: "", + }, + { + testName: "duplicate arguments without value", + arguments: []string{ + "--enable-feature-a", + "--enable-feature-b", + "--enable-feature-a", + "--enable-feature-c", }, - expectedError: fmt.Sprintf(errorSameHostTagMultipleTimes, "[foo bar]"), + expectedError: fmt.Sprintf(errorDuplicateOneAgentArgument, "--enable-feature-a"), }, } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go b/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go index 677e3bf4bd..703e8c84a1 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go @@ -266,6 +266,36 @@ func TestArguments(t *testing.T) { assert.Contains(t, arguments, "--set-no-proxy=*.dev.dynatracelabs.com,dynakube-activegate.dynatrace") }) + t.Run("allow arguments without value, but deduplicate", func(t *testing.T) { + custArgs := []string{ + "--enable-feature-a", + "--enable-feature-b", + "--enable-feature-c", + "--enable-feature-c", + "--enable-feature-a", + "--enable-feature-b", + } + builder := builder{ + dk: &dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{ClassicFullStack: &oneagent.HostInjectSpec{}}}}, + hostInjectSpec: &oneagent.HostInjectSpec{Args: custArgs}, + deploymentType: deploymentmetadata.CloudNativeDeploymentType, + } + + arguments, _ := builder.arguments() + + expectedDefaultArguments := []string{ + "--enable-feature-a", + "--enable-feature-b", + "--enable-feature-c", + "--set-host-id-source=auto", + "--set-host-property=OperatorVersion=$(DT_OPERATOR_VERSION)", + "--set-no-proxy=", + "--set-proxy=", + "--set-server={$(DT_SERVER)}", + "--set-tenant=$(DT_TENANT)", + } + assert.Equal(t, expectedDefaultArguments, arguments) + }) } func TestPodSpec_Arguments(t *testing.T) { From 7db4e4245a21a842f2c648ffe4fbef2003017577 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2025 19:34:02 +0000 Subject: [PATCH 248/426] fix(deps): update module github.com/docker/cli to v28.0.1+incompatible (main) (#4516) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cd50824c45..7c99c4a640 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.3 require ( github.com/container-storage-interface/spec v1.11.0 - github.com/docker/cli v28.0.0+incompatible + github.com/docker/cli v28.0.1+incompatible github.com/evanphx/json-patch v5.9.11+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.3 diff --git a/go.sum b/go.sum index c93d7210c8..7a43f343e0 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v28.0.0+incompatible h1:ido37VmLUqEp+5NFb9icd6BuBB+SNDgCn+5kPCr2buA= -github.com/docker/cli v28.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl3hgCPOKzs= +github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= From 956cffbe06222005f1624beb79014e925fbf304a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2025 22:53:31 +0000 Subject: [PATCH 249/426] chore(deps): update docker/build-push-action action to v6.15.0 (main) (#4517) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 5b35b7a1d5..784eef1294 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -35,7 +35,7 @@ runs: run: | touch dynatrace-operator-bin-sbom.cdx.json - name: Build target - uses: docker/build-push-action@0adf9959216b96bec444f325f1e493d4aa344497 # v6.14.0 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 with: builder: ${{ steps.buildx.outputs.name }} build-args: | From 9fa5066d35457864552e31eb16f414f567b0283a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 27 Feb 2025 01:41:23 +0000 Subject: [PATCH 250/426] chore(deps): update docker/metadata-action action to v5.7.0 (main) (#4518) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 50a6a36f10..6fef3deb8f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -164,7 +164,7 @@ jobs: run: | hack/build/ci/prepare-build-variables.sh - name: Docker metadata - uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 id: meta with: images: dynatrace/dynatrace-operator diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fae4f5b65c..483b348b59 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -21,7 +21,7 @@ jobs: run: | hack/build/ci/prepare-build-variables.sh - name: Docker metadata - uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 id: meta with: images: dynatrace/dynatrace-operator From 5b7acf043e4e7b09dffc0ccd2c1402f4a49875f8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 27 Feb 2025 07:01:14 +0000 Subject: [PATCH 251/426] chore(deps): update codecov/codecov-action action to v5.4.0 (main) (#4521) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6fef3deb8f..77519e1094 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -67,7 +67,7 @@ jobs: run: | make go/check-coverage - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 + uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 with: fail_ci_if_error: true verbose: true From 60f6c61cb9eeecf60d1f6c2acbc3564085f51ce3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 27 Feb 2025 07:10:18 +0000 Subject: [PATCH 252/426] chore(deps): update docker/setup-buildx-action action to v3.10.0 (main) (#4519) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 784eef1294..fdb2956e24 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -16,7 +16,7 @@ runs: - name: Set up QEMU uses: docker/setup-qemu-action@4574d27a4764455b42196d70a065bc6853246a25 # v3.4.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3.9.0 + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - name: Set up Golang uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: From 250ef85cc06e7a6e20cf9039fbfdb1269793978b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 27 Feb 2025 07:49:55 +0000 Subject: [PATCH 253/426] chore(deps): update docker/setup-qemu-action action to v3.5.0 (main) (#4520) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index fdb2956e24..6e3e9ab5a7 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -14,7 +14,7 @@ runs: using: "composite" steps: - name: Set up QEMU - uses: docker/setup-qemu-action@4574d27a4764455b42196d70a065bc6853246a25 # v3.4.0 + uses: docker/setup-qemu-action@5964de0df58d5ad28b04d8fe2e6b80ad47105b91 # v3.5.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - name: Set up Golang From 78ecc38bccecf00c9b1623970746a7e22e01fdb5 Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Thu, 27 Feb 2025 16:47:03 +0100 Subject: [PATCH 254/426] Creates AG TLS certificate (pem) if tlsSecretName is empty and the feature flags is enabled (#4494) --- doc/api/feature-flags.md | 4 +- doc/e2e/features.md | 18 +- hack/doc/gen_e2e_features.sh | 3 +- hack/doc/gen_feature_flags.sh | 3 +- pkg/api/v1beta3/dynakube/activegate/props.go | 28 ++- pkg/api/v1beta3/dynakube/activegate/spec.go | 2 + pkg/api/v1beta3/dynakube/activegate_props.go | 1 + pkg/api/v1beta3/dynakube/certs.go | 2 +- pkg/api/v1beta3/dynakube/feature_flags.go | 7 + .../internal/capability/reconciler.go | 11 +- .../internal/capability/reconciler_test.go | 32 ++-- .../statefulset/builder/modifiers/certs.go | 2 +- .../activegate/internal/tls/conditions.go | 5 + .../activegate/internal/tls/config.go | 7 + .../activegate/internal/tls/reconciler.go | 172 ++++++++++++++++++ .../internal/tls/reconciler_test.go | 137 ++++++++++++++ .../dynakube/activegate/reconciler.go | 4 +- .../dynakube/activegate/reconciler_test.go | 6 +- .../dynakube/extension/eec/reconciler_test.go | 49 ++++- .../dynakube/extension/eec/statefulset.go | 8 +- .../dynakube/extension/tls/reconciler.go | 14 +- .../dynakube/oneagent/daemonset/volumes.go | 2 +- .../oneagent/daemonset/volumes_test.go | 53 +++++- pkg/util/certificates/certificates.go | 12 ++ .../cloudnative/codemodules/codemodules.go | 40 +++- test/features/cloudnative/container.go | 16 +- 26 files changed, 569 insertions(+), 69 deletions(-) create mode 100644 pkg/controllers/dynakube/activegate/internal/tls/conditions.go create mode 100644 pkg/controllers/dynakube/activegate/internal/tls/config.go create mode 100644 pkg/controllers/dynakube/activegate/internal/tls/reconciler.go create mode 100644 pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go diff --git a/doc/api/feature-flags.md b/doc/api/feature-flags.md index 0ae8bb9eaf..4f8cbce445 100644 --- a/doc/api/feature-flags.md +++ b/doc/api/feature-flags.md @@ -35,6 +35,8 @@ const ( AnnotationFeatureAutomaticK8sApiMonitoringClusterName = AnnotationFeaturePrefix + "automatic-kubernetes-api-monitoring-cluster-name" AnnotationFeatureK8sAppEnabled = AnnotationFeaturePrefix + "k8s-app-enabled" + AnnotationFeatureActiveGateAutomaticTLSCertificate = AnnotationFeaturePrefix + "automatic-tls-certificate" + AnnotationFeatureNoProxy = AnnotationFeaturePrefix + "no-proxy" // Deprecated: AnnotationFeatureOneAgentIgnoreProxy use AnnotationFeatureNoProxy instead. @@ -74,7 +76,7 @@ const ( -## func [MountAttemptsToTimeout]() +## func [MountAttemptsToTimeout]() ```go func MountAttemptsToTimeout(maxAttempts int) string diff --git a/doc/e2e/features.md b/doc/e2e/features.md index 18d350a903..0af2d44ded 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -128,8 +128,8 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" ## Index - [func AssessActiveGateContainer(builder *features.FeatureBuilder, dk *dynakube.DynaKube, trustedCAs []byte)](<#AssessActiveGateContainer>) -- [func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrt []byte, trustedCAs []byte)](<#AssessOneAgentContainer>) -- [func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrt []byte, trustedCAs []byte)](<#AssessSampleContainer>) +- [func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrtFunc func() []byte, trustedCAs []byte)](<#AssessOneAgentContainer>) +- [func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrtFunc func() []byte, trustedCAs []byte)](<#AssessSampleContainer>) - [func AssessSampleInitContainers(builder *features.FeatureBuilder, sampleApp *sample.App)](<#AssessSampleInitContainers>) - [func DefaultCloudNativeSpec() *oneagent.CloudNativeFullStackSpec](<#DefaultCloudNativeSpec>) @@ -146,7 +146,7 @@ func AssessActiveGateContainer(builder *features.FeatureBuilder, dk *dynakube.Dy ## func [AssessOneAgentContainer]() ```go -func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrt []byte, trustedCAs []byte) +func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrtFunc func() []byte, trustedCAs []byte) ``` @@ -154,7 +154,7 @@ func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrt []byte, tru ## func [AssessSampleContainer]() ```go -func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrt []byte, trustedCAs []byte) +func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrtFunc func() []byte, trustedCAs []byte) ``` @@ -189,7 +189,7 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/codemo -## func [InstallFromImage]() +## func [InstallFromImage]() ```go func InstallFromImage(t *testing.T) features.Feature @@ -199,7 +199,7 @@ Verification that the storage in the CSI driver directory does not increase when -## func [WithProxy]() +## func [WithProxy]() ```go func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature @@ -215,7 +215,7 @@ Connectivity in the dynatrace namespace and sample application namespace is rest -## func [WithProxyAndAGCert]() +## func [WithProxyAndAGCert]() ```go func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature @@ -223,7 +223,7 @@ func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature -## func [WithProxyCA]() +## func [WithProxyCA]() ```go func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature @@ -231,7 +231,7 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature -## func [WithProxyCAAndAGCert]() +## func [WithProxyCAAndAGCert]() ```go func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature diff --git a/hack/doc/gen_e2e_features.sh b/hack/doc/gen_e2e_features.sh index d8346242e8..c4f08bc737 100755 --- a/hack/doc/gen_e2e_features.sh +++ b/hack/doc/gen_e2e_features.sh @@ -23,7 +23,8 @@ done # remove gomarkdoc headers and add custom one output=$(echo "${output}" | sed s/"$gomarkdoc_header"//) -output="${script_header}\n${output}" +output="${script_header} +${output}" # write output to file mkdir -p $output_dir diff --git a/hack/doc/gen_feature_flags.sh b/hack/doc/gen_feature_flags.sh index cc4436725b..b3021758cf 100755 --- a/hack/doc/gen_feature_flags.sh +++ b/hack/doc/gen_feature_flags.sh @@ -17,7 +17,8 @@ output=$(echo "${output}" | sed '$d') # remove gomarkdoc headers and add custom one output=$(echo "${output}" | sed s/"$gomarkdoc_header"//) -output="${script_header}\n${output}" +output="${script_header} +${output}" # write output to file mkdir -p $output_dir diff --git a/pkg/api/v1beta3/dynakube/activegate/props.go b/pkg/api/v1beta3/dynakube/activegate/props.go index a7e9e70120..639cf51d9f 100644 --- a/pkg/api/v1beta3/dynakube/activegate/props.go +++ b/pkg/api/v1beta3/dynakube/activegate/props.go @@ -10,6 +10,7 @@ import ( const ( TenantSecretSuffix = "-activegate-tenant-secret" + TlsSecretSuffix = "-activegate-tls-secret" ConnectionInfoConfigMapSuffix = "-activegate-connection-info" AuthTokenSecretSuffix = "-activegate-authtoken-secret" DefaultImageRegistrySubPath = "/linux/activegate" @@ -23,6 +24,10 @@ func (ag *Spec) SetName(name string) { ag.name = name } +func (ag *Spec) SetAutomaticTLSCertificate(enabled bool) { + ag.automaticTLSCertificateEnabled = enabled +} + func (ag *Spec) SetExtensionsDependency(isEnabled bool) { ag.enabledDependencies.extensions = isEnabled } @@ -92,20 +97,37 @@ func (ag *Spec) IsMetricsIngestEnabled() bool { return ag.IsMode(MetricsIngestCapability.DisplayName) } +func (ag *Spec) IsAutomaticTlsSecretEnabled() bool { + return ag.automaticTLSCertificateEnabled +} + func (ag *Spec) HasCaCert() bool { - return ag.IsEnabled() && ag.TlsSecretName != "" + return ag.IsEnabled() && (ag.TlsSecretName != "" || ag.IsAutomaticTlsSecretEnabled()) } -// ActivegateTenantSecret returns the name of the secret containing tenant UUID, token and communication endpoints for ActiveGate. +// GetTenantSecretName returns the name of the secret containing tenant UUID, token and communication endpoints for ActiveGate. func (ag *Spec) GetTenantSecretName() string { return ag.name + TenantSecretSuffix } -// ActiveGateAuthTokenSecret returns the name of the secret containing the ActiveGateAuthToken, which is mounted to the AGs. +// GetAuthTokenSecretName returns the name of the secret containing the ActiveGateAuthToken, which is mounted to the AGs. func (ag *Spec) GetAuthTokenSecretName() string { return ag.name + AuthTokenSecretSuffix } +// GetTLSSecretName returns the name of the AG TLS secret. +func (ag *Spec) GetTLSSecretName() string { + if ag.TlsSecretName != "" { + return ag.TlsSecretName + } + + if ag.IsAutomaticTlsSecretEnabled() { + return ag.name + TlsSecretSuffix + } + + return "" +} + func (ag *Spec) GetConnectionInfoConfigMapName() string { return ag.name + ConnectionInfoConfigMapSuffix } diff --git a/pkg/api/v1beta3/dynakube/activegate/spec.go b/pkg/api/v1beta3/dynakube/activegate/spec.go index ff1231c57c..f4323e6624 100644 --- a/pkg/api/v1beta3/dynakube/activegate/spec.go +++ b/pkg/api/v1beta3/dynakube/activegate/spec.go @@ -114,6 +114,8 @@ type Spec struct { enabledDependencies dependencies + automaticTLSCertificateEnabled bool + // UseEphemeralVolume UseEphemeralVolume bool `json:"useEphemeralVolume,omitempty"` } diff --git a/pkg/api/v1beta3/dynakube/activegate_props.go b/pkg/api/v1beta3/dynakube/activegate_props.go index 4c9bdc2234..4e4febc371 100644 --- a/pkg/api/v1beta3/dynakube/activegate_props.go +++ b/pkg/api/v1beta3/dynakube/activegate_props.go @@ -7,6 +7,7 @@ import ( func (dk *DynaKube) ActiveGate() *activegate.ActiveGate { dk.Spec.ActiveGate.SetApiUrl(dk.ApiUrl()) dk.Spec.ActiveGate.SetName(dk.Name) + dk.Spec.ActiveGate.SetAutomaticTLSCertificate(dk.FeatureActiveGateAutomaticTLSCertificate()) dk.Spec.ActiveGate.SetExtensionsDependency(dk.IsExtensionsEnabled()) dk.Spec.ActiveGate.SetOTLPingestDependency(dk.IsOTLPingestEnabled()) diff --git a/pkg/api/v1beta3/dynakube/certs.go b/pkg/api/v1beta3/dynakube/certs.go index 12a1aa53d5..f6e5aa1068 100644 --- a/pkg/api/v1beta3/dynakube/certs.go +++ b/pkg/api/v1beta3/dynakube/certs.go @@ -48,7 +48,7 @@ func (dk *DynaKube) TrustedCAs(ctx context.Context, kubeReader client.Reader) ([ func (dk *DynaKube) ActiveGateTLSCert(ctx context.Context, kubeReader client.Reader) ([]byte, error) { if dk.ActiveGate().HasCaCert() { - secretName := dk.Spec.ActiveGate.TlsSecretName + secretName := dk.Spec.ActiveGate.GetTLSSecretName() var tlsSecret corev1.Secret diff --git a/pkg/api/v1beta3/dynakube/feature_flags.go b/pkg/api/v1beta3/dynakube/feature_flags.go index 4f67e6d2ce..fd45eaf1f1 100644 --- a/pkg/api/v1beta3/dynakube/feature_flags.go +++ b/pkg/api/v1beta3/dynakube/feature_flags.go @@ -47,6 +47,8 @@ const ( AnnotationFeatureAutomaticK8sApiMonitoringClusterName = AnnotationFeaturePrefix + "automatic-kubernetes-api-monitoring-cluster-name" AnnotationFeatureK8sAppEnabled = AnnotationFeaturePrefix + "k8s-app-enabled" + AnnotationFeatureActiveGateAutomaticTLSCertificate = AnnotationFeaturePrefix + "automatic-tls-certificate" + // dtClient. AnnotationFeatureNoProxy = AnnotationFeaturePrefix + "no-proxy" @@ -129,6 +131,11 @@ func (dk *DynaKube) FeatureNoProxy() string { return dk.getFeatureFlagRaw(AnnotationFeatureNoProxy) } +// FeatureActiveGateAutomaticTLSCertificate is a feature flag to enable automatic creation of AG TLS certificate if TrustedCAs are used. +func (dk *DynaKube) FeatureActiveGateAutomaticTLSCertificate() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureActiveGateAutomaticTLSCertificate) == truePhrase +} + // FeatureOneAgentMaxUnavailable is a feature flag to configure maxUnavailable on the OneAgent DaemonSets rolling upgrades. func (dk *DynaKube) FeatureOneAgentMaxUnavailable() int { return dk.getFeatureFlagInt(AnnotationFeatureOneAgentMaxUnavailable, 1) diff --git a/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go b/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go index 67e6e5a191..420ac86db9 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go @@ -21,20 +21,22 @@ type Reconciler struct { capability capability.Capability statefulsetReconciler controllers.Reconciler customPropertiesReconciler controllers.Reconciler + tlsSecretReconciler controllers.Reconciler dk *dynakube.DynaKube } -func NewReconciler(clt client.Client, capability capability.Capability, dk *dynakube.DynaKube, statefulsetReconciler controllers.Reconciler, customPropertiesReconciler controllers.Reconciler) controllers.Reconciler { +func NewReconciler(clt client.Client, capability capability.Capability, dk *dynakube.DynaKube, statefulsetReconciler controllers.Reconciler, customPropertiesReconciler controllers.Reconciler, tlsSecretReconciler controllers.Reconciler) controllers.Reconciler { //nolint:revive return &Reconciler{ statefulsetReconciler: statefulsetReconciler, customPropertiesReconciler: customPropertiesReconciler, + tlsSecretReconciler: tlsSecretReconciler, capability: capability, dk: dk, client: clt, } } -type NewReconcilerFunc = func(clt client.Client, capability capability.Capability, dk *dynakube.DynaKube, statefulsetReconciler controllers.Reconciler, customPropertiesReconciler controllers.Reconciler) controllers.Reconciler +type NewReconcilerFunc = func(clt client.Client, capability capability.Capability, dk *dynakube.DynaKube, statefulsetReconciler controllers.Reconciler, customPropertiesReconciler controllers.Reconciler, tlsSecretReconciler controllers.Reconciler) controllers.Reconciler func (r *Reconciler) Reconcile(ctx context.Context) error { err := r.customPropertiesReconciler.Reconcile(ctx) @@ -52,6 +54,11 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { return err } + err = r.tlsSecretReconciler.Reconcile(ctx) + if err != nil { + return err + } + err = r.statefulsetReconciler.Reconcile(ctx) return errors.WithStack(err) diff --git a/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go index 121d2400f5..ff6e146c9d 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go @@ -93,8 +93,9 @@ func TestReconcile(t *testing.T) { dk := buildDynakube(capabilitiesWithService) mockStatefulSetReconciler := getMockReconciler(t, nil) mockCustompropertiesReconciler := getMockReconciler(t, nil) + mockTlsSecretReconciler := getMockReconciler(t, nil) - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) err := r.Reconcile(context.Background()) @@ -107,8 +108,9 @@ func TestReconcile(t *testing.T) { dk := buildDynakube(capabilitiesWithoutService) mockStatefulSetReconciler := getMockReconciler(t, errors.New("")) mockCustompropertiesReconciler := getMockReconciler(t, nil) + mockTlsSecretReconciler := getMockReconciler(t, nil) - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) err := r.Reconcile(context.Background()) @@ -121,8 +123,9 @@ func TestReconcile(t *testing.T) { dk := buildDynakube(capabilitiesWithoutService) mockStatefulSetReconciler := getMockReconciler(t) mockCustompropertiesReconciler := getMockReconciler(t, errors.New("")) + mockTlsSecretReconciler := getMockReconciler(t, nil) - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) err := r.Reconcile(context.Background()) @@ -134,8 +137,9 @@ func TestReconcile(t *testing.T) { dk := buildDynakube(capabilitiesWithoutService) mockStatefulSetReconciler := getMockReconciler(t, errors.New("")) mockCustompropertiesReconciler := getMockReconciler(t, errors.New("")) + mockTlsSecretReconciler := getMockReconciler(t, nil) - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) err := r.Reconcile(context.Background()) @@ -145,8 +149,9 @@ func TestReconcile(t *testing.T) { dk := buildDynakube(capabilitiesWithService) mockStatefulSetReconciler := getMockReconciler(t, nil) mockCustompropertiesReconciler := getMockReconciler(t, nil) + mockTlsSecretReconciler := getMockReconciler(t, nil) - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) err := r.Reconcile(context.Background()) @@ -166,8 +171,9 @@ func TestReconcile(t *testing.T) { dk := buildDynakube(capabilitiesWithoutService) mockStatefulSetReconciler := getMockReconciler(t, nil) mockCustompropertiesReconciler := getMockReconciler(t, nil) + mockTlsSecretReconciler := getMockReconciler(t, nil) - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) err := r.Reconcile(context.Background()) @@ -191,9 +197,10 @@ func TestCreateOrUpdateService(t *testing.T) { dk := buildDynakube(capabilitiesWithService) mockStatefulSetReconciler := getMockReconciler(t, nil) mockCustompropertiesReconciler := getMockReconciler(t, nil) + mockTlsSecretReconciler := getMockReconciler(t, nil) t.Run(`create service works`, func(t *testing.T) { - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) service := &corev1.Service{} @@ -210,7 +217,7 @@ func TestCreateOrUpdateService(t *testing.T) { assert.NotNil(t, service) }) t.Run(`ports get updated`, func(t *testing.T) { - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) err := r.createOrUpdateService(context.Background()) @@ -238,7 +245,7 @@ func TestCreateOrUpdateService(t *testing.T) { require.NotEqual(t, actualService.Spec.Ports, service.Spec.Ports) }) t.Run(`labels get updated`, func(t *testing.T) { - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) err := r.createOrUpdateService(context.Background()) @@ -270,8 +277,9 @@ func TestPortsAreOutdated(t *testing.T) { dk := buildDynakube(capabilitiesWithService) mockStatefulSetReconciler := getMockReconciler(t, nil) mockCustompropertiesReconciler := getMockReconciler(t, nil) + mockTlsSecretReconciler := getMockReconciler(t, nil) - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) desiredService := CreateService(r.dk, r.capability.ShortName()) @@ -298,7 +306,9 @@ func TestLabelsAreOutdated(t *testing.T) { dk := buildDynakube(capabilitiesWithService) mockStatefulSetReconciler := getMockReconciler(t, nil) mockCustompropertiesReconciler := getMockReconciler(t, nil) - r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler).(*Reconciler) + mockTlsSecretReconciler := getMockReconciler(t, nil) + + r := NewReconciler(clt, capability.NewMultiCapability(dk), dk, mockStatefulSetReconciler, mockCustompropertiesReconciler, mockTlsSecretReconciler).(*Reconciler) verifyReconciler(t, r) desiredService := CreateService(r.dk, r.capability.ShortName()) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs.go index df892934f7..5c22cf1b93 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs.go @@ -48,7 +48,7 @@ func (mod CertificatesModifier) getVolumes() []corev1.Volume { Name: jettyCerts, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: mod.dk.Spec.ActiveGate.TlsSecretName, + SecretName: mod.dk.ActiveGate().GetTLSSecretName(), }, }, }, diff --git a/pkg/controllers/dynakube/activegate/internal/tls/conditions.go b/pkg/controllers/dynakube/activegate/internal/tls/conditions.go new file mode 100644 index 0000000000..5a61bbe7f1 --- /dev/null +++ b/pkg/controllers/dynakube/activegate/internal/tls/conditions.go @@ -0,0 +1,5 @@ +package tls + +const ( + conditionType = "TLSSecret" +) diff --git a/pkg/controllers/dynakube/activegate/internal/tls/config.go b/pkg/controllers/dynakube/activegate/internal/tls/config.go new file mode 100644 index 0000000000..fca05602f6 --- /dev/null +++ b/pkg/controllers/dynakube/activegate/internal/tls/config.go @@ -0,0 +1,7 @@ +package tls + +import "github.com/Dynatrace/dynatrace-operator/pkg/logd" + +var ( + log = logd.Get().WithName("dynakube-activegate-tls-secret") +) diff --git a/pkg/controllers/dynakube/activegate/internal/tls/reconciler.go b/pkg/controllers/dynakube/activegate/internal/tls/reconciler.go new file mode 100644 index 0000000000..606d509daa --- /dev/null +++ b/pkg/controllers/dynakube/activegate/internal/tls/reconciler.go @@ -0,0 +1,172 @@ +package tls + +import ( + "context" + "crypto/x509" + "net" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/certificates" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + activeGateSelfSignedTLSCommonNameSuffix = "activegate" + + tlsCrtDataName = "server.crt" +) + +type Reconciler struct { + client client.Client + apiReader client.Reader + dk *dynakube.DynaKube + timeProvider *timeprovider.Provider +} + +type ReconcilerBuilder func(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler + +func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler { + return &Reconciler{ + client: client, + dk: dk, + apiReader: apiReader, + timeProvider: timeprovider.New(), + } +} + +func (r *Reconciler) Reconcile(ctx context.Context) error { + if r.dk.ActiveGate().IsEnabled() && r.dk.ActiveGate().IsAutomaticTlsSecretEnabled() && r.dk.ActiveGate().TlsSecretName == "" { + return r.reconcileSelfSignedTLSSecret(ctx) + } + + if meta.FindStatusCondition(*r.dk.Conditions(), conditionType) == nil { + return nil + } + defer meta.RemoveStatusCondition(r.dk.Conditions(), conditionType) + + return r.deleteSelfSignedTLSSecret(ctx) +} + +func (r *Reconciler) reconcileSelfSignedTLSSecret(ctx context.Context) error { + query := k8ssecret.Query(r.client, r.client, log) + + _, err := query.Get(ctx, types.NamespacedName{ + Name: r.dk.ActiveGate().GetTLSSecretName(), + Namespace: r.dk.Namespace, + }) + + if err != nil && k8serrors.IsNotFound(err) { + return r.createSelfSignedTLSSecret(ctx) + } + + if err != nil { + conditions.SetKubeApiError(r.dk.Conditions(), conditionType, err) + + return err + } + + return nil +} + +func (r *Reconciler) deleteSelfSignedTLSSecret(ctx context.Context) error { + query := k8ssecret.Query(r.client, r.client, log) + + return query.Delete(ctx, &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: r.dk.ActiveGate().GetTLSSecretName(), + Namespace: r.dk.Namespace, + }, + }) +} + +func (r *Reconciler) createSelfSignedTLSSecret(ctx context.Context) error { + cert, err := certificates.New(r.timeProvider) + if err != nil { + conditions.SetSecretGenFailed(r.dk.Conditions(), conditionType, err) + + return err + } + + cert.Cert.DNSNames = certificates.AltNames(r.dk.Name, r.dk.Namespace, activeGateSelfSignedTLSCommonNameSuffix) + cert.Cert.KeyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment + cert.Cert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} + cert.Cert.Subject.CommonName = certificates.CommonName(r.dk.Name, r.dk.Namespace, activeGateSelfSignedTLSCommonNameSuffix) + + ipAddresses, err := getCertificateAltIPs(r.dk.Status.ActiveGate.ServiceIPs) + if err != nil { + conditions.SetSecretGenFailed(r.dk.Conditions(), conditionType, err) + + return err + } + + cert.Cert.IPAddresses = ipAddresses + + err = cert.SelfSign() + if err != nil { + conditions.SetSecretGenFailed(r.dk.Conditions(), conditionType, err) + + return err + } + + pemCert, pemPk, err := cert.ToPEM() + if err != nil { + conditions.SetSecretGenFailed(r.dk.Conditions(), conditionType, err) + + return err + } + + coreLabels := k8slabels.NewCoreLabels(r.dk.Name, k8slabels.ActiveGateComponentLabel) + secretData := map[string][]byte{ + consts.TLSCrtDataName: pemCert, + consts.TLSKeyDataName: pemPk, + tlsCrtDataName: pemCert, + } + + secret, err := k8ssecret.Build(r.dk, r.dk.ActiveGate().GetTLSSecretName(), secretData, k8ssecret.SetLabels(coreLabels.BuildLabels())) + if err != nil { + conditions.SetSecretGenFailed(r.dk.Conditions(), conditionType, err) + + return err + } + + secret.Type = corev1.SecretTypeOpaque + + query := k8ssecret.Query(r.client, r.client, log) + + err = query.Create(ctx, secret) + if err != nil { + conditions.SetKubeApiError(r.dk.Conditions(), conditionType, err) + + return err + } + + conditions.SetSecretCreated(r.dk.Conditions(), conditionType, secret.Name) + + return nil +} + +func getCertificateAltIPs(ips []string) ([]net.IP, error) { + altIPs := []net.IP{} + + for _, ip := range ips { + netIP := net.ParseIP(ip) + if netIP == nil { + return nil, errors.Errorf("failed to parse '%s' IP address", ip) + } + + altIPs = append(altIPs, netIP) + } + + return altIPs, nil +} diff --git a/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go new file mode 100644 index 0000000000..09dc93e5de --- /dev/null +++ b/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go @@ -0,0 +1,137 @@ +package tls + +import ( + "context" + "fmt" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + testNamespace = "test-namespace" + testDynakubeName = "test-dynakube" +) + +func TestReconciler_Reconcile(t *testing.T) { + t.Run(`ActiveGate disabled`, func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", + }, + Namespace: testNamespace, + Name: testDynakubeName, + }, + } + fakeClient := fake.NewClient() + r := NewReconciler(fakeClient, fakeClient, dk) + err := r.Reconcile(context.Background()) + require.NoError(t, err) + + agTLSSecret := corev1.Secret{} + err = r.client.Get(context.Background(), client.ObjectKey{Name: r.dk.ActiveGate().GetTLSSecretName(), Namespace: r.dk.Namespace}, &agTLSSecret) + + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err)) + }) + + t.Run(`custom ActiveGate TLS secret exists`, func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", + }, + Namespace: testNamespace, + Name: testDynakubeName, + }, + Spec: dynakube.DynaKubeSpec{ + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.RoutingCapability.DisplayName, + }, + TlsSecretName: "test", + }, + }, + } + fakeClient := fake.NewClient() + r := NewReconciler(fakeClient, fakeClient, dk) + err := r.Reconcile(context.Background()) + require.NoError(t, err) + + agTLSSecret := corev1.Secret{} + err = r.client.Get(context.Background(), client.ObjectKey{Name: r.dk.ActiveGate().GetTLSSecretName(), Namespace: r.dk.Namespace}, &agTLSSecret) + + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err)) + }) + + t.Run(`automatic-tls-certificate feature disabled`, func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: testNamespace, + Name: testDynakubeName, + }, + Spec: dynakube.DynaKubeSpec{ + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.RoutingCapability.DisplayName, + }, + }, + }, + } + fakeClient := fake.NewClient() + r := NewReconciler(fakeClient, fakeClient, dk) + err := r.Reconcile(context.Background()) + require.NoError(t, err) + + agTLSSecret := corev1.Secret{} + err = r.client.Get(context.Background(), client.ObjectKey{Name: r.dk.ActiveGate().GetTLSSecretName(), Namespace: r.dk.Namespace}, &agTLSSecret) + + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err)) + }) + + t.Run(`secret created`, func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", + }, + Namespace: testNamespace, + Name: testDynakubeName, + }, + Spec: dynakube.DynaKubeSpec{ + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.RoutingCapability.DisplayName, + }, + }, + }, + } + fakeClient := fake.NewClient() + r := NewReconciler(fakeClient, fakeClient, dk) + err := r.Reconcile(context.Background()) + require.NoError(t, err) + + agTLSSecret := corev1.Secret{} + err = r.client.Get(context.Background(), client.ObjectKey{Name: r.dk.ActiveGate().GetTLSSecretName(), Namespace: r.dk.Namespace}, &agTLSSecret) + + require.NoError(t, err) + + condition := meta.FindStatusCondition(r.dk.Status.Conditions, conditionType) + assert.Equal(t, metav1.ConditionTrue, condition.Status) + assert.Equal(t, conditions.SecretCreatedReason, condition.Reason) + assert.Equal(t, fmt.Sprintf("%s created", agTLSSecret.Name), condition.Message) + }) +} diff --git a/pkg/controllers/dynakube/activegate/reconciler.go b/pkg/controllers/dynakube/activegate/reconciler.go index e8d2a02496..7f219ec45c 100644 --- a/pkg/controllers/dynakube/activegate/reconciler.go +++ b/pkg/controllers/dynakube/activegate/reconciler.go @@ -10,6 +10,7 @@ import ( capabilityInternal "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/customproperties" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/tls" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" agconnectioninfo "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dtpullsecret" @@ -180,8 +181,9 @@ func extractPublicData(dk *dynakube.DynaKube) map[string]string { func (r *Reconciler) createCapability(ctx context.Context, agCapability capability.Capability) error { customPropertiesReconciler := r.newCustomPropertiesReconcilerFunc(r.dk.ActiveGate().GetServiceAccountOwner(), agCapability.Properties().CustomProperties) //nolint:typeCheck statefulsetReconciler := r.newStatefulsetReconcilerFunc(r.client, r.apiReader, r.dk, agCapability) //nolint:typeCheck + tlsSecretReconciler := tls.NewReconciler(r.client, r.apiReader, r.dk) - capabilityReconciler := r.newCapabilityReconcilerFunc(r.client, agCapability, r.dk, statefulsetReconciler, customPropertiesReconciler) + capabilityReconciler := r.newCapabilityReconcilerFunc(r.client, agCapability, r.dk, statefulsetReconciler, customPropertiesReconciler, tlsSecretReconciler) return capabilityReconciler.Reconcile(ctx) } diff --git a/pkg/controllers/dynakube/activegate/reconciler_test.go b/pkg/controllers/dynakube/activegate/reconciler_test.go index 272d0698f8..d5e7525b60 100644 --- a/pkg/controllers/dynakube/activegate/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/reconciler_test.go @@ -163,7 +163,7 @@ func TestReconciler_Reconcile(t *testing.T) { newStatefulsetReconcilerFunc: func(_ client.Client, _ client.Reader, _ *dynakube.DynaKube, _ capability.Capability) controllers.Reconciler { return fakeReconciler }, - newCapabilityReconcilerFunc: func(_ client.Client, _ capability.Capability, _ *dynakube.DynaKube, _ controllers.Reconciler, _ controllers.Reconciler) controllers.Reconciler { + newCapabilityReconcilerFunc: func(_ client.Client, _ capability.Capability, _ *dynakube.DynaKube, _ controllers.Reconciler, _ controllers.Reconciler, _ controllers.Reconciler) controllers.Reconciler { return fakeReconciler }, newCustomPropertiesReconcilerFunc: func(_ string, customPropertiesSource *value.Source) controllers.Reconciler { @@ -184,7 +184,7 @@ func TestReconciler_Reconcile(t *testing.T) { newStatefulsetReconcilerFunc: func(_ client.Client, _ client.Reader, _ *dynakube.DynaKube, _ capability.Capability) controllers.Reconciler { return fakeReconciler }, - newCapabilityReconcilerFunc: func(_ client.Client, _ capability.Capability, _ *dynakube.DynaKube, _ controllers.Reconciler, _ controllers.Reconciler) controllers.Reconciler { + newCapabilityReconcilerFunc: func(_ client.Client, _ capability.Capability, _ *dynakube.DynaKube, _ controllers.Reconciler, _ controllers.Reconciler, _ controllers.Reconciler) controllers.Reconciler { return fakeReconciler }, newCustomPropertiesReconcilerFunc: func(_ string, customPropertiesSource *value.Source) controllers.Reconciler { @@ -545,7 +545,7 @@ func TestReconcile_ActivegateConfigMap(t *testing.T) { newStatefulsetReconcilerFunc: func(_ client.Client, _ client.Reader, _ *dynakube.DynaKube, _ capability.Capability) controllers.Reconciler { return fakeReconciler }, - newCapabilityReconcilerFunc: func(_ client.Client, _ capability.Capability, _ *dynakube.DynaKube, _ controllers.Reconciler, _ controllers.Reconciler) controllers.Reconciler { + newCapabilityReconcilerFunc: func(_ client.Client, _ capability.Capability, _ *dynakube.DynaKube, _ controllers.Reconciler, _ controllers.Reconciler, _ controllers.Reconciler) controllers.Reconciler { return fakeReconciler }, newCustomPropertiesReconcilerFunc: func(_ string, _ *value.Source) controllers.Reconciler { diff --git a/pkg/controllers/dynakube/extension/eec/reconciler_test.go b/pkg/controllers/dynakube/extension/eec/reconciler_test.go index 91e4f5e999..08ae11b2e6 100644 --- a/pkg/controllers/dynakube/extension/eec/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/eec/reconciler_test.go @@ -971,7 +971,7 @@ func TestActiveGateVolumes(t *testing.T) { }, } - t.Run("ActiveGate tls certificate is mounted to EEC", func(t *testing.T) { + t.Run("volumes with custom ActiveGate tls certificate", func(t *testing.T) { dk := getTestDynakube() dk.Spec.ActiveGate.TlsSecretName = tlsSecretName statefulSet := getStatefulset(t, dk) @@ -983,7 +983,8 @@ func TestActiveGateVolumes(t *testing.T) { require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) require.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) }) - t.Run("ActiveGate tls certificate is not mounted to EEC", func(t *testing.T) { + + t.Run("volumes without custom ActiveGate tls certificate", func(t *testing.T) { dk := getTestDynakube() statefulSet := getStatefulset(t, dk) @@ -994,4 +995,48 @@ func TestActiveGateVolumes(t *testing.T) { require.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) require.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) }) + + t.Run("volumes with TrustedCAs certificates", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.TrustedCAs = "custom-tls" + statefulSet := getStatefulset(t, dk) + + require.NotEmpty(t, statefulSet.Spec.Template.Spec.Containers) + require.NotEmpty(t, statefulSet.Spec.Template.Spec.Volumes) + + require.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, expectedEnvVar) + require.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + require.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) + }) + + t.Run("volumes with automatically created ActiveGate tls certificate", func(t *testing.T) { + dk := getTestDynakube() + dk.Annotations[dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate] = "true" + dk.Spec.TrustedCAs = "custom-tls" + + expectedVolume := corev1.Volume{ + Name: activeGateTrustedCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + DefaultMode: &defaultMode, + SecretName: dk.ActiveGate().GetTLSSecretName(), + Items: []corev1.KeyToPath{ + { + Key: activeGateTrustedCertSecretKeyPath, + Path: activeGateTrustedCertSecretKeyPath, + }, + }, + }, + }, + } + + statefulSet := getStatefulset(t, dk) + + require.NotEmpty(t, statefulSet.Spec.Template.Spec.Containers) + require.NotEmpty(t, statefulSet.Spec.Template.Spec.Volumes) + + require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, expectedEnvVar) + require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + require.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) + }) } diff --git a/pkg/controllers/dynakube/extension/eec/statefulset.go b/pkg/controllers/dynakube/extension/eec/statefulset.go index 86cd31282e..41f6c40844 100644 --- a/pkg/controllers/dynakube/extension/eec/statefulset.go +++ b/pkg/controllers/dynakube/extension/eec/statefulset.go @@ -254,7 +254,7 @@ func buildContainerEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { {Name: envHttpsPrivKeyPathPem, Value: envEecHttpsPrivKeyPathPem}, } - if dk.Spec.ActiveGate.TlsSecretName != "" { + if dk.ActiveGate().HasCaCert() { containerEnvs = append(containerEnvs, corev1.EnvVar{Name: envActiveGateTrustedCertName, Value: envActiveGateTrustedCert}) } @@ -312,7 +312,7 @@ func buildContainerVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { }) } - if dk.Spec.ActiveGate.TlsSecretName != "" { + if dk.ActiveGate().HasCaCert() { volumeMounts = append(volumeMounts, corev1.VolumeMount{ Name: activeGateTrustedCertVolumeName, MountPath: activeGateTrustedCertMountPath, @@ -388,14 +388,14 @@ func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { }) } - if dk.Spec.ActiveGate.TlsSecretName != "" { + if dk.ActiveGate().HasCaCert() { defaultMode := int32(420) o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ Name: activeGateTrustedCertVolumeName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ DefaultMode: &defaultMode, - SecretName: dk.Spec.ActiveGate.TlsSecretName, + SecretName: dk.ActiveGate().GetTLSSecretName(), Items: []corev1.KeyToPath{ { Key: activeGateTrustedCertSecretKeyPath, diff --git a/pkg/controllers/dynakube/extension/tls/reconciler.go b/pkg/controllers/dynakube/extension/tls/reconciler.go index 01196c5bb6..3903a9ea34 100644 --- a/pkg/controllers/dynakube/extension/tls/reconciler.go +++ b/pkg/controllers/dynakube/extension/tls/reconciler.go @@ -21,7 +21,7 @@ import ( ) const ( - extensionsSelfSignedTLSCommonNameSuffix = "-extensions-controller.dynatrace" + extensionsSelfSignedTLSCommonNameSuffix = "extensions-controller" ) type reconciler struct { @@ -94,10 +94,10 @@ func (r *reconciler) createSelfSignedTLSSecret(ctx context.Context) error { return err } - cert.Cert.DNSNames = getCertificateAltNames(r.dk.Name) + cert.Cert.DNSNames = certificates.AltNames(r.dk.Name, r.dk.Namespace, extensionsSelfSignedTLSCommonNameSuffix) cert.Cert.KeyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment cert.Cert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} - cert.Cert.Subject.CommonName = r.dk.Name + extensionsSelfSignedTLSCommonNameSuffix + cert.Cert.Subject.CommonName = certificates.CommonName(r.dk.Name, r.dk.Namespace, extensionsSelfSignedTLSCommonNameSuffix) err = cert.SelfSign() if err != nil { @@ -138,11 +138,3 @@ func (r *reconciler) createSelfSignedTLSSecret(ctx context.Context) error { return nil } - -func getCertificateAltNames(dkName string) []string { - return []string{ - dkName + "-extensions-controller.dynatrace", - dkName + "-extensions-controller.dynatrace.svc", - dkName + "-extensions-controller.dynatrace.svc.cluster.local", - } -} diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go index e0d82674a2..9dbd5421d8 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go @@ -152,7 +152,7 @@ func getActiveGateCaCertVolume(dk *dynakube.DynaKube) corev1.Volume { Name: activeGateCaCertVolumeName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: dk.Spec.ActiveGate.TlsSecretName, + SecretName: dk.Spec.ActiveGate.GetTLSSecretName(), Items: []corev1.KeyToPath{ { Key: "server.crt", diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go index 853c60c337..1e33d9e7b5 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go @@ -86,6 +86,29 @@ func TestPrepareVolumes(t *testing.T) { volumes := prepareVolumes(dk) assert.Contains(t, volumes, getActiveGateCaCertVolume(dk)) }) + t.Run(`has automatically created tls volume`, func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: corev1.ObjectMeta{ + Name: "dynakube", + Annotations: map[string]string{ + dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", + }, + }, + Spec: dynakube.DynaKubeSpec{ + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, + TrustedCAs: testName, + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, + }, + }, + } + volumes := prepareVolumes(dk) + assert.Contains(t, volumes, getActiveGateCaCertVolume(dk)) + }) t.Run(`csi volume not supported on classicFullStack`, func(t *testing.T) { dk := &dynakube.DynaKube{ Spec: dynakube.DynaKubeSpec{ @@ -148,6 +171,7 @@ func TestPrepareVolumeMounts(t *testing.T) { volumeMounts := prepareVolumeMounts(dk) assert.Contains(t, volumeMounts, getReadOnlyRootMount()) + assert.NotContains(t, volumeMounts, getClusterCaCertVolumeMount()) assert.NotContains(t, volumeMounts, getActiveGateCaCertVolumeMount()) }) t.Run(`has cluster certificate volume mount`, func(t *testing.T) { @@ -171,7 +195,6 @@ func TestPrepareVolumeMounts(t *testing.T) { OneAgent: oneagent.Spec{ HostMonitoring: &oneagent.HostInjectSpec{}, }, - TrustedCAs: testName, ActiveGate: activegate.Spec{ Capabilities: []activegate.CapabilityDisplayName{ activegate.KubeMonCapability.DisplayName, @@ -184,6 +207,34 @@ func TestPrepareVolumeMounts(t *testing.T) { volumeMounts := prepareVolumeMounts(dk) assert.Contains(t, volumeMounts, getReadOnlyRootMount()) + assert.NotContains(t, volumeMounts, getClusterCaCertVolumeMount()) + assert.Contains(t, volumeMounts, getActiveGateCaCertVolumeMount()) + }) + t.Run(`has automatically created ActiveGate CA volume mount`, func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: corev1.ObjectMeta{ + Name: "dynakube", + Annotations: map[string]string{ + dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", + }, + }, + Spec: dynakube.DynaKubeSpec{ + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, + }, + TrustedCAs: testName, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, + }, + } + + volumeMounts := prepareVolumeMounts(dk) + + assert.Contains(t, volumeMounts, getReadOnlyRootMount()) + assert.Contains(t, volumeMounts, getClusterCaCertVolumeMount()) assert.Contains(t, volumeMounts, getActiveGateCaCertVolumeMount()) }) t.Run(`readonly volume not supported on classicFullStack`, func(t *testing.T) { diff --git a/pkg/util/certificates/certificates.go b/pkg/util/certificates/certificates.go index 4a5d570e41..7045badbeb 100644 --- a/pkg/util/certificates/certificates.go +++ b/pkg/util/certificates/certificates.go @@ -116,3 +116,15 @@ func ValidateCertificateExpiration(certData []byte, renewalThreshold time.Durati return true, nil } + +func CommonName(dkName string, dkNamespace string, componentName string) string { + return dkName + "-" + componentName + "." + dkNamespace +} + +func AltNames(dkName string, dkNamespace string, componentName string) []string { + return []string{ + dkName + "-" + componentName + "." + dkNamespace, + dkName + "-" + componentName + "." + dkNamespace + ".svc", + dkName + "-" + componentName + "." + dkNamespace + ".svc.cluster.local", + } +} diff --git a/test/features/cloudnative/codemodules/codemodules.go b/test/features/cloudnative/codemodules/codemodules.go index f9bfd984ff..1db3d830bc 100644 --- a/test/features/cloudnative/codemodules/codemodules.go +++ b/test/features/cloudnative/codemodules/codemodules.go @@ -40,6 +40,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/e2e-framework/klient/k8s/resources" @@ -174,8 +175,8 @@ func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature { builder.Assess("check env variables of oneagent pods", checkOneAgentEnvVars(cloudNativeDynakube)) builder.Assess("check proxy settings in ruxitagentproc.conf", proxy.CheckRuxitAgentProcFileHasProxySetting(*sampleApp, proxySpec)) - cloudnative.AssessSampleContainer(builder, sampleApp, nil, nil) - cloudnative.AssessOneAgentContainer(builder, nil, nil) + cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return nil }, nil) + cloudnative.AssessOneAgentContainer(builder, func() []byte { return nil }, nil) cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, nil) // Register sample, dynakubeComponents and operator uninstall @@ -201,6 +202,9 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature { dynakubeComponents.WithActiveGate(), dynakubeComponents.WithIstioIntegration(), dynakubeComponents.WithProxy(proxySpec), + dynakubeComponents.WithAnnotations(map[string]string{ + dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", + }), ) sampleNamespace := *namespace.New("codemodules-sample-with-proxy-custom-ca", namespace.WithIstio()) @@ -234,8 +238,16 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature { builder.Assess("codemodules have been downloaded", imageHasBeenDownloaded(cloudNativeDynakube)) - cloudnative.AssessSampleContainer(builder, sampleApp, nil, trustedCa) - cloudnative.AssessOneAgentContainer(builder, nil, trustedCa) + agTlsSecret := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: cloudNativeDynakube.ActiveGate().GetTLSSecretName(), + Namespace: cloudNativeDynakube.Namespace, + }, + } + builder.Assess("read AG TLS secret", getAgTlsSecret(&agTlsSecret)) + + cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agTlsSecret.Data[dynakube.TLSCertKey] }, trustedCa) + cloudnative.AssessOneAgentContainer(builder, func() []byte { return agTlsSecret.Data[dynakube.TLSCertKey] }, trustedCa) cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, trustedCa) // Register sample, dynakubeComponents and operator uninstall @@ -248,6 +260,18 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature { return builder.Feature() } +func getAgTlsSecret(secret *corev1.Secret) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + err := envConfig.Client().Resources().Get(ctx, secret.Name, secret.Namespace, secret) + require.NoError(t, err) + + _, ok := secret.Data[dynakube.TLSCertKey] + require.True(t, ok) + + return ctx + } +} + func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature { builder := features.New("codemodules-with-proxy-and-ag-cert") secretConfigs := tenant.GetMultiTenantSecret(t) @@ -300,8 +324,8 @@ func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature builder.Assess("codemodules have been downloaded", imageHasBeenDownloaded(cloudNativeDynakube)) - cloudnative.AssessSampleContainer(builder, sampleApp, agCrt, nil) - cloudnative.AssessOneAgentContainer(builder, agCrt, nil) + cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agCrt }, nil) + cloudnative.AssessOneAgentContainer(builder, func() []byte { return agCrt }, nil) cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, nil) // Register sample, dynakubeComponents and operator uninstall @@ -372,8 +396,8 @@ func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Featur builder.Assess("codemodules have been downloaded", imageHasBeenDownloaded(cloudNativeDynakube)) - cloudnative.AssessSampleContainer(builder, sampleApp, agCrt, trustedCa) - cloudnative.AssessOneAgentContainer(builder, agCrt, trustedCa) + cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agCrt }, trustedCa) + cloudnative.AssessOneAgentContainer(builder, func() []byte { return agCrt }, trustedCa) cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, trustedCa) // Register sample, dynakubeComponents and operator uninstall diff --git a/test/features/cloudnative/container.go b/test/features/cloudnative/container.go index 542fefb8fa..dd4b5b2d2c 100644 --- a/test/features/cloudnative/container.go +++ b/test/features/cloudnative/container.go @@ -25,11 +25,11 @@ const ( activeGateRootCAPath = "/var/lib/dynatrace/secrets/rootca/rootca.pem" ) -func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrt []byte, trustedCAs []byte) { - builder.Assess("certificates are propagated to sample apps containers", checkSampleContainer(sampleApp, agCrt, trustedCAs)) +func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrtFunc func() []byte, trustedCAs []byte) { + builder.Assess("certificates are propagated to sample apps containers", checkSampleContainer(sampleApp, agCrtFunc, trustedCAs)) } -func checkSampleContainer(sampleApp *sample.App, agCrt []byte, trustedCAs []byte) features.Func { +func checkSampleContainer(sampleApp *sample.App, agCrtFunc func() []byte, trustedCAs []byte) features.Func { return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { resources := envConfig.Client().Resources() @@ -45,9 +45,9 @@ func checkSampleContainer(sampleApp *sample.App, agCrt []byte, trustedCAs []byte require.NotNil(t, podItem.Spec) require.NotEmpty(t, podItem.Spec.Containers) - certs := string(agCrt) + "\n" + string(trustedCAs) + certs := string(agCrtFunc()) + "\n" + string(trustedCAs) - if string(agCrt) == "" && string(trustedCAs) == "" { + if string(agCrtFunc()) == "" && string(trustedCAs) == "" { checkFileNotFound(ctx, t, resources, podItem, sampleApp.ContainerName(), oneAgentCustomPemPath) } else { checkFileContents(ctx, t, resources, podItem, sampleApp.ContainerName(), oneAgentCustomPemPath, certs) @@ -63,11 +63,11 @@ func checkSampleContainer(sampleApp *sample.App, agCrt []byte, trustedCAs []byte } } -func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrt []byte, trustedCAs []byte) { - builder.Assess("certificates are propagated to OneAgent containers", checkOneAgentContainer(agCrt, trustedCAs)) +func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrtFunc func() []byte, trustedCAs []byte) { + builder.Assess("certificates are propagated to OneAgent containers", checkOneAgentContainer(agCrtFunc, trustedCAs)) } -func checkOneAgentContainer(agCrt []byte, trustedCAs []byte) features.Func { +func checkOneAgentContainer(agCrtFunc func() []byte, trustedCAs []byte) features.Func { return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { // TODO: when OneAgent ticket is done, probably the same pem files as in case of sample container From c504bf1d1bac1ba2334ea7bc17cb47bfbbe8b7bc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 27 Feb 2025 21:56:31 +0000 Subject: [PATCH 255/426] chore(deps): update module github.com/vektra/mockery to v2.52.4 (main) (#4524) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index c0c88fec3e..cb75002712 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.30.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.52.3 +mockery_version=v2.52.4 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest From e73b2c6db329aacc73ef967d3409f2cec8a63837 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Fri, 28 Feb 2025 10:28:37 +0100 Subject: [PATCH 256/426] Respect custom nodeSelector when building logMon/KSPM DaemonSet (#4525) --- .../dynakube/kspm/daemonset/reconciler.go | 1 + .../dynakube/kspm/daemonset/reconciler_test.go | 15 +++++++++++++++ .../logmonitoring/daemonset/reconciler.go | 1 + .../logmonitoring/daemonset/reconciler_test.go | 16 ++++++++++++++++ pkg/util/kubeobjects/daemonset/builder.go | 6 ++++++ 5 files changed, 39 insertions(+) diff --git a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go index 6bcaf6e5d3..dea0fdfe9e 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go @@ -91,6 +91,7 @@ func (r *Reconciler) generateDaemonSet() (*appsv1.DaemonSet, error) { daemonset.SetServiceAccount(serviceAccountName), daemonset.SetAffinity(node.AMDOnlyAffinity()), daemonset.SetPriorityClass(r.dk.KSPM().PriorityClassName), + daemonset.SetNodeSelector(r.dk.KSPM().NodeSelector), daemonset.SetTolerations(r.dk.KSPM().Tolerations), daemonset.SetPullSecret(r.dk.ImagePullSecretReferences()...), daemonset.SetUpdateStrategy(r.getUpdateStrategy()), diff --git a/pkg/controllers/dynakube/kspm/daemonset/reconciler_test.go b/pkg/controllers/dynakube/kspm/daemonset/reconciler_test.go index ce874891aa..0fe8bc65e6 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/reconciler_test.go +++ b/pkg/controllers/dynakube/kspm/daemonset/reconciler_test.go @@ -220,6 +220,21 @@ func TestGenerateDaemonSet(t *testing.T) { assert.Equal(t, daemonset.Spec.Template.Spec.Tolerations, customTolerations) }) + t.Run("respect custom nodeSelector", func(t *testing.T) { + customNodeSelector := map[string]string{ + "some.nodeSelector.key": "true", + } + + dk := createDynakube(true) + dk.KSPM().NodeSelector = customNodeSelector + reconciler := NewReconciler(nil, + nil, dk) + daemonset, err := reconciler.generateDaemonSet() + require.NoError(t, err) + require.NotNil(t, daemonset) + + assert.Equal(t, daemonset.Spec.Template.Spec.NodeSelector, customNodeSelector) + }) } func createDynakube(isEnabled bool) *dynakube.DynaKube { diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go index bdf7f6e9bd..5a62ecdc1c 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go @@ -101,6 +101,7 @@ func (r *Reconciler) generateDaemonSet() (*appsv1.DaemonSet, error) { daemonset.SetDNSPolicy(r.dk.LogMonitoring().Template().DNSPolicy), daemonset.SetAffinity(node.Affinity()), daemonset.SetPriorityClass(r.dk.LogMonitoring().Template().PriorityClassName), + daemonset.SetNodeSelector(r.dk.LogMonitoring().Template().NodeSelector), daemonset.SetTolerations(r.dk.LogMonitoring().Template().Tolerations), daemonset.SetPullSecret(r.dk.ImagePullSecretReferences()...), daemonset.SetUpdateStrategy(appsv1.DaemonSetUpdateStrategy{ diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go index 10cd0a0d2a..01c60cbe67 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go @@ -279,6 +279,22 @@ func TestGenerateDaemonSet(t *testing.T) { assert.Equal(t, daemonset.Spec.Template.Spec.Tolerations, customTolerations) }) + t.Run("respect custom nodeselector", func(t *testing.T) { + customNodeSelector := map[string]string{ + "some.nodeSelector.key": "true", + } + + dk := createDynakube(true) + dk.Spec.Templates.LogMonitoring = &logmonitoring.TemplateSpec{ + NodeSelector: customNodeSelector, + } + reconciler := NewReconciler(nil, fake.NewClient(), dk) + daemonset, err := reconciler.generateDaemonSet() + require.NoError(t, err) + require.NotNil(t, daemonset) + + assert.Equal(t, daemonset.Spec.Template.Spec.NodeSelector, customNodeSelector) + }) } func createDynakube(isEnabled bool) *dynakube.DynaKube { diff --git a/pkg/util/kubeobjects/daemonset/builder.go b/pkg/util/kubeobjects/daemonset/builder.go index ee1bbb6a4d..de9c697d1e 100644 --- a/pkg/util/kubeobjects/daemonset/builder.go +++ b/pkg/util/kubeobjects/daemonset/builder.go @@ -46,6 +46,12 @@ func SetTolerations(tolerations []corev1.Toleration) builder.Option[*appsv1.Daem } } +func SetNodeSelector(nodeSelector map[string]string) builder.Option[*appsv1.DaemonSet] { + return func(s *appsv1.DaemonSet) { + s.Spec.Template.Spec.NodeSelector = nodeSelector + } +} + func SetDNSPolicy(policy corev1.DNSPolicy) builder.Option[*appsv1.DaemonSet] { return func(s *appsv1.DaemonSet) { s.Spec.Template.Spec.DNSPolicy = policy From 10caa8470599e9e015380f65f819f3907a0a048c Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Fri, 28 Feb 2025 10:34:12 +0100 Subject: [PATCH 257/426] cherry pick remove obsolete OTLP token (#4526) Co-authored-by: StefanHauth <63204425+StefanHauth@users.noreply.github.com> --- .../dynakube/otelc/statefulset/env.go | 8 -------- .../otelc/statefulset/reconciler_test.go | 16 +++++----------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/pkg/controllers/dynakube/otelc/statefulset/env.go b/pkg/controllers/dynakube/otelc/statefulset/env.go index 5277b59c8f..7eeb417491 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env.go @@ -21,7 +21,6 @@ const ( envPodName = "POD_NAME" envOTLPgrpcPort = "OTLP_GRPC_PORT" envOTLPhttpPort = "OTLP_HTTP_PORT" - envOTLPtoken = "OTLP_TOKEN" envEECDStoken = "EEC_DS_TOKEN" envTrustedCAs = "TRUSTED_CAS" envK8sClusterName = "K8S_CLUSTER_NAME" @@ -59,13 +58,6 @@ func getEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { }, {Name: envOTLPgrpcPort, Value: defaultOLTPgrpcPort}, {Name: envOTLPhttpPort, Value: defaultOLTPhttpPort}, - {Name: envOTLPtoken, ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, - Key: consts.OtelcTokenSecretKey, - }, - }, - }, {Name: envEECDStoken, ValueFrom: &corev1.EnvVarSource{ SecretKeyRef: &corev1.SecretKeySelector{ LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go index 0a8e2020b1..8d3a0c0dbf 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go @@ -219,22 +219,16 @@ func TestEnvironmentVariables(t *testing.T) { }}, statefulSet.Spec.Template.Spec.Containers[0].Env[3]) assert.Equal(t, corev1.EnvVar{Name: envOTLPgrpcPort, Value: defaultOLTPgrpcPort}, statefulSet.Spec.Template.Spec.Containers[0].Env[4]) assert.Equal(t, corev1.EnvVar{Name: envOTLPhttpPort, Value: defaultOLTPhttpPort}, statefulSet.Spec.Template.Spec.Containers[0].Env[5]) - assert.Equal(t, corev1.EnvVar{Name: envOTLPtoken, ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, - Key: consts.OtelcTokenSecretKey, - }, - }}, statefulSet.Spec.Template.Spec.Containers[0].Env[6]) assert.Equal(t, corev1.EnvVar{Name: envEECDStoken, ValueFrom: &corev1.EnvVarSource{ SecretKeyRef: &corev1.SecretKeySelector{ LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, Key: consts.OtelcTokenSecretKey, }, - }}, statefulSet.Spec.Template.Spec.Containers[0].Env[7]) - assert.Equal(t, corev1.EnvVar{Name: envCertDir, Value: customEecTLSCertificatePath}, statefulSet.Spec.Template.Spec.Containers[0].Env[8]) - assert.Equal(t, corev1.EnvVar{Name: envK8sClusterName, Value: dk.Name}, statefulSet.Spec.Template.Spec.Containers[0].Env[9]) - assert.Equal(t, corev1.EnvVar{Name: envK8sClusterUid, Value: dk.Status.KubeSystemUUID}, statefulSet.Spec.Template.Spec.Containers[0].Env[10]) - assert.Equal(t, corev1.EnvVar{Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, statefulSet.Spec.Template.Spec.Containers[0].Env[11]) + }}, statefulSet.Spec.Template.Spec.Containers[0].Env[6]) + assert.Equal(t, corev1.EnvVar{Name: envCertDir, Value: customEecTLSCertificatePath}, statefulSet.Spec.Template.Spec.Containers[0].Env[7]) + assert.Equal(t, corev1.EnvVar{Name: envK8sClusterName, Value: dk.Name}, statefulSet.Spec.Template.Spec.Containers[0].Env[8]) + assert.Equal(t, corev1.EnvVar{Name: envK8sClusterUid, Value: dk.Status.KubeSystemUUID}, statefulSet.Spec.Template.Spec.Containers[0].Env[9]) + assert.Equal(t, corev1.EnvVar{Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, statefulSet.Spec.Template.Spec.Containers[0].Env[10]) }) t.Run("environment variables with trustedCA", func(t *testing.T) { dk := getTestDynakube() From cc7c8c8597307e4e5cc2c7264a1214849283817a Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 28 Feb 2025 10:58:35 +0100 Subject: [PATCH 258/426] Mount /var/log readonly to standalone logmonitoring (#4522) --- .../dynakube/logmonitoring/daemonset/args.go | 3 +- .../logmonitoring/daemonset/args_test.go | 2 +- .../logmonitoring/daemonset/container.go | 2 +- .../logmonitoring/daemonset/volumes.go | 86 +++++++------------ .../logmonitoring/daemonset/volumes_test.go | 4 +- 5 files changed, 35 insertions(+), 62 deletions(-) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/args.go b/pkg/controllers/dynakube/logmonitoring/daemonset/args.go index 68d28fd9bd..75606fda6f 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/args.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/args.go @@ -14,11 +14,12 @@ func getInitArgs(dk dynakube.DynaKube) []string { fmt.Sprintf("-p dt.entity.kubernetes_cluster=$(%s)", entityEnv), fmt.Sprintf("-c k8s_fullpodname $(%s)", podNameEnv), fmt.Sprintf("-c k8s_poduid $(%s)", podUIDEnv), - fmt.Sprintf("-c k8s_containername %s", containerName), //nolint:perfsprint fmt.Sprintf("-c k8s_basepodname $(%s)", basePodNameEnv), fmt.Sprintf("-c k8s_namespace $(%s)", namespaceNameEnv), fmt.Sprintf("-c k8s_node_name $(%s)", nodeNameEnv), fmt.Sprintf("-c k8s_cluster_id $(%s)", clusterUIDEnv), + "-c k8s_containername " + containerName, + "-l " + dtLogVolumePath, } return append(baseArgs, dk.LogMonitoring().Template().Args...) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/args_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/args_test.go index b75b846cd2..2ef66ca8e9 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/args_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/args_test.go @@ -9,7 +9,7 @@ import ( ) const ( - expectedBaseInitArgsLen = 11 + expectedBaseInitArgsLen = 12 ) func TestGetInitArgs(t *testing.T) { diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go index fad2bd5394..61970eefd0 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go @@ -51,7 +51,7 @@ func getInitContainer(dk dynakube.DynaKube, tenantUUID string) corev1.Container Name: initContainerName, Image: dk.LogMonitoring().Template().ImageRef.StringWithDefaults(defaultImageRepo, defaultImageTag), ImagePullPolicy: corev1.PullAlways, - VolumeMounts: getDTVolumeMounts(tenantUUID), + VolumeMounts: []corev1.VolumeMount{getDTVolumeMounts(tenantUUID)}, Command: []string{bootstrapCommand}, Env: getInitEnvs(dk), Args: getInitArgs(dk), diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go index ab912a74ae..0f841cb55b 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes.go @@ -17,20 +17,14 @@ const ( dtLibVolumeName = "dynatrace-lib" dtLibVolumeMountPath = "/var/lib/dynatrace" dtSubPathTemplate = "logmonitoring-%s" - dtLibVolumePath = "/tmp/dynatrace" + dtLogVolumePath = "/tmp/dynatrace" dtLogVolumeName = "dynatrace-logs" - dtLogVolumeMountPath = "/var/log/dynatrace" // for the logs that the logmonitoring will ingest - podLogsVolumeName = "var-log-pods" - podLogsVolumePath = "/var/log/pods" - dockerLogsVolumeName = "docker-container-logs" - dockerLogsVolumePath = "/var/lib/docker/containers" - containerLogsVolumeName = "container-logs" - containerLogsVolumePath = "/var/log/containers" - journalLogsVolumeName = "var-log-journal" - journalLogsVolumePath = "/var/log/journal" - journalLogsVolumeHostPath = "/var/log" + dockerLogsVolumeName = "docker-container-logs" + dockerLogsVolumePath = "/var/lib/docker/containers" + logsVolumeHostPath = "/var/log" + logsVolumeName = "var-log" ) // getConfigVolumeMount provides the VolumeMount for the deployment.conf @@ -55,17 +49,22 @@ func getConfigVolume(dkName string) corev1.Volume { } // getDTVolumeMounts provides the VolumeMounts for the dynatrace specific folders -func getDTVolumeMounts(tenantUUID string) []corev1.VolumeMount { - return []corev1.VolumeMount{ - { - Name: dtLibVolumeName, - SubPath: fmt.Sprintf(dtSubPathTemplate, tenantUUID), - MountPath: dtLibVolumeMountPath, - }, - { - Name: dtLogVolumeName, - MountPath: dtLogVolumeMountPath, - }, +func getDTVolumeMounts(tenantUUID string) corev1.VolumeMount { + return corev1.VolumeMount{ + + Name: dtLibVolumeName, + SubPath: fmt.Sprintf(dtSubPathTemplate, tenantUUID), + MountPath: dtLibVolumeMountPath, + } +} + +// getDTVolumeMounts provides the VolumeMounts for the dynatrace specific folders +func getDTLogVolumeMounts(tenantUUID string) corev1.VolumeMount { + return corev1.VolumeMount{ + + Name: dtLogVolumeName, + SubPath: fmt.Sprintf(dtSubPathTemplate, tenantUUID), + MountPath: dtLogVolumePath, } } @@ -76,7 +75,7 @@ func getDTVolumes() []corev1.Volume { Name: dtLibVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: dtLibVolumePath, + Path: dtLogVolumePath, Type: ptr.To(corev1.HostPathDirectoryOrCreate), }, }, @@ -97,18 +96,8 @@ func getIngestVolumeMounts() []corev1.VolumeMount { ReadOnly: true, }, { - Name: podLogsVolumeName, - MountPath: podLogsVolumePath, - ReadOnly: true, - }, - { - Name: containerLogsVolumeName, - MountPath: containerLogsVolumePath, - ReadOnly: true, - }, - { - Name: journalLogsVolumeName, - MountPath: journalLogsVolumePath, + Name: logsVolumeName, + MountPath: logsVolumeHostPath, ReadOnly: true, }, } @@ -122,33 +111,15 @@ func getIngestVolumes() []corev1.Volume { VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ Path: dockerLogsVolumePath, - Type: ptr.To(corev1.HostPathDirectory), - }, - }, - }, - { - Name: podLogsVolumeName, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: podLogsVolumePath, - Type: ptr.To(corev1.HostPathDirectory), - }, - }, - }, - { - Name: containerLogsVolumeName, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: containerLogsVolumePath, - Type: ptr.To(corev1.HostPathDirectory), + Type: ptr.To(corev1.HostPathDirectoryOrCreate), }, }, }, { - Name: journalLogsVolumeName, + Name: logsVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: journalLogsVolumeHostPath, + Path: logsVolumeHostPath, Type: ptr.To(corev1.HostPathDirectory), }, }, @@ -159,7 +130,8 @@ func getIngestVolumes() []corev1.Volume { func getVolumeMounts(tenantUUID string) []corev1.VolumeMount { var mounts []corev1.VolumeMount mounts = append(mounts, getConfigVolumeMount()) - mounts = append(mounts, getDTVolumeMounts(tenantUUID)...) + mounts = append(mounts, getDTVolumeMounts(tenantUUID)) + mounts = append(mounts, getDTLogVolumeMounts(tenantUUID)) mounts = append(mounts, getIngestVolumeMounts()...) return mounts diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go index dc68f19d7b..63790a3840 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/volumes_test.go @@ -8,8 +8,8 @@ import ( ) const ( - expectedMountLen = 7 - expectedInitMountLen = 2 + expectedMountLen = 5 + expectedInitMountLen = 1 ) func TestGetVolumeMounts(t *testing.T) { From 9743ce061cedbdb95fad0c6ae6d4af7fdccea189 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 28 Feb 2025 11:56:00 +0100 Subject: [PATCH 259/426] The snapshot image shouldn't expire (#4514) --- hack/build/ci/prepare-build-variables.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/build/ci/prepare-build-variables.sh b/hack/build/ci/prepare-build-variables.sh index b5648e9492..335f985976 100755 --- a/hack/build/ci/prepare-build-variables.sh +++ b/hack/build/ci/prepare-build-variables.sh @@ -15,7 +15,7 @@ createDockerImageTag() { } createDockerImageLabels() { - if [[ "${GITHUB_REF_TYPE}" != "tag" ]] && [[ ! "${GITHUB_REF_NAME}" =~ ^release-* ]]; then + if [[ "${GITHUB_REF_TYPE}" != "tag" ]] && [[ ! "${GITHUB_REF_NAME}" =~ ^release-* ]] && [[ "${GITHUB_REF_NAME}" != "main" ]]; then echo "quay.expires-after=10d" fi From b3c1aea2110d898cb4fb49548c1f71f57db814e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 19:53:20 +0000 Subject: [PATCH 260/426] chore(deps): update docker/setup-qemu-action action to v3.6.0 (main) (#4528) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 6e3e9ab5a7..a091529a9d 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -14,7 +14,7 @@ runs: using: "composite" steps: - name: Set up QEMU - uses: docker/setup-qemu-action@5964de0df58d5ad28b04d8fe2e6b80ad47105b91 # v3.5.0 + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - name: Set up Golang From 96120c5cfdea9c0e343de06245b52960394cb8c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 05:30:17 +0000 Subject: [PATCH 261/426] chore(deps): update module github.com/golangci/golangci-lint to v1.64.6 (main) (#4531) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- hack/make/prerequisites.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 77519e1094..16f45c4eef 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -89,7 +89,7 @@ jobs: uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0 with: # renovate depName=github.com/golangci/golangci-lint - version: v1.64.5 + version: v1.64.6 args: --build-tags e2e --timeout 300s --out-${NO_FUTURE}format colored-line-number - name: Run deadcode id: deadcode diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index cb75002712..f588ad8fd0 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -3,7 +3,7 @@ kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.2 # renovate depName=github.com/golangci/golangci-lint -golang_ci_cmd_version=v1.64.5 +golang_ci_cmd_version=v1.64.6 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools From a2dad703eed02411d64b18cbe3025110ddc72c76 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 06:37:42 +0000 Subject: [PATCH 262/426] chore(deps): update module github.com/vektra/mockery to v2.53.0 (main) (#4532) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index f588ad8fd0..9119b6b74b 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.30.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.52.4 +mockery_version=v2.53.0 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest From 6be6f8893c294f937ebed78ab5b7618dc0d8d3e4 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Mon, 3 Mar 2025 10:32:52 +0100 Subject: [PATCH 263/426] Add DynaKube phase handling also to KSPM and LogMon (#4527) --- pkg/controllers/dynakube/phase.go | 64 ++++++++++-- pkg/controllers/dynakube/phase_test.go | 135 ++++++++++++++++++++++++- 2 files changed, 192 insertions(+), 7 deletions(-) diff --git a/pkg/controllers/dynakube/phase.go b/pkg/controllers/dynakube/phase.go index 4c97ed2e41..371cabaf19 100644 --- a/pkg/controllers/dynakube/phase.go +++ b/pkg/controllers/dynakube/phase.go @@ -17,6 +17,8 @@ func (controller *Controller) determineDynaKubePhase(dk *dynakube.DynaKube) stat controller.determineExtensionsExecutionControllerPhase, controller.determineExtensionsCollectorPhase, controller.determineOneAgentPhase, + controller.determineLogAgentPhase, + controller.determineKSPMPhase, } for _, component := range components { if phase := component(dk); phase != status.Running { @@ -94,7 +96,7 @@ func (controller *Controller) determinePrometheusStatefulsetPhase(dk *dynakube.D func (controller *Controller) determineOneAgentPhase(dk *dynakube.DynaKube) status.DeploymentPhase { if dk.OneAgent().IsCloudNativeFullstackMode() || dk.OneAgent().IsClassicFullStackMode() || dk.OneAgent().IsHostMonitoringMode() { - oneAgentPods, err := controller.numberOfMissingOneagentPods(dk) + oneAgentPods, err := controller.numberOfMissingDaemonSetPods(dk, dk.OneAgent().GetDaemonsetName()) if k8serrors.IsNotFound(err) { log.Info("oneagent daemonset not yet available", "dynakube", dk.Name) @@ -117,16 +119,66 @@ func (controller *Controller) determineOneAgentPhase(dk *dynakube.DynaKube) stat return status.Running } -func (controller *Controller) numberOfMissingOneagentPods(dk *dynakube.DynaKube) (int32, error) { - oneAgentDaemonSet := &appsv1.DaemonSet{} - instanceName := dk.OneAgent().GetDaemonsetName() +func (controller *Controller) determineLogAgentPhase(dk *dynakube.DynaKube) status.DeploymentPhase { + if dk.LogMonitoring().IsStandalone() { + logAgentPods, err := controller.numberOfMissingDaemonSetPods(dk, dk.LogMonitoring().GetDaemonSetName()) + if k8serrors.IsNotFound(err) { + log.Info("logagent daemonset not yet available", "dynakube", dk.Name) + + return status.Deploying + } + + if err != nil { + log.Error(err, "logagent daemonset could not be accessed", "dynakube", dk.Name) + + return status.Error + } + + if logAgentPods > 0 { + log.Info("logagent daemonset is still deploying", "dynakube", dk.Name) + + return status.Deploying + } + } + + return status.Running +} + +func (controller *Controller) determineKSPMPhase(dk *dynakube.DynaKube) status.DeploymentPhase { + if dk.KSPM().IsEnabled() { + kspmPods, err := controller.numberOfMissingDaemonSetPods(dk, dk.KSPM().GetDaemonSetName()) + if k8serrors.IsNotFound(err) { + log.Info("kspm daemonset not yet available", "dynakube", dk.Name) + + return status.Deploying + } + + if err != nil { + log.Error(err, "kspm daemonset could not be accessed", "dynakube", dk.Name) + + return status.Error + } + + if kspmPods > 0 { + log.Info("kspm daemonset is still deploying", "dynakube", dk.Name) + + return status.Deploying + } + } + + return status.Running +} + +func (controller *Controller) numberOfMissingDaemonSetPods(dk *dynakube.DynaKube, dsName string) (int32, error) { + daemonSet := &appsv1.DaemonSet{} + instanceName := dsName - err := controller.client.Get(context.Background(), types.NamespacedName{Name: instanceName, Namespace: dk.Namespace}, oneAgentDaemonSet) + err := controller.client.Get(context.Background(), types.NamespacedName{Name: instanceName, Namespace: dk.Namespace}, daemonSet) if err != nil { return 0, err } - return oneAgentDaemonSet.Status.CurrentNumberScheduled - oneAgentDaemonSet.Status.NumberReady, nil + return daemonSet.Status.CurrentNumberScheduled - daemonSet.Status.NumberReady, nil } func (controller *Controller) numberOfMissingActiveGatePods(dk *dynakube.DynaKube) (int32, error) { diff --git a/pkg/controllers/dynakube/phase_test.go b/pkg/controllers/dynakube/phase_test.go index abc07fc48e..ca7c86fa09 100644 --- a/pkg/controllers/dynakube/phase_test.go +++ b/pkg/controllers/dynakube/phase_test.go @@ -4,9 +4,12 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" @@ -259,6 +262,120 @@ func TestExtensionsCollectorPhaseChanges(t *testing.T) { }) } +func TestLogAgentPhaseChanges(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + LogMonitoring: &logmonitoring.Spec{}, + Templates: dynakube.TemplatesSpec{ + LogMonitoring: &logmonitoring.TemplateSpec{ + ImageRef: image.Ref{ + Repository: "test", + Tag: "test-tag", + }, + }, + }, + }, + } + + t.Run("no LogAgent pods in cluster -> deploying", func(t *testing.T) { + fakeClient := fake.NewClient() + controller := &Controller{ + client: fakeClient, + apiReader: fakeClient, + } + phase := controller.determineDynaKubePhase(dk) + assert.Equal(t, status.Deploying, phase) + }) + t.Run("Error accessing k8s api", func(t *testing.T) { + fakeClient := errorClient{} + controller := &Controller{ + client: fakeClient, + apiReader: fakeClient, + } + phase := controller.determineDynaKubePhase(dk) + assert.Equal(t, status.Error, phase) + }) + t.Run("LogAgent daemonsets in cluster not all ready -> deploying", func(t *testing.T) { + fakeClient := fake.NewClient(createDaemonSet(testNamespace, dk.LogMonitoring().GetDaemonSetName(), 3, 2)) + controller := &Controller{ + client: fakeClient, + apiReader: fakeClient, + } + phase := controller.determineDynaKubePhase(dk) + assert.Equal(t, status.Deploying, phase) + }) + t.Run("LogAgent daemonsets in cluster all ready -> running", func(t *testing.T) { + fakeClient := fake.NewClient(createDaemonSet(testNamespace, dk.LogMonitoring().GetDaemonSetName(), 3, 3)) + controller := &Controller{ + client: fakeClient, + apiReader: fakeClient, + } + phase := controller.determineDynaKubePhase(dk) + assert.Equal(t, status.Running, phase) + }) +} + +func TestKSPMPhaseChanges(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + }, + Spec: dynakube.DynaKubeSpec{ + Kspm: &kspm.Spec{}, + Templates: dynakube.TemplatesSpec{ + KspmNodeConfigurationCollector: kspm.NodeConfigurationCollectorSpec{ + ImageRef: image.Ref{ + Repository: "test", + Tag: "test-tag", + }, + }, + }, + }, + } + + t.Run("no KSPM pods in cluster -> deploying", func(t *testing.T) { + fakeClient := fake.NewClient() + controller := &Controller{ + client: fakeClient, + apiReader: fakeClient, + } + phase := controller.determineDynaKubePhase(dk) + assert.Equal(t, status.Deploying, phase) + }) + t.Run("Error accessing k8s api", func(t *testing.T) { + fakeClient := errorClient{} + controller := &Controller{ + client: fakeClient, + apiReader: fakeClient, + } + phase := controller.determineDynaKubePhase(dk) + assert.Equal(t, status.Error, phase) + }) + t.Run("KSPM daemonsets in cluster not all ready -> deploying", func(t *testing.T) { + fakeClient := fake.NewClient(createDaemonSet(testNamespace, dk.KSPM().GetDaemonSetName(), 3, 2)) + controller := &Controller{ + client: fakeClient, + apiReader: fakeClient, + } + phase := controller.determineDynaKubePhase(dk) + assert.Equal(t, status.Deploying, phase) + }) + t.Run("KSPM daemonsets in cluster all ready -> running", func(t *testing.T) { + fakeClient := fake.NewClient(createDaemonSet(testNamespace, dk.KSPM().GetDaemonSetName(), 3, 3)) + controller := &Controller{ + client: fakeClient, + apiReader: fakeClient, + } + phase := controller.determineDynaKubePhase(dk) + assert.Equal(t, status.Running, phase) + }) +} + func TestDynakubePhaseChanges(t *testing.T) { dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ @@ -270,6 +387,10 @@ func TestDynakubePhaseChanges(t *testing.T) { ClassicFullStack: &oneagent.HostInjectSpec{}, }, + LogMonitoring: &logmonitoring.Spec{}, + + Kspm: &kspm.Spec{}, + Extensions: &dynakube.ExtensionsSpec{}, }, } @@ -282,6 +403,10 @@ func TestDynakubePhaseChanges(t *testing.T) { otelcNotReady := createStatefulset(testNamespace, dk.ExtensionsCollectorStatefulsetName(), 2, 1) oaReady := createDaemonSet(testNamespace, "test-name-oneagent", 3, 3) oaNotReady := createDaemonSet(testNamespace, "test-name-oneagent", 3, 2) + logAgentReady := createDaemonSet(testNamespace, dk.LogMonitoring().GetDaemonSetName(), 3, 3) + logAgentNotReady := createDaemonSet(testNamespace, dk.LogMonitoring().GetDaemonSetName(), 3, 2) + kspmReady := createDaemonSet(testNamespace, dk.KSPM().GetDaemonSetName(), 3, 3) + kspmNotReady := createDaemonSet(testNamespace, dk.KSPM().GetDaemonSetName(), 3, 2) tests := []struct { clt client.Client @@ -348,9 +473,17 @@ func TestDynakubePhaseChanges(t *testing.T) { phase: status.Deploying, }, { - clt: fake.NewClient(agReady, oaReady, eecReady, otelcReady), + clt: fake.NewClient(agReady, oaReady, eecReady, otelcReady, logAgentReady, kspmReady), phase: status.Running, }, + { + clt: fake.NewClient(agReady, oaNotReady, eecReady, otelcReady, logAgentNotReady, kspmReady), + phase: status.Deploying, + }, + { + clt: fake.NewClient(agReady, oaReady, eecReady, otelcReady, logAgentReady, kspmNotReady), + phase: status.Deploying, + }, } for i, test := range tests { From 07f4bddeb86333125766b84544f07513b816623d Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Mon, 3 Mar 2025 14:01:06 +0100 Subject: [PATCH 264/426] otelc generatro: remove required telemetry service section (#4534) --- pkg/otelcgen/otelcgen.go | 32 +++++++++++++------ pkg/otelcgen/services.go | 24 ++++++++------ pkg/otelcgen/testdata/exporters_only.yaml | 21 ------------ pkg/otelcgen/testdata/extensions_only.yaml | 21 ------------ pkg/otelcgen/testdata/full_config.yaml | 21 ------------ pkg/otelcgen/testdata/processors_only.yaml | 21 ------------ .../testdata/receivers_jaeger_only.yaml | 21 ------------ .../testdata/receivers_otlp_only.yaml | 21 ------------ pkg/otelcgen/testdata/receivers_statsd.yaml | 21 ------------ .../testdata/receivers_zipkin_only.yaml | 21 ------------ pkg/otelcgen/testdata/services_only.yaml | 21 ------------ 11 files changed, 38 insertions(+), 207 deletions(-) diff --git a/pkg/otelcgen/otelcgen.go b/pkg/otelcgen/otelcgen.go index faba3dd993..1aaf114417 100644 --- a/pkg/otelcgen/otelcgen.go +++ b/pkg/otelcgen/otelcgen.go @@ -5,7 +5,6 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/confmap" - "go.opentelemetry.io/collector/otelcol" "gopkg.in/yaml.v3" ) @@ -69,19 +68,34 @@ var ( ) type Config struct { - cfg *otelcol.Config + // Receivers is a map of ComponentID to Receivers. + Receivers map[component.ID]component.Config `mapstructure:"receivers"` + + // Exporters is a map of ComponentID to Exporters. + Exporters map[component.ID]component.Config `mapstructure:"exporters"` + + // Processors is a map of ComponentID to Processors. + Processors map[component.ID]component.Config `mapstructure:"processors"` + + // Connectors is a map of ComponentID to connectors. + Connectors map[component.ID]component.Config `mapstructure:"connectors"` + + // Extensions is a map of ComponentID to extensions. + Extensions map[component.ID]component.Config `mapstructure:"extensions"` + tlsKey string tlsCert string caFile string podIP string apiToken string + + Service ServiceConfig `mapstructure:"service"` } type Option func(c *Config) error func NewConfig(podIP string, options ...Option) (*Config, error) { c := Config{ - cfg: &otelcol.Config{}, podIP: podIP, } @@ -97,7 +111,7 @@ func NewConfig(podIP string, options ...Option) (*Config, error) { func (c *Config) Marshal() ([]byte, error) { conf := confmap.New() - if err := conf.Marshal(c.cfg); err != nil { + if err := conf.Marshal(c); err != nil { return nil, err } @@ -132,7 +146,7 @@ func WithProtocols(protocols ...string) Option { return err } - c.cfg.Receivers = receivers + c.Receivers = receivers return nil } @@ -142,7 +156,7 @@ func WithProcessors() Option { return func(c *Config) error { processors := c.buildProcessors() - c.cfg.Processors = processors + c.Processors = processors return nil } @@ -152,7 +166,7 @@ func WithExporters() Option { return func(c *Config) error { exporters := c.buildExporters() - c.cfg.Exporters = exporters + c.Exporters = exporters return nil } @@ -162,7 +176,7 @@ func WithExtensions() Option { return func(c *Config) error { extensions := c.buildExtensions() - c.cfg.Extensions = extensions + c.Extensions = extensions return nil } @@ -172,7 +186,7 @@ func WithServices() Option { return func(c *Config) error { services := c.buildServices() - c.cfg.Service = services + c.Service = services return nil } diff --git a/pkg/otelcgen/services.go b/pkg/otelcgen/services.go index 47afbf08fb..150d60fd47 100644 --- a/pkg/otelcgen/services.go +++ b/pkg/otelcgen/services.go @@ -3,7 +3,6 @@ package otelcgen import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/pipeline" - "go.opentelemetry.io/collector/service" "go.opentelemetry.io/collector/service/extensions" "go.opentelemetry.io/collector/service/pipelines" "go.opentelemetry.io/collector/service/telemetry" @@ -16,14 +15,21 @@ var ( debug = component.MustNewID("debug") ) -func (c *Config) buildServices() service.Config { - return service.Config{ - Telemetry: telemetry.Config{ - Logs: telemetry.LogsConfig{}, - Metrics: telemetry.MetricsConfig{}, - Traces: telemetry.TracesConfig{}, - Resource: nil, - }, +// ServiceConfig defines the configurable components of the Service. +// based on "go.opentelemetry.io/collector/service.Config +type ServiceConfig struct { + // Telemetry is the configuration for collector's own telemetry. + Telemetry telemetry.Config `mapstructure:"telemetry,omitempty"` + + // Pipelines are the set of data pipelines configured for the service. + Pipelines pipelines.Config `mapstructure:"pipelines"` + + // Extensions are the ordered list of extensions configured for the service. + Extensions extensions.Config `mapstructure:"extensions"` +} + +func (c *Config) buildServices() ServiceConfig { + return ServiceConfig{ Extensions: extensions.Config{healthCheck}, Pipelines: pipelines.Config{ traces: &pipelines.PipelineConfig{ diff --git a/pkg/otelcgen/testdata/exporters_only.yaml b/pkg/otelcgen/testdata/exporters_only.yaml index f1a82d9ba4..a5defb4bea 100644 --- a/pkg/otelcgen/testdata/exporters_only.yaml +++ b/pkg/otelcgen/testdata/exporters_only.yaml @@ -12,24 +12,3 @@ receivers: {} service: extensions: [] pipelines: {} - telemetry: - logs: - development: false - disable_caller: false - disable_stacktrace: false - encoding: "" - error_output_paths: [] - initial_fields: {} - level: info - output_paths: [] - processors: [] - sampling: null - metrics: - address: "" - level: Basic - readers: [] - resource: {} - traces: - level: Basic - processors: [] - propagators: [] diff --git a/pkg/otelcgen/testdata/extensions_only.yaml b/pkg/otelcgen/testdata/extensions_only.yaml index 7d028089aa..d4c586ce3b 100644 --- a/pkg/otelcgen/testdata/extensions_only.yaml +++ b/pkg/otelcgen/testdata/extensions_only.yaml @@ -8,24 +8,3 @@ receivers: {} service: extensions: [] pipelines: {} - telemetry: - logs: - development: false - disable_caller: false - disable_stacktrace: false - encoding: "" - error_output_paths: [] - initial_fields: {} - level: info - output_paths: [] - processors: [] - sampling: null - metrics: - address: "" - level: Basic - readers: [] - resource: {} - traces: - level: Basic - processors: [] - propagators: [] diff --git a/pkg/otelcgen/testdata/full_config.yaml b/pkg/otelcgen/testdata/full_config.yaml index d8a4e74ce2..2dcda80b45 100644 --- a/pkg/otelcgen/testdata/full_config.yaml +++ b/pkg/otelcgen/testdata/full_config.yaml @@ -231,24 +231,3 @@ service: - k8sattributes - transform - batch/traces - telemetry: - logs: - development: false - disable_caller: false - disable_stacktrace: false - encoding: "" - error_output_paths: [ ] - initial_fields: { } - level: info - output_paths: [ ] - processors: [ ] - sampling: null - metrics: - address: "" - level: Basic - readers: [ ] - resource: { } - traces: - level: Basic - processors: [ ] - propagators: [ ] diff --git a/pkg/otelcgen/testdata/processors_only.yaml b/pkg/otelcgen/testdata/processors_only.yaml index 24b6e5f747..5fc43bd435 100644 --- a/pkg/otelcgen/testdata/processors_only.yaml +++ b/pkg/otelcgen/testdata/processors_only.yaml @@ -135,24 +135,3 @@ receivers: {} service: extensions: [] pipelines: {} - telemetry: - logs: - development: false - disable_caller: false - disable_stacktrace: false - encoding: "" - error_output_paths: [] - initial_fields: {} - level: info - output_paths: [] - processors: [] - sampling: null - metrics: - address: "" - level: Basic - readers: [] - resource: {} - traces: - level: Basic - processors: [] - propagators: [] diff --git a/pkg/otelcgen/testdata/receivers_jaeger_only.yaml b/pkg/otelcgen/testdata/receivers_jaeger_only.yaml index 73117b4e28..e58d4d2ab4 100644 --- a/pkg/otelcgen/testdata/receivers_jaeger_only.yaml +++ b/pkg/otelcgen/testdata/receivers_jaeger_only.yaml @@ -22,24 +22,3 @@ receivers: service: extensions: [] pipelines: {} - telemetry: - logs: - development: false - disable_caller: false - disable_stacktrace: false - encoding: "" - error_output_paths: [] - initial_fields: {} - level: info - output_paths: [] - processors: [] - sampling: null - metrics: - address: "" - level: Basic - readers: [] - resource: {} - traces: - level: Basic - processors: [] - propagators: [] diff --git a/pkg/otelcgen/testdata/receivers_otlp_only.yaml b/pkg/otelcgen/testdata/receivers_otlp_only.yaml index 0b9b0cb208..4a1e56f702 100644 --- a/pkg/otelcgen/testdata/receivers_otlp_only.yaml +++ b/pkg/otelcgen/testdata/receivers_otlp_only.yaml @@ -18,24 +18,3 @@ receivers: service: extensions: [] pipelines: {} - telemetry: - logs: - development: false - disable_caller: false - disable_stacktrace: false - encoding: "" - error_output_paths: [] - initial_fields: {} - level: info - output_paths: [] - processors: [] - sampling: null - metrics: - address: "" - level: Basic - readers: [] - resource: {} - traces: - level: Basic - processors: [] - propagators: [] diff --git a/pkg/otelcgen/testdata/receivers_statsd.yaml b/pkg/otelcgen/testdata/receivers_statsd.yaml index 05579ee114..b3602e65a3 100644 --- a/pkg/otelcgen/testdata/receivers_statsd.yaml +++ b/pkg/otelcgen/testdata/receivers_statsd.yaml @@ -21,24 +21,3 @@ receivers: service: extensions: [] pipelines: {} - telemetry: - logs: - development: false - disable_caller: false - disable_stacktrace: false - encoding: "" - error_output_paths: [] - initial_fields: {} - level: info - output_paths: [] - processors: [] - sampling: null - metrics: - address: "" - level: Basic - readers: [] - resource: {} - traces: - level: Basic - processors: [] - propagators: [] diff --git a/pkg/otelcgen/testdata/receivers_zipkin_only.yaml b/pkg/otelcgen/testdata/receivers_zipkin_only.yaml index d893ba808c..e21c174bfa 100644 --- a/pkg/otelcgen/testdata/receivers_zipkin_only.yaml +++ b/pkg/otelcgen/testdata/receivers_zipkin_only.yaml @@ -11,24 +11,3 @@ receivers: service: extensions: [] pipelines: {} - telemetry: - logs: - development: false - disable_caller: false - disable_stacktrace: false - encoding: "" - error_output_paths: [] - initial_fields: {} - level: info - output_paths: [] - processors: [] - sampling: null - metrics: - address: "" - level: Basic - readers: [] - resource: {} - traces: - level: Basic - processors: [] - propagators: [] diff --git a/pkg/otelcgen/testdata/services_only.yaml b/pkg/otelcgen/testdata/services_only.yaml index d6676ee57d..05c47b8ae8 100644 --- a/pkg/otelcgen/testdata/services_only.yaml +++ b/pkg/otelcgen/testdata/services_only.yaml @@ -46,24 +46,3 @@ service: - k8sattributes - transform - batch/traces - telemetry: - logs: - development: false - disable_caller: false - disable_stacktrace: false - encoding: "" - error_output_paths: [ ] - initial_fields: { } - level: info - output_paths: [ ] - processors: [ ] - sampling: null - metrics: - address: "" - level: Basic - readers: [ ] - resource: { } - traces: - level: Basic - processors: [ ] - propagators: [ ] From 73bbcbee3f05ee40f20842a66d912c44191bd4af Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 06:04:17 +0000 Subject: [PATCH 265/426] fix(deps): update module istio.io/api to v1.25.0 (main) (#4535) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 13 +------------ go.sum | 55 ++----------------------------------------------------- 2 files changed, 3 insertions(+), 65 deletions(-) diff --git a/go.mod b/go.mod index 7c99c4a640..eb27e460c2 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,6 @@ require ( github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v0.120.0 go.opentelemetry.io/collector/confmap v1.26.0 - go.opentelemetry.io/collector/otelcol v0.120.0 go.opentelemetry.io/collector/pipeline v0.120.0 go.opentelemetry.io/collector/service v0.120.0 go.uber.org/zap v1.27.0 @@ -29,7 +28,7 @@ require ( golang.org/x/sys v0.30.0 google.golang.org/grpc v1.70.0 gopkg.in/yaml.v3 v3.0.1 - istio.io/api v1.24.3 + istio.io/api v1.25.0 istio.io/client-go v1.24.3 k8s.io/api v0.32.2 k8s.io/apiextensions-apiserver v0.32.2 @@ -50,14 +49,12 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect - github.com/ebitengine/purego v0.8.2 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.23.0 // indirect @@ -77,7 +74,6 @@ require ( github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect github.com/knadh/koanf/v2 v2.1.2 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -91,25 +87,19 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect github.com/vbatts/tar-split v0.11.6 // indirect github.com/vladimirvivien/gexe v0.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/collector/component/componentstatus v0.120.0 // indirect go.opentelemetry.io/collector/component/componenttest v0.120.0 // indirect go.opentelemetry.io/collector/config/configtelemetry v0.120.0 // indirect - go.opentelemetry.io/collector/confmap/xconfmap v0.120.0 // indirect go.opentelemetry.io/collector/connector v0.120.0 // indirect go.opentelemetry.io/collector/connector/connectortest v0.120.0 // indirect go.opentelemetry.io/collector/connector/xconnector v0.120.0 // indirect @@ -136,7 +126,6 @@ require ( go.opentelemetry.io/collector/receiver v0.120.0 // indirect go.opentelemetry.io/collector/receiver/receivertest v0.120.0 // indirect go.opentelemetry.io/collector/receiver/xreceiver v0.120.0 // indirect - go.opentelemetry.io/collector/semconv v0.120.0 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect go.opentelemetry.io/contrib/config v0.14.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect diff --git a/go.sum b/go.sum index 7a43f343e0..0547b7594b 100644 --- a/go.sum +++ b/go.sum @@ -22,16 +22,12 @@ github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBi github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= -github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= -github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= @@ -43,8 +39,6 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= @@ -61,13 +55,10 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -111,8 +102,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -144,15 +133,11 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= -github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA= github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= @@ -163,11 +148,7 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= -github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= -github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= @@ -188,10 +169,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= github.com/vladimirvivien/gexe v0.2.0 h1:nbdAQ6vbZ+ZNsolCgSVb9Fno60kzSuvtzVh6Ytqi/xY= @@ -200,34 +177,20 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= -github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/collector v0.120.0 h1:RmEFc4rPB0wg7fEDY0k8OenXznAtsVGzgAkjTAF44WQ= go.opentelemetry.io/collector v0.120.0/go.mod h1:uNDaRieHl04oQCvGFY4KzpDRqejgMNbea0u2+vk7P3k= -go.opentelemetry.io/collector/client v1.26.0 h1:m/rXHfGzHx4RcETswnm5Y2r1uPv6q0lY+M4btNxbLnE= -go.opentelemetry.io/collector/client v1.26.0/go.mod h1:H7dkvh+4BbglV1QiyI+AD/aWuqJ3iE5oiYr5oDKtBLw= go.opentelemetry.io/collector/component v0.120.0 h1:YHEQ6NuBI6FQHKW24OwrNg2IJ0EUIg4RIuwV5YQ6PSI= go.opentelemetry.io/collector/component v0.120.0/go.mod h1:Ya5O+5NWG9XdhJPnOVhKtBrNXHN3hweQbB98HH4KPNU= go.opentelemetry.io/collector/component/componentstatus v0.120.0 h1:hzKjI9+AIl8A/saAARb47JqabWsge0kMp8NSPNiCNOQ= go.opentelemetry.io/collector/component/componentstatus v0.120.0/go.mod h1:kbuAEddxvcyjGLXGmys3nckAj4jTGC0IqDIEXAOr3Ag= go.opentelemetry.io/collector/component/componenttest v0.120.0 h1:vKX85d3lpxj/RoiFQNvmIpX9lOS80FY5svzOYUyeYX0= go.opentelemetry.io/collector/component/componenttest v0.120.0/go.mod h1:QDLboWF2akEqAGyvje8Hc7GfXcrZvQ5FhmlWvD5SkzY= -go.opentelemetry.io/collector/config/configauth v0.120.0 h1:5yJd4fYAxdbMnuEkTyfnKtZKEqNJVPyt+roDYDPdWIk= -go.opentelemetry.io/collector/config/configauth v0.120.0/go.mod h1:n1rj/cJ+wi+4Cr7q9Z87sF2izYown4/ADDiPZMdLd6g= -go.opentelemetry.io/collector/config/configcompression v1.26.0 h1:90J6ePTWwZbN6QRPawuGOmJG5H84KB4DzHdbd/kUZM4= -go.opentelemetry.io/collector/config/configcompression v1.26.0/go.mod h1:QwbNpaOl6Me+wd0EdFuEJg0Cc+WR42HNjJtdq4TwE6w= -go.opentelemetry.io/collector/config/confighttp v0.120.0 h1:ZOA59E7VsYSmMLGkNke6uOGq3yYK1hJ9OUa/swNeVtI= -go.opentelemetry.io/collector/config/confighttp v0.120.0/go.mod h1:9GpKCdtmypk+DpuoJlAyV5LppiWazFahuJby+L5Rz2Q= -go.opentelemetry.io/collector/config/configopaque v1.26.0 h1:lM9+fDvr5RWkTupoq8xi7qt0kvXoUX7UFN8D7Wb4zRI= -go.opentelemetry.io/collector/config/configopaque v1.26.0/go.mod h1:GYQiC8IejBcwE8z0O4DwbBR/Hf6U7d8DTf+cszyqwFs= go.opentelemetry.io/collector/config/configretry v1.26.0 h1:DGuaZYkGXCr+Wd6+D65xZv7E9z/nyt/F//XbC4B/7M4= go.opentelemetry.io/collector/config/configretry v1.26.0/go.mod h1:8gzFQ0qzKLYvzP2sNPwsB9gwzKSEls649yANmt/d6yE= go.opentelemetry.io/collector/config/configtelemetry v0.120.0 h1:YPXMpfMd9PhngFXiwi3Lmze/Rs0nGS5wQOX16Elev+8= go.opentelemetry.io/collector/config/configtelemetry v0.120.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= -go.opentelemetry.io/collector/config/configtls v1.26.0 h1:aBNqX3Q3WpO20SG/CF6sKxD1rJllKom7gCOW6SeGcq4= -go.opentelemetry.io/collector/config/configtls v1.26.0/go.mod h1:ppoLSWiwovldy4R9KCs6+XCWhvvBaF8eBhkUL460lxw= go.opentelemetry.io/collector/confmap v1.26.0 h1:+EVk0RaCBHs+7dYTwawd5n5tJiiUtErIy3YS3NIFP8o= go.opentelemetry.io/collector/confmap v1.26.0/go.mod h1:tmOa6iw3FJsEgfBHKALqvcdfRtf71JZGor0wSM5MoH8= go.opentelemetry.io/collector/confmap/xconfmap v0.120.0 h1:wt+9H/TLXhY6q40AVx+fn2XK/FhjXuwInwFq9X9+aik= @@ -254,24 +217,18 @@ go.opentelemetry.io/collector/exporter/xexporter v0.120.0 h1:HSe3a+0lt/o/g8GgNKg go.opentelemetry.io/collector/exporter/xexporter v0.120.0/go.mod h1:P/87SRTCd/PnQhwAQbELAxotp5gIewT/vpOfEWJZPLk= go.opentelemetry.io/collector/extension v0.120.0 h1:CA2e6jF5Sz6PE+yxGbJUn0QTMwTo28MO8FNBhdKAABw= go.opentelemetry.io/collector/extension v0.120.0/go.mod h1:o2/Kk61I1G9XOdD8W4Tbrg05jD4P/QF0ecxYTcT8OZ8= -go.opentelemetry.io/collector/extension/auth v0.120.0 h1:Z4mgQay67BC43F3yK50V/hLdmegBNyMt1upJRV6YW4g= -go.opentelemetry.io/collector/extension/auth v0.120.0/go.mod h1:2DyrUZYNlO3ExAVhflUwvifpxb077Q2aLndcPfkZIzM= go.opentelemetry.io/collector/extension/extensioncapabilities v0.120.0 h1:RaXVtUOiRNuPA5mr8cgieuY1O7M0sVWn2Gvhe24n51c= go.opentelemetry.io/collector/extension/extensioncapabilities v0.120.0/go.mod h1:3PBL7XUwQIzEhnMn12w6XC7sSh9JRUvmdlWs3KJ9KLc= go.opentelemetry.io/collector/extension/extensiontest v0.120.0 h1:DSN2cuuQ+CUVEgEStX04lG4rg/6oZeM2zyeX5wXeGWg= go.opentelemetry.io/collector/extension/extensiontest v0.120.0/go.mod h1:MTFigcQ7hblDUv12b3RbfYvtmzUNZzLiDoug11ezJWQ= go.opentelemetry.io/collector/extension/xextension v0.120.0 h1:2lwasSQI3Fk6zto7u1uaMqDHESZtdq6a9kaAdCPwwO8= go.opentelemetry.io/collector/extension/xextension v0.120.0/go.mod h1:9QT+Rq6YniuuKklpeAYpvp9ezPn2bjLOqzsBiFk55DE= -go.opentelemetry.io/collector/extension/zpagesextension v0.120.0 h1:Oc8F0o3jLzKw5wlB7eqK6vc4K4eF5wSDZfN175qmfTo= -go.opentelemetry.io/collector/extension/zpagesextension v0.120.0/go.mod h1:7BuJXALIFukILETkzGcFhxPQFaYkvXLPpwbtOTMY6DI= go.opentelemetry.io/collector/featuregate v1.26.0 h1:NIZdJby6jL9tEHI25ddeUNgc09Q0Fof31YHF1CSVp4Y= go.opentelemetry.io/collector/featuregate v1.26.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= go.opentelemetry.io/collector/internal/fanoutconsumer v0.120.0 h1:vcY46z2WnYs0bcFulJX51O2dXc2sgWDymR91u/tV5EE= go.opentelemetry.io/collector/internal/fanoutconsumer v0.120.0/go.mod h1:qUcJqy4Us/pxnWJTqloDmlAz8wGUIZDe/RMSmzfymdo= go.opentelemetry.io/collector/internal/telemetry v0.120.0 h1:JsHTY2/9+EYGgg6sqb85KU5iSZow373Z3IZywYTgiUA= go.opentelemetry.io/collector/internal/telemetry v0.120.0/go.mod h1:5F/UCo4WlIjobkypTWgoWTvyIM2AN2INR5/HmvXdilQ= -go.opentelemetry.io/collector/otelcol v0.120.0 h1:iCUzunaztU69MlA+fe1/5VLIuufAFo53psghgaEdamo= -go.opentelemetry.io/collector/otelcol v0.120.0/go.mod h1:nNELe3quKRa4Ra3zTsCOkC7IXii0Z2E2wureB1SW1OA= go.opentelemetry.io/collector/pdata v1.26.0 h1:o7nP0RTQOG0LXk55ZZjLrxwjX8x3wHF7Z7xPeOaskEA= go.opentelemetry.io/collector/pdata v1.26.0/go.mod h1:18e8/xDZsqyj00h/5HM5GLdJgBzzG9Ei8g9SpNoiMtI= go.opentelemetry.io/collector/pdata/pprofile v0.120.0 h1:lQl74z41MN9a0M+JFMZbJVesjndbwHXwUleVrVcTgc8= @@ -302,12 +259,8 @@ go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25P go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= go.opentelemetry.io/contrib/config v0.14.0/go.mod h1:77rDmFPqBae5jtQ2C78RuDTHz4P27C8LzoN0MZyumYQ= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/contrib/propagators/b3 v1.34.0 h1:9pQdCEvV/6RWQmag94D6rhU+A4rzUhYBEJ8bpscx5p8= go.opentelemetry.io/contrib/propagators/b3 v1.34.0/go.mod h1:FwM71WS8i1/mAK4n48t0KU6qUS/OZRBgDrHZv3RlJ+w= -go.opentelemetry.io/contrib/zpages v0.59.0 h1:t0H5zUy8fifIhRuVwm2FrA/D70Kk10SSpAEvvbaNscw= -go.opentelemetry.io/contrib/zpages v0.59.0/go.mod h1:9wo+yUPvHnBQEzoHJ8R3nA/Q5rkef7HjtLlSFI0Tgrc= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= @@ -376,12 +329,8 @@ golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= @@ -426,8 +375,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -istio.io/api v1.24.3 h1:iwWWPM0uEQ+oxRHvIWoB8MQ4bjF3dRQj+M5IDVczg0M= -istio.io/api v1.24.3/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= +istio.io/api v1.25.0 h1:UVQNFUAz4R06NagA+QpEzLmi4sw+m+UuMgD6sIyXawA= +istio.io/api v1.25.0/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= istio.io/client-go v1.24.3 h1:TB8IcM3yyMCDzKRJo0YfFOUGNQmkhwH/JE/Yr3lzVAk= istio.io/client-go v1.24.3/go.mod h1:zSyw/c4luKQKosFIHQaWAQOA0c3bODu4SahQCAMlKA4= k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= From 05ab8db7dbd7172fa7510cdd023df48759ecfe0f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 12:44:36 +0000 Subject: [PATCH 266/426] chore(deps): update peter-evans/create-pull-request action to v7.0.8 (main) (#4537) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 483b348b59..bfc6f49892 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -408,7 +408,7 @@ jobs: hack/build/ci/generate-new-helm-index-yaml.sh "helm-pkg" ${{ needs.prepare.outputs.version_without_prefix }} - name: Create pull request for adding helm index to main branch if: ${{ !contains(github.ref, '-rc.') }} - uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 # v7.0.7 + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 with: base: main delete-branch: true From c928f986dadc7fc299d62ee65ddbb26f06b36b9b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 13:32:35 +0000 Subject: [PATCH 267/426] fix(deps): update module go.opentelemetry.io/collector/confmap to v1.27.0 (main) (#4538) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eb27e460c2..eeae4b0e11 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v0.120.0 - go.opentelemetry.io/collector/confmap v1.26.0 + go.opentelemetry.io/collector/confmap v1.27.0 go.opentelemetry.io/collector/pipeline v0.120.0 go.opentelemetry.io/collector/service v0.120.0 go.uber.org/zap v1.27.0 diff --git a/go.sum b/go.sum index 0547b7594b..16001efca0 100644 --- a/go.sum +++ b/go.sum @@ -191,8 +191,8 @@ go.opentelemetry.io/collector/config/configretry v1.26.0 h1:DGuaZYkGXCr+Wd6+D65x go.opentelemetry.io/collector/config/configretry v1.26.0/go.mod h1:8gzFQ0qzKLYvzP2sNPwsB9gwzKSEls649yANmt/d6yE= go.opentelemetry.io/collector/config/configtelemetry v0.120.0 h1:YPXMpfMd9PhngFXiwi3Lmze/Rs0nGS5wQOX16Elev+8= go.opentelemetry.io/collector/config/configtelemetry v0.120.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= -go.opentelemetry.io/collector/confmap v1.26.0 h1:+EVk0RaCBHs+7dYTwawd5n5tJiiUtErIy3YS3NIFP8o= -go.opentelemetry.io/collector/confmap v1.26.0/go.mod h1:tmOa6iw3FJsEgfBHKALqvcdfRtf71JZGor0wSM5MoH8= +go.opentelemetry.io/collector/confmap v1.27.0 h1:OIjPcjij1NxkVQsQVmHro4+t1eYNFiUGib9+J9YBZhM= +go.opentelemetry.io/collector/confmap v1.27.0/go.mod h1:tmOa6iw3FJsEgfBHKALqvcdfRtf71JZGor0wSM5MoH8= go.opentelemetry.io/collector/confmap/xconfmap v0.120.0 h1:wt+9H/TLXhY6q40AVx+fn2XK/FhjXuwInwFq9X9+aik= go.opentelemetry.io/collector/confmap/xconfmap v0.120.0/go.mod h1:wkzt6fVdLqBP+ZvbJWCLbo68nedvmoK09wFpR17awgs= go.opentelemetry.io/collector/connector v0.120.0 h1:t6/2wOhm2UAgOPRKhMhybna8UjvoJI4hX305CIA2hWU= From 7b432c2c6c050a341ae66cc3183b0ca7de46226a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:53:05 +0000 Subject: [PATCH 268/426] fix(deps): update module go.opentelemetry.io/collector/pipeline to v0.121.0 (main) (#4539) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eeae4b0e11..0dfd1f193d 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v0.120.0 go.opentelemetry.io/collector/confmap v1.27.0 - go.opentelemetry.io/collector/pipeline v0.120.0 + go.opentelemetry.io/collector/pipeline v0.121.0 go.opentelemetry.io/collector/service v0.120.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 diff --git a/go.sum b/go.sum index 16001efca0..da883ca025 100644 --- a/go.sum +++ b/go.sum @@ -235,8 +235,8 @@ go.opentelemetry.io/collector/pdata/pprofile v0.120.0 h1:lQl74z41MN9a0M+JFMZbJVe go.opentelemetry.io/collector/pdata/pprofile v0.120.0/go.mod h1:4zwhklS0qhjptF5GUJTWoCZSTYE+2KkxYrQMuN4doVI= go.opentelemetry.io/collector/pdata/testdata v0.120.0 h1:Zp0LBOv3yzv/lbWHK1oht41OZ4WNbaXb70ENqRY7HnE= go.opentelemetry.io/collector/pdata/testdata v0.120.0/go.mod h1:PfezW5Rzd13CWwrElTZRrjRTSgMGUOOGLfHeBjj+LwY= -go.opentelemetry.io/collector/pipeline v0.120.0 h1:QQQbnLCYiuOqmxIRQ11cvFGt+SXq0rypK3fW8qMkzqQ= -go.opentelemetry.io/collector/pipeline v0.120.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= +go.opentelemetry.io/collector/pipeline v0.121.0 h1:SOiocdyWCJCjWAb96HIxsy9enp2qyQ1NRFo26qyHlCE= +go.opentelemetry.io/collector/pipeline v0.121.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= go.opentelemetry.io/collector/pipeline/xpipeline v0.120.0 h1:klY22BaRMO1+JmjUu0Af961hpHA5qnOTAVR7tN+UTW8= go.opentelemetry.io/collector/pipeline/xpipeline v0.120.0/go.mod h1:K/7Ki7toZQpNV0GF7TbrOEoo8dP3dDXKKSRNnTyEsBE= go.opentelemetry.io/collector/processor v0.120.0 h1:No+I65ybBLVy4jc7CxcsfduiBrm7Z6kGfTnekW3hx1A= From 66bd7a135fa9ab7be220f4b379ab40a3419e73f7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 19:33:18 +0000 Subject: [PATCH 269/426] fix(deps): update module github.com/prometheus/client_golang to v1.21.1 (main) (#4544) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0dfd1f193d..ce618f1bd3 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/klauspost/compress v1.18.0 github.com/opencontainers/go-digest v1.0.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.21.0 + github.com/prometheus/client_golang v1.21.1 github.com/spf13/afero v1.12.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 diff --git a/go.sum b/go.sum index da883ca025..c26e9eeb2a 100644 --- a/go.sum +++ b/go.sum @@ -138,8 +138,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA= -github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= +github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk= +github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= From 54c405172ef68b68f69f5e362ea1cfab840b0a3d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 22:04:34 +0000 Subject: [PATCH 270/426] fix(deps): update module go.opentelemetry.io/collector/service to v0.121.0 (main) (#4540) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 62 ++++++++++++------------- go.sum | 144 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 103 insertions(+), 103 deletions(-) diff --git a/go.mod b/go.mod index ce618f1bd3..d7a6b1daa4 100644 --- a/go.mod +++ b/go.mod @@ -16,10 +16,10 @@ require ( github.com/spf13/afero v1.12.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 - go.opentelemetry.io/collector/component v0.120.0 + go.opentelemetry.io/collector/component v1.27.0 go.opentelemetry.io/collector/confmap v1.27.0 go.opentelemetry.io/collector/pipeline v0.121.0 - go.opentelemetry.io/collector/service v0.120.0 + go.opentelemetry.io/collector/service v0.121.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.23.0 @@ -97,35 +97,35 @@ require ( github.com/vladimirvivien/gexe v0.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/collector/component/componentstatus v0.120.0 // indirect - go.opentelemetry.io/collector/component/componenttest v0.120.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.120.0 // indirect - go.opentelemetry.io/collector/connector v0.120.0 // indirect - go.opentelemetry.io/collector/connector/connectortest v0.120.0 // indirect - go.opentelemetry.io/collector/connector/xconnector v0.120.0 // indirect - go.opentelemetry.io/collector/consumer v1.26.0 // indirect - go.opentelemetry.io/collector/consumer/consumererror v0.120.0 // indirect - go.opentelemetry.io/collector/consumer/consumertest v0.120.0 // indirect - go.opentelemetry.io/collector/consumer/xconsumer v0.120.0 // indirect - go.opentelemetry.io/collector/exporter v0.120.0 // indirect - go.opentelemetry.io/collector/exporter/exportertest v0.120.0 // indirect - go.opentelemetry.io/collector/exporter/xexporter v0.120.0 // indirect - go.opentelemetry.io/collector/extension v0.120.0 // indirect - go.opentelemetry.io/collector/extension/extensioncapabilities v0.120.0 // indirect - go.opentelemetry.io/collector/extension/extensiontest v0.120.0 // indirect - go.opentelemetry.io/collector/featuregate v1.26.0 // indirect - go.opentelemetry.io/collector/internal/fanoutconsumer v0.120.0 // indirect - go.opentelemetry.io/collector/internal/telemetry v0.120.0 // indirect - go.opentelemetry.io/collector/pdata v1.26.0 // indirect - go.opentelemetry.io/collector/pdata/pprofile v0.120.0 // indirect - go.opentelemetry.io/collector/pdata/testdata v0.120.0 // indirect - go.opentelemetry.io/collector/pipeline/xpipeline v0.120.0 // indirect - go.opentelemetry.io/collector/processor v0.120.0 // indirect - go.opentelemetry.io/collector/processor/processortest v0.120.0 // indirect - go.opentelemetry.io/collector/processor/xprocessor v0.120.0 // indirect - go.opentelemetry.io/collector/receiver v0.120.0 // indirect - go.opentelemetry.io/collector/receiver/receivertest v0.120.0 // indirect - go.opentelemetry.io/collector/receiver/xreceiver v0.120.0 // indirect + go.opentelemetry.io/collector/component/componentstatus v0.121.0 // indirect + go.opentelemetry.io/collector/component/componenttest v0.121.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.121.0 // indirect + go.opentelemetry.io/collector/connector v0.121.0 // indirect + go.opentelemetry.io/collector/connector/connectortest v0.121.0 // indirect + go.opentelemetry.io/collector/connector/xconnector v0.121.0 // indirect + go.opentelemetry.io/collector/consumer v1.27.0 // indirect + go.opentelemetry.io/collector/consumer/consumererror v0.121.0 // indirect + go.opentelemetry.io/collector/consumer/consumertest v0.121.0 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.121.0 // indirect + go.opentelemetry.io/collector/exporter v0.121.0 // indirect + go.opentelemetry.io/collector/exporter/exportertest v0.121.0 // indirect + go.opentelemetry.io/collector/exporter/xexporter v0.121.0 // indirect + go.opentelemetry.io/collector/extension v1.27.0 // indirect + go.opentelemetry.io/collector/extension/extensioncapabilities v0.121.0 // indirect + go.opentelemetry.io/collector/extension/extensiontest v0.121.0 // indirect + go.opentelemetry.io/collector/featuregate v1.27.0 // indirect + go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0 // indirect + go.opentelemetry.io/collector/internal/telemetry v0.121.0 // indirect + go.opentelemetry.io/collector/pdata v1.27.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.121.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.121.0 // indirect + go.opentelemetry.io/collector/pipeline/xpipeline v0.121.0 // indirect + go.opentelemetry.io/collector/processor v0.121.0 // indirect + go.opentelemetry.io/collector/processor/processortest v0.121.0 // indirect + go.opentelemetry.io/collector/processor/xprocessor v0.121.0 // indirect + go.opentelemetry.io/collector/receiver v0.121.0 // indirect + go.opentelemetry.io/collector/receiver/receivertest v0.121.0 // indirect + go.opentelemetry.io/collector/receiver/xreceiver v0.121.0 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect go.opentelemetry.io/contrib/config v0.14.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect diff --git a/go.sum b/go.sum index c26e9eeb2a..18a6993a01 100644 --- a/go.sum +++ b/go.sum @@ -179,82 +179,82 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/collector v0.120.0 h1:RmEFc4rPB0wg7fEDY0k8OenXznAtsVGzgAkjTAF44WQ= -go.opentelemetry.io/collector v0.120.0/go.mod h1:uNDaRieHl04oQCvGFY4KzpDRqejgMNbea0u2+vk7P3k= -go.opentelemetry.io/collector/component v0.120.0 h1:YHEQ6NuBI6FQHKW24OwrNg2IJ0EUIg4RIuwV5YQ6PSI= -go.opentelemetry.io/collector/component v0.120.0/go.mod h1:Ya5O+5NWG9XdhJPnOVhKtBrNXHN3hweQbB98HH4KPNU= -go.opentelemetry.io/collector/component/componentstatus v0.120.0 h1:hzKjI9+AIl8A/saAARb47JqabWsge0kMp8NSPNiCNOQ= -go.opentelemetry.io/collector/component/componentstatus v0.120.0/go.mod h1:kbuAEddxvcyjGLXGmys3nckAj4jTGC0IqDIEXAOr3Ag= -go.opentelemetry.io/collector/component/componenttest v0.120.0 h1:vKX85d3lpxj/RoiFQNvmIpX9lOS80FY5svzOYUyeYX0= -go.opentelemetry.io/collector/component/componenttest v0.120.0/go.mod h1:QDLboWF2akEqAGyvje8Hc7GfXcrZvQ5FhmlWvD5SkzY= -go.opentelemetry.io/collector/config/configretry v1.26.0 h1:DGuaZYkGXCr+Wd6+D65xZv7E9z/nyt/F//XbC4B/7M4= -go.opentelemetry.io/collector/config/configretry v1.26.0/go.mod h1:8gzFQ0qzKLYvzP2sNPwsB9gwzKSEls649yANmt/d6yE= -go.opentelemetry.io/collector/config/configtelemetry v0.120.0 h1:YPXMpfMd9PhngFXiwi3Lmze/Rs0nGS5wQOX16Elev+8= -go.opentelemetry.io/collector/config/configtelemetry v0.120.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= +go.opentelemetry.io/collector v0.121.0 h1:K23nHTjhqKDOYpBUDyeK0/Yjzs5Py8Ysvec7zyKXuK0= +go.opentelemetry.io/collector v0.121.0/go.mod h1:M4TlnmkjIgishm2DNCk9K3hMKTmAsY9w8cNFsp9EchM= +go.opentelemetry.io/collector/component v1.27.0 h1:6wk0K23YT9lSprX8BH9x5w8ssAORE109ekH/ix2S614= +go.opentelemetry.io/collector/component v1.27.0/go.mod h1:fIyBHoa7vDyZL3Pcidgy45cx24tBe7iHWne097blGgo= +go.opentelemetry.io/collector/component/componentstatus v0.121.0 h1:G4KqBUuAqnQ1kB3fUxXPwspjwnhGZzdArlO7vc343og= +go.opentelemetry.io/collector/component/componentstatus v0.121.0/go.mod h1:ufRv8q15XNdbr9nNzdepMHlLl2aC3NHQgecCzp5VRns= +go.opentelemetry.io/collector/component/componenttest v0.121.0 h1:4q1/7WnP9LPKaY4HAd8/OkzhllZpRACKAOlWsqbrzqc= +go.opentelemetry.io/collector/component/componenttest v0.121.0/go.mod h1:H7bEXDPMYNeWcHal0xyKlVfRPByVxale7hCJ+Myjq3Q= +go.opentelemetry.io/collector/config/configretry v1.27.0 h1:mM0X/7eiWRVmYTZJ5QTtly10uJWHnctIFuYST6tc/zU= +go.opentelemetry.io/collector/config/configretry v1.27.0/go.mod h1:8gzFQ0qzKLYvzP2sNPwsB9gwzKSEls649yANmt/d6yE= +go.opentelemetry.io/collector/config/configtelemetry v0.121.0 h1:0nEcLHRjr6E9P0LXhy7uluPpOw78YZ4N0t6pZJ5ug0g= +go.opentelemetry.io/collector/config/configtelemetry v0.121.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= go.opentelemetry.io/collector/confmap v1.27.0 h1:OIjPcjij1NxkVQsQVmHro4+t1eYNFiUGib9+J9YBZhM= go.opentelemetry.io/collector/confmap v1.27.0/go.mod h1:tmOa6iw3FJsEgfBHKALqvcdfRtf71JZGor0wSM5MoH8= -go.opentelemetry.io/collector/confmap/xconfmap v0.120.0 h1:wt+9H/TLXhY6q40AVx+fn2XK/FhjXuwInwFq9X9+aik= -go.opentelemetry.io/collector/confmap/xconfmap v0.120.0/go.mod h1:wkzt6fVdLqBP+ZvbJWCLbo68nedvmoK09wFpR17awgs= -go.opentelemetry.io/collector/connector v0.120.0 h1:t6/2wOhm2UAgOPRKhMhybna8UjvoJI4hX305CIA2hWU= -go.opentelemetry.io/collector/connector v0.120.0/go.mod h1:REneUxc1SnH07DlNXCvh0ZBBi67wAT4HpzAPRmIt378= -go.opentelemetry.io/collector/connector/connectortest v0.120.0 h1:Blh4QsVBoPoT9dR4GC6f1oGrzotkOOElevTQOk9Wn7c= -go.opentelemetry.io/collector/connector/connectortest v0.120.0/go.mod h1:NPyD5TVRND637kd+5nTeik8ZDl82MNJXln3mY80sY2M= -go.opentelemetry.io/collector/connector/xconnector v0.120.0 h1:waYzmPSRr9BwDJxFO2wYgfPIttPhaIdyKj2xRTYLXZo= -go.opentelemetry.io/collector/connector/xconnector v0.120.0/go.mod h1:wpy9ab9AAZiekNPKZoaEmXWDmzIdQ2o2xNSgx6Otamg= -go.opentelemetry.io/collector/consumer v1.26.0 h1:0MwuzkWFLOm13qJvwW85QkoavnGpR4ZObqCs9g1XAvk= -go.opentelemetry.io/collector/consumer v1.26.0/go.mod h1:I/ZwlWM0sbFLhbStpDOeimjtMbWpMFSoGdVmzYxLGDg= -go.opentelemetry.io/collector/consumer/consumererror v0.120.0 h1:f46ZnKCGBdvkjtJBT0ruA9cxDnvuR1jeR0amq9qc6Mc= -go.opentelemetry.io/collector/consumer/consumererror v0.120.0/go.mod h1:2Cx8948nywlM1MFJgqLrIJ7N/pfxZsMF0qq+n9oFJz0= -go.opentelemetry.io/collector/consumer/consumertest v0.120.0 h1:iPFmXygDsDOjqwdQ6YZcTmpiJeQDJX+nHvrjTPsUuv4= -go.opentelemetry.io/collector/consumer/consumertest v0.120.0/go.mod h1:HeSnmPfAEBnjsRR5UY1fDTLlSrYsMsUjufg1ihgnFJ0= -go.opentelemetry.io/collector/consumer/xconsumer v0.120.0 h1:dzM/3KkFfMBIvad+NVXDV+mA+qUpHyu5c70TFOjDg68= -go.opentelemetry.io/collector/consumer/xconsumer v0.120.0/go.mod h1:eOf7RX9CYC7bTZQFg0z2GHdATpQDxI0DP36F9gsvXOQ= -go.opentelemetry.io/collector/exporter v0.120.0 h1:8PIJTV0VW1gyr8XuiEMi/aq+baCMdk1hjSrAYiG8aKk= -go.opentelemetry.io/collector/exporter v0.120.0/go.mod h1:JZCNkv0K+Gwdnfwby7Nxc1/gsmy468SBIjI/6fQdxuk= -go.opentelemetry.io/collector/exporter/exportertest v0.120.0 h1:7ABriAYXGxvUdCXxe0LpsrMGQ+BP5z/gadm1gRWbD4o= -go.opentelemetry.io/collector/exporter/exportertest v0.120.0/go.mod h1:t0hONsvJp5MM1EF1l83voJHcharIPdnpUBP42UhCoCY= -go.opentelemetry.io/collector/exporter/xexporter v0.120.0 h1:HSe3a+0lt/o/g8GgNKgkw9y9vULN4QeY6NeKms8j/GI= -go.opentelemetry.io/collector/exporter/xexporter v0.120.0/go.mod h1:P/87SRTCd/PnQhwAQbELAxotp5gIewT/vpOfEWJZPLk= -go.opentelemetry.io/collector/extension v0.120.0 h1:CA2e6jF5Sz6PE+yxGbJUn0QTMwTo28MO8FNBhdKAABw= -go.opentelemetry.io/collector/extension v0.120.0/go.mod h1:o2/Kk61I1G9XOdD8W4Tbrg05jD4P/QF0ecxYTcT8OZ8= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.120.0 h1:RaXVtUOiRNuPA5mr8cgieuY1O7M0sVWn2Gvhe24n51c= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.120.0/go.mod h1:3PBL7XUwQIzEhnMn12w6XC7sSh9JRUvmdlWs3KJ9KLc= -go.opentelemetry.io/collector/extension/extensiontest v0.120.0 h1:DSN2cuuQ+CUVEgEStX04lG4rg/6oZeM2zyeX5wXeGWg= -go.opentelemetry.io/collector/extension/extensiontest v0.120.0/go.mod h1:MTFigcQ7hblDUv12b3RbfYvtmzUNZzLiDoug11ezJWQ= -go.opentelemetry.io/collector/extension/xextension v0.120.0 h1:2lwasSQI3Fk6zto7u1uaMqDHESZtdq6a9kaAdCPwwO8= -go.opentelemetry.io/collector/extension/xextension v0.120.0/go.mod h1:9QT+Rq6YniuuKklpeAYpvp9ezPn2bjLOqzsBiFk55DE= -go.opentelemetry.io/collector/featuregate v1.26.0 h1:NIZdJby6jL9tEHI25ddeUNgc09Q0Fof31YHF1CSVp4Y= -go.opentelemetry.io/collector/featuregate v1.26.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.120.0 h1:vcY46z2WnYs0bcFulJX51O2dXc2sgWDymR91u/tV5EE= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.120.0/go.mod h1:qUcJqy4Us/pxnWJTqloDmlAz8wGUIZDe/RMSmzfymdo= -go.opentelemetry.io/collector/internal/telemetry v0.120.0 h1:JsHTY2/9+EYGgg6sqb85KU5iSZow373Z3IZywYTgiUA= -go.opentelemetry.io/collector/internal/telemetry v0.120.0/go.mod h1:5F/UCo4WlIjobkypTWgoWTvyIM2AN2INR5/HmvXdilQ= -go.opentelemetry.io/collector/pdata v1.26.0 h1:o7nP0RTQOG0LXk55ZZjLrxwjX8x3wHF7Z7xPeOaskEA= -go.opentelemetry.io/collector/pdata v1.26.0/go.mod h1:18e8/xDZsqyj00h/5HM5GLdJgBzzG9Ei8g9SpNoiMtI= -go.opentelemetry.io/collector/pdata/pprofile v0.120.0 h1:lQl74z41MN9a0M+JFMZbJVesjndbwHXwUleVrVcTgc8= -go.opentelemetry.io/collector/pdata/pprofile v0.120.0/go.mod h1:4zwhklS0qhjptF5GUJTWoCZSTYE+2KkxYrQMuN4doVI= -go.opentelemetry.io/collector/pdata/testdata v0.120.0 h1:Zp0LBOv3yzv/lbWHK1oht41OZ4WNbaXb70ENqRY7HnE= -go.opentelemetry.io/collector/pdata/testdata v0.120.0/go.mod h1:PfezW5Rzd13CWwrElTZRrjRTSgMGUOOGLfHeBjj+LwY= +go.opentelemetry.io/collector/confmap/xconfmap v0.121.0 h1:pZ7SOl/i3kUIPdUwIeHHsYqzOHNLCwiyXZnwQ7rLO3E= +go.opentelemetry.io/collector/confmap/xconfmap v0.121.0/go.mod h1:YI1Sp8mbYro/H3rqH4csTq68VUuie5WVb7LI1o5+tVc= +go.opentelemetry.io/collector/connector v0.121.0 h1:Bhre1CU8+nvXhOO74ZjCQth6JIwuRgGmUVFU5I6fDhY= +go.opentelemetry.io/collector/connector v0.121.0/go.mod h1:njtHMkFOuZ5W5Ax2BnsqC8EThgTU7tF1k7OBpRs0+uQ= +go.opentelemetry.io/collector/connector/connectortest v0.121.0 h1:3MhdOd5Sbd4kE/gjY8WDc0lb5Y2V1IEeYfRss8P5tnU= +go.opentelemetry.io/collector/connector/connectortest v0.121.0/go.mod h1:Xu4oO85n1yi2+7RNq0MzjW9LYeW17mXn5qmTe1o/al8= +go.opentelemetry.io/collector/connector/xconnector v0.121.0 h1:bWgg0zRD/pTeRZb5mhhOMZMuaru/txA5M8loCBOIPho= +go.opentelemetry.io/collector/connector/xconnector v0.121.0/go.mod h1:1Y/ypNTUkWEkm+nUP8mWKVMIRnQ/UPUuetp7RgnSfN0= +go.opentelemetry.io/collector/consumer v1.27.0 h1:JoXdoCeFDJG3d9TYrKHvTT4eBhzKXDVTkWW5mDfnLiY= +go.opentelemetry.io/collector/consumer v1.27.0/go.mod h1:1B/+kTDUI6u3mCIOAkm5ityIpv5uC0Ll78IA50SNZ24= +go.opentelemetry.io/collector/consumer/consumererror v0.121.0 h1:yFcCqi4Djhl2oUxYIyi5FAeLit/m1ah0sAokZKsP3zM= +go.opentelemetry.io/collector/consumer/consumererror v0.121.0/go.mod h1:kHrvHQ8AuWVjhSFixR51iEozdnoGkX6AjDWyhr3gSDo= +go.opentelemetry.io/collector/consumer/consumertest v0.121.0 h1:EIJPAXQY0w9j1k/e5OzJqOYVEr6WljKpJBjgkkp/hWw= +go.opentelemetry.io/collector/consumer/consumertest v0.121.0/go.mod h1:Hmj+TizzsLU0EmS2n/rJYScOybNmm3mrAjis6ed7qTw= +go.opentelemetry.io/collector/consumer/xconsumer v0.121.0 h1:/FJ7L6+G++FvktXc/aBnnYDIKLoYsWLh0pKbvzFFwF8= +go.opentelemetry.io/collector/consumer/xconsumer v0.121.0/go.mod h1:KKy8Qg/vOnyseoi7A9/x1a1oEqSmf0WBHkJFlnQH0Ow= +go.opentelemetry.io/collector/exporter v0.121.0 h1:HkE/qvnhmPtI/O/ITloukHFt4Ywmz6YzyWyWAqNGoKI= +go.opentelemetry.io/collector/exporter v0.121.0/go.mod h1:Xi4UtotE9QdA7UGkJVxHyg4grycYIKVDp/F+henuv3k= +go.opentelemetry.io/collector/exporter/exportertest v0.121.0 h1:kjtZwZd0Mj5VZv3JGxuQBnqmfmOCcCdhpz0G4INd6o0= +go.opentelemetry.io/collector/exporter/exportertest v0.121.0/go.mod h1:xGIi17/Ffteh308BRruHXVzq51o7wxYcUch0zXzyrqA= +go.opentelemetry.io/collector/exporter/xexporter v0.121.0 h1:e5QIl51EutJrH8X4tfnQUgfz1ebXPlLUzTltlT40IAc= +go.opentelemetry.io/collector/exporter/xexporter v0.121.0/go.mod h1:PGrW5pOQkNpaz8xqtkITCNEkcJVxOHSptg2chVTtv+o= +go.opentelemetry.io/collector/extension v1.27.0 h1:7F+O8/+bcwo3Zk3B/+H8A75cz9dhqXUrbeiyiFajoy4= +go.opentelemetry.io/collector/extension v1.27.0/go.mod h1:Fe0nUGMcr0c6IIBD3QEa3XmdUYpfmm5wCjc3PYho8DM= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.121.0 h1:Xj9UY6KCfydV1RfPi3ycR94pQSoN4oT9b0rdwsDDOGg= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.121.0/go.mod h1:Wz7FanSxDq2aCbclOfqXTAm5CvWJCWeXzO6quzAGG04= +go.opentelemetry.io/collector/extension/extensiontest v0.121.0 h1:ce3IEWXBDOOSljd0niVbwHs7AhC8hOjC2RXGIoMOXog= +go.opentelemetry.io/collector/extension/extensiontest v0.121.0/go.mod h1:yrZhZhf2a3aD0/17drjHnzSTlr0XnNREVrOLYBlcP1o= +go.opentelemetry.io/collector/extension/xextension v0.121.0 h1:RIhFXwm9+2sc6H2PsM9asGfEBlIDBrK+dyyFMx257bs= +go.opentelemetry.io/collector/extension/xextension v0.121.0/go.mod h1:EiGx9nRD/7TU4++2/f5+2wdxUnDvjINCpWKLgfF2JRA= +go.opentelemetry.io/collector/featuregate v1.27.0 h1:4LLrccoMz/gJT5uym8ojBlMzY5tr4RzUUXzwlBuiRz0= +go.opentelemetry.io/collector/featuregate v1.27.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0 h1:gefyTUyn1WHIPvcPUB7LEbPEVj1VB2wqjh2cvxrMzVg= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0/go.mod h1:JM4FHRtacWUGEiZUpR2utoRfvgTdvYk+3OBJjyD9RzQ= +go.opentelemetry.io/collector/internal/telemetry v0.121.0 h1:vSJg6eS2rpxL8gGFDQEO8OTsIYRO2sDKiyUyEHAFspU= +go.opentelemetry.io/collector/internal/telemetry v0.121.0/go.mod h1:B8og4U7fKoCBrumTxSTr6PKbXDc1t9H1a8bKBcZjHQk= +go.opentelemetry.io/collector/pdata v1.27.0 h1:66yI7FYkUDia74h48Fd2/KG2Vk8DxZnGw54wRXykCEU= +go.opentelemetry.io/collector/pdata v1.27.0/go.mod h1:18e8/xDZsqyj00h/5HM5GLdJgBzzG9Ei8g9SpNoiMtI= +go.opentelemetry.io/collector/pdata/pprofile v0.121.0 h1:DFBelDRsZYxEaSoxSRtseAazsHJfqfC/Yl64uPicl2g= +go.opentelemetry.io/collector/pdata/pprofile v0.121.0/go.mod h1:j/fjrd7ybJp/PXkba92QLzx7hykUVmU8x/WJvI2JWSg= +go.opentelemetry.io/collector/pdata/testdata v0.121.0 h1:FFz+rdb7o6JRZ82Zmp6WKEdKnEMaoF3jLb7F1F21ijg= +go.opentelemetry.io/collector/pdata/testdata v0.121.0/go.mod h1:UhiSwmVpBbuKlPdmhBytiVTHipSz/JO6c4mbD4kWOPg= go.opentelemetry.io/collector/pipeline v0.121.0 h1:SOiocdyWCJCjWAb96HIxsy9enp2qyQ1NRFo26qyHlCE= go.opentelemetry.io/collector/pipeline v0.121.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= -go.opentelemetry.io/collector/pipeline/xpipeline v0.120.0 h1:klY22BaRMO1+JmjUu0Af961hpHA5qnOTAVR7tN+UTW8= -go.opentelemetry.io/collector/pipeline/xpipeline v0.120.0/go.mod h1:K/7Ki7toZQpNV0GF7TbrOEoo8dP3dDXKKSRNnTyEsBE= -go.opentelemetry.io/collector/processor v0.120.0 h1:No+I65ybBLVy4jc7CxcsfduiBrm7Z6kGfTnekW3hx1A= -go.opentelemetry.io/collector/processor v0.120.0/go.mod h1:4zaJGLZCK8XKChkwlGC/gn0Dj4Yke04gQCu4LGbJGro= -go.opentelemetry.io/collector/processor/processortest v0.120.0 h1:R+VSVSU59W0/mPAcyt8/h1d0PfWN6JI2KY5KeMICXvo= -go.opentelemetry.io/collector/processor/processortest v0.120.0/go.mod h1:me+IVxPsj4IgK99I0pgKLX34XnJtcLwqtgTuVLhhYDI= -go.opentelemetry.io/collector/processor/xprocessor v0.120.0 h1:mBznj/1MtNqmu6UpcoXz6a63tU0931oWH2pVAt2+hzo= -go.opentelemetry.io/collector/processor/xprocessor v0.120.0/go.mod h1:Nsp0sDR3gE+GAhi9d0KbN0RhOP+BK8CGjBRn8+9d/SY= -go.opentelemetry.io/collector/receiver v0.120.0 h1:JTnPqmBLRXpOyLPh8Kch/5C8SivnpYK9Lzy4PvtEnLQ= -go.opentelemetry.io/collector/receiver v0.120.0/go.mod h1:jpYY55wTVE0FqiBIJrNv2HrvSUnGEjLS/3CWGA+CeL4= -go.opentelemetry.io/collector/receiver/receivertest v0.120.0 h1:Op9yCT0kGvqPF0BB83+iOcsxJJHPCLeL4f4/Op1MBoI= -go.opentelemetry.io/collector/receiver/receivertest v0.120.0/go.mod h1:lpFA4FzcHWki7rLzsNncYmDZ4f7Eik8JY1Mmsaw5uMw= -go.opentelemetry.io/collector/receiver/xreceiver v0.120.0 h1:+gHYd9rTBRKSQfWsTzV2wlwfaVL/LZSz5wu4sygZH7w= -go.opentelemetry.io/collector/receiver/xreceiver v0.120.0/go.mod h1:dkHpL1QqLi/G+60VZnfFpZQf9qoxDVnp6G9FuAcMgfk= -go.opentelemetry.io/collector/semconv v0.120.0 h1:iG9N78c2IZN4XOH7ZSdAQJBbaHDTuPnTlbQjKV9uIPY= -go.opentelemetry.io/collector/semconv v0.120.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= -go.opentelemetry.io/collector/service v0.120.0 h1:7E0ILhOYP72qZBNmprsJxLFozEuXlF0Evy5e4HinTJI= -go.opentelemetry.io/collector/service v0.120.0/go.mod h1:hRVK2Tvgm6W+8zb6NZ4fKuhMot3jzz6tu9YHDgwIQ8E= +go.opentelemetry.io/collector/pipeline/xpipeline v0.121.0 h1:Mkw2Jk43TK2hzY6nLy1koO1XD/KUj8nzK2FB+/WDxoM= +go.opentelemetry.io/collector/pipeline/xpipeline v0.121.0/go.mod h1:nTfAnIPgIwevodUp9z0gwfl2S+lVEvz3CjhOqU/Lk/8= +go.opentelemetry.io/collector/processor v0.121.0 h1:OcLrJ2F17cU0oDtXEYbGvL8vbku/kRQgAafSZ3+8jLY= +go.opentelemetry.io/collector/processor v0.121.0/go.mod h1:BoFEMvPn5/p53eWz+R9cibIxCXzaRZ/RtcBPtvqXNaQ= +go.opentelemetry.io/collector/processor/processortest v0.121.0 h1:1c3mEABELrxdC1obSQjIlfh5jZljJlzUravmzy1Mofo= +go.opentelemetry.io/collector/processor/processortest v0.121.0/go.mod h1:oL4S/eguZ6XTK6IxAQXhXD9yWuRrG5/Maiskbf9HL0o= +go.opentelemetry.io/collector/processor/xprocessor v0.121.0 h1:AiqDKzpEYZpiP9y3RRp4G9ym6fG2f9HByu3yWkSdd2E= +go.opentelemetry.io/collector/processor/xprocessor v0.121.0/go.mod h1:Puk+6YYKyqLVKqpftUXg0blMrd3BlH/Av+oiajp1sHQ= +go.opentelemetry.io/collector/receiver v0.121.0 h1:gQGAiSXX5ZjAqb3fZVlZc4DjT90at/HmnKzNG/XIdZw= +go.opentelemetry.io/collector/receiver v0.121.0/go.mod h1:CqvQRwGGOqq6PRI6qmkKzF7AYWwRZTpCX6w7U3wIAmQ= +go.opentelemetry.io/collector/receiver/receivertest v0.121.0 h1:kdwV0tkaawRwKoZ1hl2xeYo4Oqfoa5drNX5I2J+rKhk= +go.opentelemetry.io/collector/receiver/receivertest v0.121.0/go.mod h1:H7N4CLG4J8Do3NWeo9gj7VmJCtDstDeeCffPBgHu1WQ= +go.opentelemetry.io/collector/receiver/xreceiver v0.121.0 h1:F6IVdEArgicLVtDtZ2Ovmjv8o6+3AyxYaC3HdNIbakM= +go.opentelemetry.io/collector/receiver/xreceiver v0.121.0/go.mod h1:ZsI1dzGq9J8y0f8h8MYYnoyC8SRJ5u1OqVRX2EwdZwo= +go.opentelemetry.io/collector/semconv v0.121.0 h1:dtdgh5TsKWGZXIBMsyCMVrY1VgmyWlXHgWx/VH9tL1U= +go.opentelemetry.io/collector/semconv v0.121.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= +go.opentelemetry.io/collector/service v0.121.0 h1:fh4pTRwYfsmXry2tc03eIbchEQUE3KGbRn0d/0IghMI= +go.opentelemetry.io/collector/service v0.121.0/go.mod h1:39g0114ia8bxz/MnlJk12DvAJuIQKijFJg7PdD0ydQw= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25PkeyWmOcI+SjXWguNw= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= From 128cc83ce2d29080b1d120f3ac5e621f97335839 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 02:40:49 +0000 Subject: [PATCH 271/426] chore(deps): update dependency redhat-openshift-ecosystem/openshift-preflight to v1.12.1 (main) (#4545) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/preflight/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/preflight/action.yaml b/.github/actions/preflight/action.yaml index 56adf6fce8..6fa5fc039e 100644 --- a/.github/actions/preflight/action.yaml +++ b/.github/actions/preflight/action.yaml @@ -29,7 +29,7 @@ runs: RHCC_APITOKEN: ${{ inputs.pyxis-api-token }} RHCC_PROJECT_ID: ${{ inputs.redhat-project-id }} # renovate depName=redhat-openshift-ecosystem/openshift-preflight - PREFLIGHT_VERSION: 1.12.0 + PREFLIGHT_VERSION: 1.12.1 IMAGE_URI: ${{ inputs.registry }}/${{ inputs.repository }}:${{ inputs.version }} run: | hack/build/ci/preflight.sh "${{ env.PREFLIGHT_VERSION }}" "${{ env.IMAGE_URI}}" "${{ inputs.report-name }}" From 195ba437d291b96e6abf0765df25344413824fd3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 07:15:09 +0000 Subject: [PATCH 272/426] chore(deps): update golang docker tag to v1.24.1 (main) (#4546) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8239171837..b5b7b8d0d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # check=skip=RedundantTargetPlatform # setup build image -FROM --platform=$BUILDPLATFORM golang:1.24.0@sha256:4546829ecda4404596cf5c9d8936488283910a3564ffc8fe4f32b33ddaeff239 AS operator-build +FROM --platform=$BUILDPLATFORM golang:1.24.1@sha256:c5adecdb7b3f8c5ca3c88648a861882849cc8b02fed68ece31e25de88ad13418 AS operator-build WORKDIR /app From c586d0b4333fad2ef7c7dfcbe1c706ea6f24aca2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 08:21:54 +0000 Subject: [PATCH 273/426] chore(deps): update module github.com/helm-unittest/helm-unittest to v0.8.0 (main) (#4547) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 9119b6b74b..a2ff16740d 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -13,7 +13,7 @@ mockery_version=v2.53.0 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest -helmunittest_version=v0.7.2 +helmunittest_version=v0.8.0 # renovate depName=github.com/princjef/gomarkdoc gomarkdoc_version=v1.1.0 # renovate depName=github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod From ef5511cf77142570501edeb24cbed918050d2331 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Wed, 5 Mar 2025 09:35:44 +0100 Subject: [PATCH 274/426] Create bootstrapper config secret instead of existing dynakube config if needed (#4515) --- .../Common/operator/clusterrole-operator.yaml | 1 + doc/api/feature-flags.md | 2 +- go.mod | 3 +- go.sum | 41 ++ pkg/api/v1beta3/dynakube/dynakube_props.go | 4 + pkg/api/v1beta3/dynakube/feature_flags.go | 6 +- pkg/api/validation/dynakube/oneagent.go | 4 +- pkg/api/validation/dynakube/oneagent_test.go | 52 ++- pkg/consts/agent_injection.go | 2 + .../csi/provisioner/controller_test.go | 2 +- pkg/controllers/csi/provisioner/install.go | 2 +- .../dynakube/injection/reconciler.go | 55 ++- .../dynakube/injection/reconciler_test.go | 41 ++ .../processmoduleconfigsecret/conditions.go | 2 +- .../processmoduleconfigsecret/reconciler.go | 22 +- .../reconciler_test.go | 12 +- .../bootstrapperconfig/bootstrapperconfig.go | 112 ++++++ .../bootstrapperconfig_test.go | 373 ++++++++++++++++++ .../namespace/bootstrapperconfig/config.go | 7 + .../namespace/bootstrapperconfig/endpoints.go | 60 +++ .../namespace/bootstrapperconfig/pmc.go | 68 ++++ .../namespace/ingestendpoint/secret.go | 12 +- pkg/injection/namespace/mapper/dynakubes.go | 7 +- .../namespace/mapper/dynakubes_test.go | 57 +++ pkg/injection/namespace/mapper/mapper_test.go | 12 + pkg/webhook/mutation/pod/oneagent/config.go | 7 +- pkg/webhook/mutation/pod/oneagent/mutator.go | 11 + .../mutation/pod/oneagent/mutator_test.go | 31 ++ 28 files changed, 959 insertions(+), 49 deletions(-) create mode 100644 pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go create mode 100644 pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go create mode 100644 pkg/injection/namespace/bootstrapperconfig/config.go create mode 100644 pkg/injection/namespace/bootstrapperconfig/endpoints.go create mode 100644 pkg/injection/namespace/bootstrapperconfig/pmc.go diff --git a/config/helm/chart/default/templates/Common/operator/clusterrole-operator.yaml b/config/helm/chart/default/templates/Common/operator/clusterrole-operator.yaml index b9d5c46c1d..1641438406 100644 --- a/config/helm/chart/default/templates/Common/operator/clusterrole-operator.yaml +++ b/config/helm/chart/default/templates/Common/operator/clusterrole-operator.yaml @@ -49,6 +49,7 @@ rules: resources: - secrets resourceNames: + - dynatrace-bootstrapper-config - dynatrace-dynakube-config - dynatrace-metadata-enrichment-endpoint verbs: diff --git a/doc/api/feature-flags.md b/doc/api/feature-flags.md index 4f8cbce445..b3a5ace476 100644 --- a/doc/api/feature-flags.md +++ b/doc/api/feature-flags.md @@ -59,7 +59,7 @@ const ( AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureDownloadViaJob = AnnotationFeatureCodeModulesPrefix + "remote-image-download" + AnnotationFeatureRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remote-image-download" ) ``` diff --git a/go.mod b/go.mod index d7a6b1daa4..71c5e368b0 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,9 @@ module github.com/Dynatrace/dynatrace-operator -go 1.23.3 +go 1.23.4 require ( + github.com/Dynatrace/dynatrace-bootstrapper v0.2.1 github.com/container-storage-interface/spec v1.11.0 github.com/docker/cli v28.0.1+incompatible github.com/evanphx/json-patch v5.9.11+incompatible diff --git a/go.sum b/go.sum index 18a6993a01..9861ff8d98 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,11 @@ +github.com/Dynatrace/dynatrace-bootstrapper v0.2.1 h1:RgoDGe4dSaZ0YKVAz4+fo7j0F/v/Y1FKFpgSsrei2FA= +github.com/Dynatrace/dynatrace-bootstrapper v0.2.1/go.mod h1:Vx5mNVnDs0eVQiDu6j5WYVTgzc0Qo42oGEtOA6NJpS4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -24,6 +28,8 @@ github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZ github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= @@ -44,6 +50,8 @@ github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1 github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= @@ -62,6 +70,8 @@ github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYu github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -73,8 +83,13 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -104,6 +119,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -171,8 +188,12 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= +github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo= +github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vladimirvivien/gexe v0.2.0 h1:nbdAQ6vbZ+ZNsolCgSVb9Fno60kzSuvtzVh6Ytqi/xY= github.com/vladimirvivien/gexe v0.2.0/go.mod h1:LHQL00w/7gDUKIak24n801ABp8C+ni6eBht9vGVst8w= +github.com/vladimirvivien/gexe v0.4.1 h1:W9gWkp8vSPjDoXDu04Yp4KljpVMaSt8IQuHswLDd5LY= +github.com/vladimirvivien/gexe v0.4.1/go.mod h1:3gjgTqE2c0VyHnU5UOIwk7gyNzZDGulPb/DJPgcw64E= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -310,6 +331,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4= +golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= @@ -341,6 +364,8 @@ golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -357,8 +382,12 @@ gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= +google.golang.org/genproto/googleapis/api v0.0.0-20250224174004-546df14abb99 h1:ilJhrCga0AptpJZXmUYG4MCrx/zf3l1okuYz7YK9PPw= +google.golang.org/genproto/googleapis/api v0.0.0-20250224174004-546df14abb99/go.mod h1:Xsh8gBVxGCcbV8ZeTB9wI5XPyZ5RvC6V3CTeeplHbiA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99 h1:ZSlhAUqC4r8TPzqLXQ0m3upBNZeF+Y8jQ3c4CR3Ujms= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= @@ -387,21 +416,33 @@ k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= +k8s.io/component-base v0.32.2 h1:1aUL5Vdmu7qNo4ZsE+569PV5zFatM9hl+lb3dEea2zU= +k8s.io/component-base v0.32.2/go.mod h1:PXJ61Vx9Lg+P5mS8TLd7bCIr+eMJRQTyXe8KvkrvJq0= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg= +k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= k8s.io/mount-utils v0.32.2 h1:aDwp+ucWiVnDr/LpRg88/dsXf/vm6gI1VZkYH3+3+Vw= k8s.io/mount-utils v0.32.2/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= +k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.20.2 h1:/439OZVxoEc02psi1h4QO3bHzTgu49bb347Xp4gW1pc= sigs.k8s.io/controller-runtime v0.20.2/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= +sigs.k8s.io/e2e-framework v0.6.0 h1:p7hFzHnLKO7eNsWGI2AbC1Mo2IYxidg49BiT4njxkrM= +sigs.k8s.io/e2e-framework v0.6.0/go.mod h1:IREnCHnKgRCioLRmNi0hxSJ1kJ+aAdjEKK/gokcZu4k= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk= +sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/pkg/api/v1beta3/dynakube/dynakube_props.go b/pkg/api/v1beta3/dynakube/dynakube_props.go index 66b73ad319..62597fe173 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_props.go +++ b/pkg/api/v1beta3/dynakube/dynakube_props.go @@ -104,3 +104,7 @@ func (dk *DynaKube) ApiRequestThreshold() time.Duration { func (dk *DynaKube) IsTokenScopeVerificationAllowed(timeProvider *timeprovider.Provider) bool { return timeProvider.IsOutdated(&dk.Status.DynatraceApi.LastTokenScopeRequest, dk.ApiRequestThreshold()) } + +func (dk *DynaKube) FeatureBootstrapperInjection() bool { + return dk.FeatureRemoteImageDownload() && !dk.OneAgent().IsCSIAvailable() +} diff --git a/pkg/api/v1beta3/dynakube/feature_flags.go b/pkg/api/v1beta3/dynakube/feature_flags.go index fd45eaf1f1..674b9fae8d 100644 --- a/pkg/api/v1beta3/dynakube/feature_flags.go +++ b/pkg/api/v1beta3/dynakube/feature_flags.go @@ -75,7 +75,7 @@ const ( AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureDownloadViaJob = AnnotationFeatureCodeModulesPrefix + "remote-image-download" + AnnotationFeatureRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remote-image-download" falsePhrase = "false" truePhrase = "true" @@ -277,8 +277,8 @@ func (dk *DynaKube) FeatureReadOnlyCsiVolume() bool { return dk.getFeatureFlagRaw(AnnotationFeatureReadOnlyCsiVolume) == truePhrase } -func (dk *DynaKube) FeatureDownloadViaJob() bool { - return dk.getFeatureFlagRaw(AnnotationFeatureDownloadViaJob) == truePhrase +func (dk *DynaKube) FeatureRemoteImageDownload() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureRemoteImageDownload) == truePhrase } func (dk *DynaKube) FeatureInjectionFailurePolicy() string { diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index 7aef8184aa..b252d68312 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -17,7 +17,7 @@ import ( const ( errorConflictingOneagentMode = `The DynaKube specification attempts to use multiple OneAgent modes simultaneously, which is not supported.` - errorImageFieldSetWithoutCSIFlag = `The DynaKube specification attempts to enable ApplicationMonitoring mode and retrieve the respective image, but the CSI driver is not enabled.` + errorImageFieldSetWithoutCSIFlag = `The DynaKube specification attempts to enable ApplicationMonitoring mode and retrieve the respective image, but the CSI driver and/or remote image download is not enabled.` errorNodeSelectorConflict = `The Dynakube specification conflicts with another Dynakube's OneAgent or Standalone-LogMonitoring. Only one Agent per node is supported. Use a nodeSelector to avoid this conflict. Conflicting DynaKubes: %s` @@ -145,7 +145,7 @@ func publicImageSetWithoutReadOnlyMode(_ context.Context, v *Validator, dk *dyna func imageFieldSetWithoutCSIFlag(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { if dk.OneAgent().IsApplicationMonitoringMode() { - if len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) > 0 && !v.modules.CSIDriver { + if len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) > 0 && !v.modules.CSIDriver && !dk.FeatureRemoteImageDownload() { return errorImageFieldSetWithoutCSIFlag } } diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index 37e0a3251b..33f01ecb61 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -288,7 +288,7 @@ func TestImageFieldSetWithoutCSIFlag(t *testing.T) { }) }) - t.Run("spec with appMon enabled, useCSIDriver not enabled but image set", func(t *testing.T) { + t.Run("spec with appMon enabled, csi driver not enabled but image set", func(t *testing.T) { setupDisabledCSIEnv(t) testImage := "testImage" @@ -306,6 +306,56 @@ func TestImageFieldSetWithoutCSIFlag(t *testing.T) { }, }) }) + + t.Run("spec with appMon enabled, csi driver not enabled but remote image download enabled and image set", func(t *testing.T) { + setupDisabledCSIEnv(t) + + testImage := "testImage" + assertAllowed(t, &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Annotations: map[string]string{ + dynakube.AnnotationFeatureRemoteImageDownload: "true", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ + CodeModulesImage: testImage, + }, + }, + }, + }, + }) + }) + + t.Run("spec with appMon enabled, csi driver and remote image download not enabled and image set", func(t *testing.T) { + setupDisabledCSIEnv(t) + + testImage := "testImage" + assertDenied(t, []string{errorImageFieldSetWithoutCSIFlag}, &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Annotations: map[string]string{ + dynakube.AnnotationFeatureRemoteImageDownload: "false", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ + CodeModulesImage: testImage, + }, + }, + }, + }, + }) + }) } func createDynakube(oaEnvVar ...string) *dynakube.DynaKube { diff --git a/pkg/consts/agent_injection.go b/pkg/consts/agent_injection.go index 19bdc00311..397fdad2df 100644 --- a/pkg/consts/agent_injection.go +++ b/pkg/consts/agent_injection.go @@ -8,6 +8,8 @@ const ( AgentInitSecretName = "dynatrace-dynakube-config" AgentInitSecretConfigField = "config" + BootstrapperInitSecretName = "dynatrace-bootstrapper-config" + LdPreloadFilename = "ld.so.preload" LibAgentProcPath = "/agent/lib64/liboneagentproc.so" diff --git a/pkg/controllers/csi/provisioner/controller_test.go b/pkg/controllers/csi/provisioner/controller_test.go index cdb78874db..e2e71b71f3 100644 --- a/pkg/controllers/csi/provisioner/controller_test.go +++ b/pkg/controllers/csi/provisioner/controller_test.go @@ -254,7 +254,7 @@ func createDynaKubeWithJobFF(t *testing.T) *dynakube.DynaKube { } dk.Status.CodeModules.ImageID = imageId dk.Annotations = map[string]string{ - dynakube.AnnotationFeatureDownloadViaJob: "true", + dynakube.AnnotationFeatureRemoteImageDownload: "true", } return dk diff --git a/pkg/controllers/csi/provisioner/install.go b/pkg/controllers/csi/provisioner/install.go index 816cfd91f0..e20e8d4ba1 100644 --- a/pkg/controllers/csi/provisioner/install.go +++ b/pkg/controllers/csi/provisioner/install.go @@ -51,7 +51,7 @@ func (provisioner *OneAgentProvisioner) installAgent(ctx context.Context, dk dyn func (provisioner *OneAgentProvisioner) getInstaller(ctx context.Context, dk dynakube.DynaKube) (installer.Installer, error) { switch { - case dk.FeatureDownloadViaJob(): + case dk.FeatureRemoteImageDownload(): return provisioner.getJobInstaller(ctx, dk), nil case dk.OneAgent().GetCustomCodeModulesImage() != "": props := &image.Properties{ diff --git a/pkg/controllers/dynakube/injection/reconciler.go b/pkg/controllers/dynakube/injection/reconciler.go index bd6069d402..1b5b2ba022 100644 --- a/pkg/controllers/dynakube/injection/reconciler.go +++ b/pkg/controllers/dynakube/injection/reconciler.go @@ -14,6 +14,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/monitoredentities" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/version" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/bootstrapperconfig" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/ingestendpoint" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/initgeneration" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" @@ -33,6 +34,7 @@ type reconciler struct { connectionInfoReconciler controllers.Reconciler monitoredEntitiesReconciler controllers.Reconciler enrichmentRulesReconciler controllers.Reconciler + dynatraceClient dynatrace.Client } type ReconcilerBuilder func( @@ -61,6 +63,7 @@ func NewReconciler( client: client, apiReader: apiReader, dk: dk, + dynatraceClient: dynatraceClient, istioReconciler: istioReconciler, versionReconciler: version.NewReconciler(apiReader, dynatraceClient, timeprovider.New().Freeze()), pmcSecretreconciler: processmoduleconfigsecret.NewReconciler( @@ -132,9 +135,11 @@ func (r *reconciler) setupOneAgentInjection(ctx context.Context) error { return err } - err = r.pmcSecretreconciler.Reconcile(ctx) - if err != nil { - return err + if !r.dk.FeatureBootstrapperInjection() { + err = r.pmcSecretreconciler.Reconcile(ctx) + if err != nil { + return err + } } if r.istioReconciler != nil { @@ -151,12 +156,8 @@ func (r *reconciler) setupOneAgentInjection(ctx context.Context) error { return nil } - err = initgeneration.NewInitGenerator(r.client, r.apiReader, r.dk.Namespace).GenerateForDynakube(ctx, r.dk) + err = r.generateCorrectInitSecret(ctx) if err != nil { - if conditions.IsKubeApiError(err) { - conditions.SetKubeApiError(r.dk.Conditions(), codeModulesInjectionConditionType, err) - } - return err } @@ -169,6 +170,31 @@ func (r *reconciler) setupOneAgentInjection(ctx context.Context) error { return nil } +func (r *reconciler) generateCorrectInitSecret(ctx context.Context) error { + var err error + if r.dk.FeatureBootstrapperInjection() { + err = bootstrapperconfig.NewSecretGenerator(r.client, r.apiReader, r.dynatraceClient).GenerateForDynakube(ctx, r.dk) + if err != nil { + if conditions.IsKubeApiError(err) { + conditions.SetKubeApiError(r.dk.Conditions(), codeModulesInjectionConditionType, err) + } + + return err + } + } else { + err = initgeneration.NewInitGenerator(r.client, r.apiReader, r.dk.Namespace).GenerateForDynakube(ctx, r.dk) + if err != nil { + if conditions.IsKubeApiError(err) { + conditions.SetKubeApiError(r.dk.Conditions(), codeModulesInjectionConditionType, err) + } + + return err + } + } + + return err +} + func (r *reconciler) cleanupOneAgentInjection(ctx context.Context) { if meta.FindStatusCondition(*r.dk.Conditions(), codeModulesInjectionConditionType) != nil { defer meta.RemoveStatusCondition(r.dk.Conditions(), codeModulesInjectionConditionType) @@ -180,9 +206,16 @@ func (r *reconciler) cleanupOneAgentInjection(ctx context.Context) { return } - err = initgeneration.NewInitGenerator(r.client, r.apiReader, r.dk.Namespace).Cleanup(ctx, namespaces) - if err != nil { - log.Error(err, "failed to clean-up code module injection init-secrets") + if r.dk.FeatureBootstrapperInjection() { + err = bootstrapperconfig.Cleanup(ctx, r.client, r.apiReader, namespaces) + if err != nil { + log.Error(err, "failed to clean-up bootstrapper code module injection init-secrets") + } + } else { + err = initgeneration.NewInitGenerator(r.client, r.apiReader, r.dk.Namespace).Cleanup(ctx, namespaces) + if err != nil { + log.Error(err, "failed to clean-up code module injection init-secrets") + } } } } diff --git a/pkg/controllers/dynakube/injection/reconciler_test.go b/pkg/controllers/dynakube/injection/reconciler_test.go index f3b17de950..5a826c4a4e 100644 --- a/pkg/controllers/dynakube/injection/reconciler_test.go +++ b/pkg/controllers/dynakube/injection/reconciler_test.go @@ -16,6 +16,7 @@ import ( versions "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/version" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" controllermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/controllers" @@ -380,6 +381,33 @@ func TestSetupOneAgentInjection(t *testing.T) { assertSecretNotFound(t, clt, consts.AgentInitSecretName, testNamespace2) }) + + t.Run(`no injection - ClassicFullStack`, func(t *testing.T) { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + + clt := clientBootstrapperConfigInjection() + rec := createReconciler(clt, testDynakube, testNamespaceDynatrace, oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, + }) + + dtClient := dtclientmock.NewClient(t) + dtClient.On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("uint")).Return(&dtclient.ProcessModuleConfig{}, nil) + + rec.dynatraceClient = dtClient + + rec.dk.Annotations = make(map[string]string) + rec.dk.Annotations[dynakube.AnnotationFeatureRemoteImageDownload] = "true" + rec.versionReconciler = createVersionReconcilerMock(t) + rec.connectionInfoReconciler = createGenericReconcilerMock(t) + rec.pmcSecretreconciler = createGenericReconcilerMock(t) + rec.monitoredEntitiesReconciler = createGenericReconcilerMock(t) + + err := rec.setupOneAgentInjection(context.Background()) + require.NoError(t, err) + + assertSecretNotFound(t, clt, consts.AgentInitSecretName, testNamespace) + assertSecretFound(t, clt, consts.BootstrapperInitSecretName, testNamespace) + }) } func TestSetupEnrichmentInjection(t *testing.T) { @@ -468,6 +496,19 @@ func clientOneAgentInjection() client.Client { ) } +func clientBootstrapperConfigInjection() client.Client { + return fake.NewClientWithIndex( + clientInjectedNamespace(testNamespace, testDynakube), + clientSecret(testDynakube, testNamespaceDynatrace, map[string][]byte{ + dtclient.ApiToken: []byte(testAPIToken), + dtclient.PaasToken: []byte(testPaasToken), + }), + clientSecret("test-dynakube-oneagent-tenant-secret", testNamespaceDynatrace, map[string][]byte{ + "tenant-token": []byte(testTenantToken), + }), + ) +} + func clientEnrichmentInjection() client.Client { return fake.NewClientWithIndex( clientInjectedNamespace(testNamespace, testDynakube), diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/conditions.go b/pkg/controllers/dynakube/processmoduleconfigsecret/conditions.go index 8e7e9dba4e..7ee97769ca 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/conditions.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/conditions.go @@ -1,5 +1,5 @@ package processmoduleconfigsecret const ( - pmcConditionType = "ProcessModuleConfig" + PMCConditionType = "ProcessModuleConfig" ) diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go index fe0a89022a..3e02795b4e 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go @@ -50,11 +50,11 @@ func NewReconciler(clt client.Client, func (r *Reconciler) Reconcile(ctx context.Context) error { if !(r.dk.OneAgent().IsCloudNativeFullstackMode() || r.dk.OneAgent().IsApplicationMonitoringMode()) { - if meta.FindStatusCondition(*r.dk.Conditions(), pmcConditionType) == nil { + if meta.FindStatusCondition(*r.dk.Conditions(), PMCConditionType) == nil { return nil } - defer meta.RemoveStatusCondition(r.dk.Conditions(), pmcConditionType) + defer meta.RemoveStatusCondition(r.dk.Conditions(), PMCConditionType) err := r.deleteSecret(ctx, &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -79,12 +79,12 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { } func (r *Reconciler) reconcileSecret(ctx context.Context) error { - if !conditions.IsOutdated(r.timeProvider, r.dk, pmcConditionType) { + if !conditions.IsOutdated(r.timeProvider, r.dk, PMCConditionType) { return nil } log.Info("processModuleConfig is outdated, updating") - conditions.SetSecretOutdated(r.dk.Conditions(), pmcConditionType, "secret is outdated, update in progress") + conditions.SetSecretOutdated(r.dk.Conditions(), PMCConditionType, "secret is outdated, update in progress") secret, err := r.prepareSecret(ctx) if err != nil { @@ -97,19 +97,19 @@ func (r *Reconciler) reconcileSecret(ctx context.Context) error { func (r *Reconciler) createOrUpdateSecret(ctx context.Context, secret *corev1.Secret) error { _, err := k8ssecret.Query(r.client, r.apiReader, log).WithOwner(r.dk).CreateOrUpdate(ctx, secret) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), pmcConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) return errors.Errorf("failed to create or update secret '%s': %v", secret.Name, err) } - conditions.SetSecretCreatedOrUpdated(r.dk.Conditions(), pmcConditionType, secret.Name) + conditions.SetSecretCreatedOrUpdated(r.dk.Conditions(), PMCConditionType, secret.Name) return nil } func (r *Reconciler) deleteSecret(ctx context.Context, secret *corev1.Secret) error { if err := k8ssecret.Query(r.client, r.apiReader, log).Delete(ctx, secret); err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), pmcConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) return err } @@ -120,7 +120,7 @@ func (r *Reconciler) deleteSecret(ctx context.Context, secret *corev1.Secret) er func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) { pmc, err := r.dtClient.GetProcessModuleConfig(ctx, 0) if err != nil { - conditions.SetDynatraceApiError(r.dk.Conditions(), pmcConditionType, err) + conditions.SetDynatraceApiError(r.dk.Conditions(), PMCConditionType, err) return nil, err } @@ -130,7 +130,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) Namespace: r.dk.Namespace, }, connectioninfo.TenantTokenKey, log) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), pmcConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) return nil, err } @@ -144,7 +144,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) if r.dk.NeedsOneAgentProxy() { proxy, err := r.dk.Proxy(ctx, r.apiReader) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), pmcConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) return nil, err } @@ -175,7 +175,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) k8ssecret.SetType(corev1.SecretTypeOpaque) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), pmcConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) return nil, err } diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go index 06c07a739b..5f36b63019 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go @@ -49,7 +49,7 @@ func TestReconcile(t *testing.T) { checkSecretForValue(t, mockK8sClient, "\"revision\":0") - condition := meta.FindStatusCondition(*dk.Conditions(), pmcConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) oldTransitionTime := condition.LastTransitionTime require.NotNil(t, condition) require.NotEmpty(t, oldTransitionTime) @@ -63,7 +63,7 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) checkSecretForValue(t, mockK8sClient, "\"revision\":0") - condition = meta.FindStatusCondition(*dk.Conditions(), pmcConditionType) + condition = meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) require.NotNil(t, condition) require.Equal(t, condition.LastTransitionTime, oldTransitionTime) @@ -74,7 +74,7 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) checkSecretForValue(t, mockK8sClient, "\"revision\":1") - condition = meta.FindStatusCondition(*dk.Conditions(), pmcConditionType) + condition = meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) require.NotNil(t, condition) require.Greater(t, condition.LastTransitionTime.Time, oldTransitionTime.Time) assert.Equal(t, conditions.SecretCreatedOrUpdatedReason, condition.Reason) @@ -83,7 +83,7 @@ func TestReconcile(t *testing.T) { t.Run("Only runs when required, and cleans up condition and pmc secret", func(t *testing.T) { dk := createDynakube(oneagent.Spec{ ClassicFullStack: &oneagent.HostInjectSpec{}}) - conditions.SetSecretCreated(dk.Conditions(), pmcConditionType, "this is a test") + conditions.SetSecretCreated(dk.Conditions(), PMCConditionType, "this is a test") secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -134,7 +134,7 @@ func TestReconcile(t *testing.T) { require.Error(t, err) require.Len(t, *dk.Conditions(), 1) - condition := meta.FindStatusCondition(*dk.Conditions(), pmcConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) assert.Equal(t, conditions.KubeApiErrorReason, condition.Reason) assert.Equal(t, metav1.ConditionFalse, condition.Status) }) @@ -155,7 +155,7 @@ func TestReconcile(t *testing.T) { require.Error(t, err) require.Len(t, *dk.Conditions(), 1) - condition := meta.FindStatusCondition(*dk.Conditions(), pmcConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) assert.Equal(t, conditions.DynatraceApiErrorReason, condition.Reason) assert.Equal(t, metav1.ConditionFalse, condition.Status) }) diff --git a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go new file mode 100644 index 0000000000..4e6a49edb8 --- /dev/null +++ b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go @@ -0,0 +1,112 @@ +package bootstrapperconfig + +import ( + "context" + "strconv" + + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/enrichment/endpoint" + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/ca" + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/curl" + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/pmc" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" + k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// SecretGenerator manages the bootstrapper init secret generation for the user namespaces. +type SecretGenerator struct { + client client.Client + dtClient dtclient.Client + apiReader client.Reader +} + +func NewSecretGenerator(client client.Client, apiReader client.Reader, dtClient dtclient.Client) *SecretGenerator { + return &SecretGenerator{ + client: client, + dtClient: dtClient, + apiReader: apiReader, + } +} + +// GenerateForDynakube creates/updates the init secret for EVERY namespace for the given dynakube. +// Used by the dynakube controller during reconcile. +func (s *SecretGenerator) GenerateForDynakube(ctx context.Context, dk *dynakube.DynaKube) error { + log.Info("reconciling namespace bootstrapper init secret for", "dynakube", dk.Name) + + data, err := s.generate(ctx, dk) + if err != nil { + return errors.WithStack(err) + } + + nsList, err := mapper.GetNamespacesForDynakube(ctx, s.apiReader, dk.Name) + if err != nil { + return errors.WithStack(err) + } + + coreLabels := k8slabels.NewCoreLabels(dk.Name, k8slabels.WebhookComponentLabel) + + secret, err := k8ssecret.BuildForNamespace(consts.BootstrapperInitSecretName, "", data, k8ssecret.SetLabels(coreLabels.BuildLabels())) + if err != nil { + return err + } + + err = k8ssecret.Query(s.client, s.apiReader, log).CreateOrUpdateForNamespaces(ctx, secret, nsList) + if err != nil { + return err + } + + log.Info("done updating init secrets") + + return nil +} + +func Cleanup(ctx context.Context, client client.Client, apiReader client.Reader, namespaces []corev1.Namespace) error { + nsList := make([]string, 0, len(namespaces)) + for _, ns := range namespaces { + nsList = append(nsList, ns.Name) + } + + return k8ssecret.Query(client, apiReader, log).DeleteForNamespaces(ctx, consts.BootstrapperInitSecretName, nsList) +} + +// generate gets the necessary info the create the init secret data +func (s *SecretGenerator) generate(ctx context.Context, dk *dynakube.DynaKube) (map[string][]byte, error) { + agCerts, err := dk.ActiveGateTLSCert(ctx, s.apiReader) + if err != nil { + return nil, errors.WithStack(err) + } + + trustedCAs, err := dk.TrustedCAs(ctx, s.apiReader) + if err != nil { + return nil, errors.WithStack(err) + } + + pmcSecret, err := s.preparePMC(ctx, *dk) + if err != nil { + return nil, errors.WithStack(err) + } + + endpointProperties, err := s.prepareEndpoints(ctx, dk) + if err != nil { + return nil, errors.WithStack(err) + } + + initialConnectRetryMs := "" + if dk.FeatureAgentInitialConnectRetry() > -1 { + initialConnectRetryMs = strconv.Itoa(dk.FeatureAgentInitialConnectRetry()) + } + + return map[string][]byte{ + pmc.InputFileName: pmcSecret, + ca.TrustedCertsInputFile: trustedCAs, + ca.AgCertsInputFile: agCerts, + curl.InputFileName: []byte(initialConnectRetryMs), + endpoint.InputFileName: []byte(endpointProperties), + }, nil +} diff --git a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go new file mode 100644 index 0000000000..26d20f2a8d --- /dev/null +++ b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go @@ -0,0 +1,373 @@ +package bootstrapperconfig + +import ( + "context" + "testing" + + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/enrichment/endpoint" + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/ca" + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/curl" + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/pmc" + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + testPaasToken = "test-paas-token" + testAPIToken = "test-api-token" + testDataIngestToken = "test-ingest-token" + + testUUID = "test-uuid" + testTenantToken = "abcd" + testCommunicationEndpoint = "https://tenant.dev.dynatracelabs.com:443" + + testHost = "test-host" + + testDynakube = "test-dynakube" + testNamespace = "test-namespace" + testNamespace2 = "test-namespace2" + + testNamespaceDynatrace = "dynatrace" + + testApiUrl = "https://" + testHost + "/e/" + testUUID + "/api" + + oldCertValue = "old-cert-value" + oldTrustedCa = "old-trusted-ca" +) + +func TestNewSecretGenerator(t *testing.T) { + client := fake.NewClient() + mockDTClient := dtclientmock.NewClient(t) + + secretGenerator := NewSecretGenerator(client, client, mockDTClient) + assert.NotNil(t, secretGenerator) + + assert.Equal(t, client, secretGenerator.client) + assert.Equal(t, client, secretGenerator.apiReader) + assert.Equal(t, mockDTClient, secretGenerator.dtClient) +} + +func TestGenerateForDynakube(t *testing.T) { + t.Run("succcessfully generate secret for dynakube", func(t *testing.T) { + dynakube := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakube, + Namespace: testNamespaceDynatrace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + }, + } + + clt := fake.NewClientWithIndex( + dynakube, + clientInjectedNamespace(testNamespace, testDynakube), + clientSecret(testDynakube, testNamespaceDynatrace, map[string][]byte{ + dtclient.ApiToken: []byte(testAPIToken), + dtclient.PaasToken: []byte(testPaasToken), + }), + clientSecret(dynakube.OneAgent().GetTenantSecret(), testNamespaceDynatrace, map[string][]byte{ + "tenant-token": []byte(testTenantToken), + }), + ) + + mockDTClient := dtclientmock.NewClient(t) + + mockDTClient.On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("uint")).Return(&dtclient.ProcessModuleConfig{}, nil) + + secretGenerator := NewSecretGenerator(clt, clt, mockDTClient) + err := secretGenerator.GenerateForDynakube(context.Background(), dynakube) + require.NoError(t, err) + + var secret corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &secret) + require.NoError(t, err) + + require.NotEmpty(t, secret) + assert.Equal(t, consts.BootstrapperInitSecretName, secret.Name) + }) + t.Run("succcessfully generate secret with fields for dynakube", func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakube, + Namespace: testNamespaceDynatrace, + Annotations: map[string]string{ + dynakube.AnnotationFeatureOneAgentInitialConnectRetry: "6500", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TrustedCAs: "test-trusted-ca", + MetadataEnrichment: dynakube.MetadataEnrichment{ + Enabled: ptr.To(true), + }, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + TlsSecretName: "test-tls-secret-name", + }, + }, + } + + clt := fake.NewClientWithIndex( + dk, + clientInjectedNamespace(testNamespace, testDynakube), + clientSecret(testDynakube, testNamespaceDynatrace, map[string][]byte{ + dtclient.ApiToken: []byte(testAPIToken), + dtclient.PaasToken: []byte(testPaasToken), + }), + clientSecret(dk.ActiveGate().TlsSecretName, testNamespaceDynatrace, map[string][]byte{ + dynakube.TLSCertKey: []byte("test-cert-value"), + }), + clientSecret(dk.OneAgent().GetTenantSecret(), testNamespaceDynatrace, map[string][]byte{ + "tenant-token": []byte(testTenantToken), + }), + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-trusted-ca", + Namespace: testNamespaceDynatrace, + }, + Data: map[string]string{ + dynakube.TrustedCAKey: "test-trusted-ca-value", + }, + }, + ) + + mockDTClient := dtclientmock.NewClient(t) + + mockDTClient.On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("uint")).Return(&dtclient.ProcessModuleConfig{}, nil) + + secretGenerator := NewSecretGenerator(clt, clt, mockDTClient) + err := secretGenerator.GenerateForDynakube(context.Background(), dk) + require.NoError(t, err) + + var secret corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &secret) + require.NoError(t, err) + + require.NotEmpty(t, secret) + + assert.Equal(t, consts.BootstrapperInitSecretName, secret.Name) + _, ok := secret.Data[pmc.InputFileName] + require.True(t, ok) + + _, ok = secret.Data[ca.TrustedCertsInputFile] + require.True(t, ok) + + _, ok = secret.Data[ca.AgCertsInputFile] + require.True(t, ok) + + _, ok = secret.Data[curl.InputFileName] + require.True(t, ok) + + _, ok = secret.Data[endpoint.InputFileName] + require.True(t, ok) + }) + t.Run("update secret with preexisting secret + fields", func(t *testing.T) { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakube, + Namespace: testNamespaceDynatrace, + Annotations: map[string]string{ + dynakube.AnnotationFeatureOneAgentInitialConnectRetry: "6500", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + MetadataEnrichment: dynakube.MetadataEnrichment{ + Enabled: ptr.To(true), + }, + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{ + activegate.KubeMonCapability.DisplayName, + }, + }, + }, + } + + clt := fake.NewClientWithIndex( + dk, + clientInjectedNamespace(testNamespace, testDynakube), + clientSecret(testDynakube, testNamespaceDynatrace, map[string][]byte{ + dtclient.ApiToken: []byte(testAPIToken), + dtclient.PaasToken: []byte(testPaasToken), + }), + clientSecret(dk.ActiveGate().TlsSecretName, testNamespaceDynatrace, map[string][]byte{ + dynakube.TLSCertKey: []byte("test-cert-value"), + }), + clientSecret(dk.OneAgent().GetTenantSecret(), testNamespaceDynatrace, map[string][]byte{ + "tenant-token": []byte(testTenantToken), + }), + clientSecret(consts.BootstrapperInitSecretName, testNamespace, map[string][]byte{ + pmc.InputFileName: nil, + ca.TrustedCertsInputFile: []byte(oldTrustedCa), + ca.AgCertsInputFile: []byte(oldCertValue), + }), + ) + + mockDTClient := dtclientmock.NewClient(t) + + mockDTClient.On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("uint")).Return(&dtclient.ProcessModuleConfig{}, nil) + + secretGenerator := NewSecretGenerator(clt, clt, mockDTClient) + err := secretGenerator.GenerateForDynakube(context.Background(), dk) + require.NoError(t, err) + + var secret corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &secret) + require.NoError(t, err) + + require.NotEmpty(t, secret) + + assert.Equal(t, consts.BootstrapperInitSecretName, secret.Name) + _, ok := secret.Data[pmc.InputFileName] + require.True(t, ok) + + val, ok := secret.Data[ca.TrustedCertsInputFile] + require.True(t, ok) + assert.NotEqual(t, oldTrustedCa, val) + require.Empty(t, val) + + _, ok = secret.Data[ca.AgCertsInputFile] + require.True(t, ok) + assert.NotEqual(t, oldCertValue, val) + require.Empty(t, val) + + _, ok = secret.Data[curl.InputFileName] + require.True(t, ok) + + _, ok = secret.Data[endpoint.InputFileName] + require.True(t, ok) + }) + t.Run("fail while generating secret for dynakube", func(t *testing.T) { + dynakube := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakube, + Namespace: testNamespaceDynatrace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + }, + } + + clt := fake.NewClientWithIndex( + dynakube, + clientInjectedNamespace(testNamespace, testDynakube), + clientSecret(testDynakube, testNamespaceDynatrace, map[string][]byte{ + dtclient.ApiToken: []byte(testAPIToken), + dtclient.PaasToken: []byte(testPaasToken), + }), + ) + + mockDTClient := dtclientmock.NewClient(t) + + mockDTClient.On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("uint")).Return(&dtclient.ProcessModuleConfig{}, nil) + + secretGenerator := NewSecretGenerator(clt, clt, mockDTClient) + err := secretGenerator.GenerateForDynakube(context.Background(), dynakube) + require.Error(t, err) + }) +} + +func TestCleanup(t *testing.T) { + dynakube := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakube, + Namespace: testNamespaceDynatrace, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + }, + } + + clt := fake.NewClientWithIndex( + dynakube, + clientInjectedNamespace(testNamespace, testDynakube), + clientSecret(testDynakube, testNamespaceDynatrace, map[string][]byte{ + dtclient.ApiToken: []byte(testAPIToken), + dtclient.PaasToken: []byte(testPaasToken), + }), + clientSecret(dynakube.OneAgent().GetTenantSecret(), testNamespaceDynatrace, map[string][]byte{ + "tenant-token": []byte(testTenantToken), + }), + clientSecret(consts.BootstrapperInitSecretName, testNamespace, nil), + clientSecret(consts.BootstrapperInitSecretName, testNamespace2, nil), + ) + namespaces := []corev1.Namespace{ + {ObjectMeta: metav1.ObjectMeta{Name: testNamespace}}, + {ObjectMeta: metav1.ObjectMeta{Name: testNamespace2}}, + } + + var secretNS1 corev1.Secret + err := clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &secretNS1) + require.NoError(t, err) + + require.NotEmpty(t, secretNS1) + assert.Equal(t, consts.BootstrapperInitSecretName, secretNS1.Name) + + var secretNS2 corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &secretNS2) + require.NoError(t, err) + + require.NotEmpty(t, secretNS2) + assert.Equal(t, consts.BootstrapperInitSecretName, secretNS2.Name) + + err = Cleanup(context.Background(), clt, clt, namespaces) + require.NoError(t, err) + + var deletedSecretNS1 corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &deletedSecretNS1) + require.Error(t, err) + + require.Empty(t, deletedSecretNS1) + assert.NotEqual(t, consts.BootstrapperInitSecretName, deletedSecretNS1.Name) + + var deletedSecretNS2 corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &deletedSecretNS2) + require.Error(t, err) + + require.Empty(t, deletedSecretNS2) + assert.NotEqual(t, consts.BootstrapperInitSecretName, deletedSecretNS2.Name) +} + +func clientSecret(secretName string, namespaceName string, data map[string][]byte) *corev1.Secret { + return &corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "core/v1", + Kind: "Secret", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: namespaceName, + }, + Data: data, + } +} + +func clientInjectedNamespace(namespaceName string, dynakubeName string) *corev1.Namespace { + return &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "corev1", + Kind: "Namespace", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: namespaceName, + Labels: map[string]string{ + dtwebhook.InjectionInstanceLabel: dynakubeName, + }, + }, + } +} diff --git a/pkg/injection/namespace/bootstrapperconfig/config.go b/pkg/injection/namespace/bootstrapperconfig/config.go new file mode 100644 index 0000000000..71d11fed35 --- /dev/null +++ b/pkg/injection/namespace/bootstrapperconfig/config.go @@ -0,0 +1,7 @@ +package bootstrapperconfig + +import "github.com/Dynatrace/dynatrace-operator/pkg/logd" + +var ( + log = logd.Get().WithName("bootstrapper-config") +) diff --git a/pkg/injection/namespace/bootstrapperconfig/endpoints.go b/pkg/injection/namespace/bootstrapperconfig/endpoints.go new file mode 100644 index 0000000000..d9668dd7c4 --- /dev/null +++ b/pkg/injection/namespace/bootstrapperconfig/endpoints.go @@ -0,0 +1,60 @@ +package bootstrapperconfig + +import ( + "context" + "fmt" + "strings" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" + dtingestendpoint "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/ingestendpoint" + k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + "github.com/pkg/errors" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (s *SecretGenerator) prepareEndpoints(ctx context.Context, dk *dynakube.DynaKube) (string, error) { + fields, err := s.prepareFieldsForEndpoints(ctx, dk) + if err != nil { + return "", errors.WithStack(err) + } + + endpointPropertiesBuilder := strings.Builder{} + + if dk.MetadataEnrichmentEnabled() { + if _, err := endpointPropertiesBuilder.WriteString(fmt.Sprintf("%s=%s\n", dtingestendpoint.MetricsUrlSecretField, fields[dtingestendpoint.MetricsUrlSecretField])); err != nil { + return "", errors.WithStack(err) + } + + if _, err := endpointPropertiesBuilder.WriteString(fmt.Sprintf("%s=%s\n", dtingestendpoint.MetricsTokenSecretField, fields[dtingestendpoint.MetricsTokenSecretField])); err != nil { + return "", errors.WithStack(err) + } + } + + return endpointPropertiesBuilder.String(), nil +} + +func (s *SecretGenerator) prepareFieldsForEndpoints(ctx context.Context, dk *dynakube.DynaKube) (map[string]string, error) { + fields := make(map[string]string) + + tokens, err := k8ssecret.Query(s.client, s.apiReader, log).Get(ctx, client.ObjectKey{Name: dk.Tokens(), Namespace: dk.Namespace}) + if err != nil { + return nil, errors.WithMessage(err, "failed to query tokens") + } + + if dk.MetadataEnrichmentEnabled() { + if token, ok := tokens.Data[dtclient.DataIngestToken]; ok { + fields[dtingestendpoint.MetricsTokenSecretField] = string(token) + } else { + log.Info("data ingest token not found in secret", "dk", dk.Name) + } + + if ingestUrl, err := dtingestendpoint.IngestUrlFor(dk); err != nil { + return nil, err + } else { + fields[dtingestendpoint.MetricsUrlSecretField] = ingestUrl + } + } + + return fields, nil +} diff --git a/pkg/injection/namespace/bootstrapperconfig/pmc.go b/pkg/injection/namespace/bootstrapperconfig/pmc.go new file mode 100644 index 0000000000..6460a6daaf --- /dev/null +++ b/pkg/injection/namespace/bootstrapperconfig/pmc.go @@ -0,0 +1,68 @@ +package bootstrapperconfig + +import ( + "context" + "encoding/json" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + "k8s.io/apimachinery/pkg/types" +) + +func (s *SecretGenerator) preparePMC(ctx context.Context, dk dynakube.DynaKube) ([]byte, error) { + pmc, err := s.dtClient.GetProcessModuleConfig(ctx, 0) + if err != nil { + conditions.SetDynatraceApiError(dk.Conditions(), processmoduleconfigsecret.PMCConditionType, err) + + return nil, err + } + + tenantToken, err := k8ssecret.GetDataFromSecretName(ctx, s.apiReader, types.NamespacedName{ + Name: dk.OneAgent().GetTenantSecret(), + Namespace: dk.Namespace, + }, connectioninfo.TenantTokenKey, log) + if err != nil { + conditions.SetKubeApiError(dk.Conditions(), processmoduleconfigsecret.PMCConditionType, err) + + return nil, err + } + + pmc = pmc. + AddHostGroup(dk.OneAgent().GetHostGroup()). + AddConnectionInfo(dk.Status.OneAgent.ConnectionInfoStatus, tenantToken). + // set proxy explicitly empty, so old proxy settings get deleted where necessary + AddProxy("") + + if dk.NeedsOneAgentProxy() { + proxy, err := dk.Proxy(ctx, s.apiReader) + if err != nil { + conditions.SetKubeApiError(dk.Conditions(), processmoduleconfigsecret.PMCConditionType, err) + + return nil, err + } + + pmc.AddProxy(proxy) + + multiCap := capability.NewMultiCapability(&dk) + dnsEntry := capability.BuildDNSEntryPointWithoutEnvVars(dk.Name, dk.Namespace, multiCap) + + if dk.FeatureNoProxy() != "" { + dnsEntry += "," + dk.FeatureNoProxy() + } + + pmc.AddNoProxy(dnsEntry) + } + + marshaled, err := json.Marshal(pmc) + if err != nil { + log.Info("could not marshal process module config") + + return nil, err + } + + return marshaled, err +} diff --git a/pkg/injection/namespace/ingestendpoint/secret.go b/pkg/injection/namespace/ingestendpoint/secret.go index 0ef55e4704..179c535462 100644 --- a/pkg/injection/namespace/ingestendpoint/secret.go +++ b/pkg/injection/namespace/ingestendpoint/secret.go @@ -163,7 +163,7 @@ func (g *SecretGenerator) PrepareFields(ctx context.Context, dk *dynakube.DynaKu log.Info("data ingest token not found in secret", "dk", dk.Name) } - if ingestUrl, err := ingestUrlFor(dk); err != nil { + if ingestUrl, err := IngestUrlFor(dk); err != nil { return nil, err } else { fields[MetricsUrlSecretField] = ingestUrl @@ -173,22 +173,22 @@ func (g *SecretGenerator) PrepareFields(ctx context.Context, dk *dynakube.DynaKu return fields, nil } -func ingestUrlFor(dk *dynakube.DynaKube) (string, error) { +func IngestUrlFor(dk *dynakube.DynaKube) (string, error) { switch { case dk.ActiveGate().IsMetricsIngestEnabled(): - return metricsIngestUrlForClusterActiveGate(dk) + return MetricsIngestUrlForClusterActiveGate(dk) case len(dk.Spec.APIURL) > 0: - return metricsIngestUrlForDynatraceActiveGate(dk) + return MetricsIngestUrlForDynatraceActiveGate(dk) default: return "", errors.New("failed to create metadata-enrichment endpoint, DynaKube.spec.apiUrl is empty") } } -func metricsIngestUrlForDynatraceActiveGate(dk *dynakube.DynaKube) (string, error) { +func MetricsIngestUrlForDynatraceActiveGate(dk *dynakube.DynaKube) (string, error) { return dk.Spec.APIURL + "/v2/metrics/ingest", nil } -func metricsIngestUrlForClusterActiveGate(dk *dynakube.DynaKube) (string, error) { +func MetricsIngestUrlForClusterActiveGate(dk *dynakube.DynaKube) (string, error) { tenant, err := dk.TenantUUID() if err != nil { return "", err diff --git a/pkg/injection/namespace/mapper/dynakubes.go b/pkg/injection/namespace/mapper/dynakubes.go index 7e2b1cdb1c..a846a9d8ac 100644 --- a/pkg/injection/namespace/mapper/dynakubes.go +++ b/pkg/injection/namespace/mapper/dynakubes.go @@ -60,7 +60,12 @@ func (dm DynakubeMapper) UnmapFromDynaKube(namespaces []corev1.Namespace) error return errors.WithMessagef(err, "failed to remove label %s from namespace %s", dtwebhook.InjectionInstanceLabel, ns.Name) } - err := k8ssecret.Query(dm.client, dm.apiReader, log).DeleteForNamespace(dm.ctx, consts.AgentInitSecretName, ns.Name) + err := k8ssecret.Query(dm.client, dm.apiReader, log).DeleteForNamespace(dm.ctx, consts.BootstrapperInitSecretName, ns.Name) + if err != nil { + return err + } + + err = k8ssecret.Query(dm.client, dm.apiReader, log).DeleteForNamespace(dm.ctx, consts.AgentInitSecretName, ns.Name) if err != nil { return err } diff --git a/pkg/injection/namespace/mapper/dynakubes_test.go b/pkg/injection/namespace/mapper/dynakubes_test.go index 2538d892e2..49fe3a80f1 100644 --- a/pkg/injection/namespace/mapper/dynakubes_test.go +++ b/pkg/injection/namespace/mapper/dynakubes_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -199,4 +200,60 @@ func TestUnmapFromDynaKube(t *testing.T) { err = clt.Get(ctx, types.NamespacedName{Name: consts.EnrichmentEndpointSecretName, Namespace: namespace.Name}, &secret) assert.True(t, k8serrors.IsNotFound(err)) }) + t.Run("Remove "+consts.BootstrapperInitSecretName, func(t *testing.T) { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + + dkRemoteImage := createDynakubeWithRemoteImageDownloadAndNoCSI("dk-test", convertToLabelSelector(labels)) + + labels := map[string]string{ + dtwebhook.InjectionInstanceLabel: dkRemoteImage.Name, + } + + ns := createNamespace("ns-bootstrapper", labels) + ns2 := createNamespace("ns-bootstrapper2", labels) + + clt := fake.NewClient(ns, ns2) + ctx := context.Background() + + namespaces, err := GetNamespacesForDynakube(ctx, clt, dkRemoteImage.Name) + require.NoError(t, err) + + var secretNS1 corev1.Secret + + clt.Create(ctx, &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: consts.BootstrapperInitSecretName, Namespace: ns.Name}}) + + err = clt.Get(ctx, types.NamespacedName{Name: consts.BootstrapperInitSecretName, Namespace: ns.Name}, &secretNS1) + require.NoError(t, err) + + require.NotEmpty(t, secretNS1) + assert.Equal(t, consts.BootstrapperInitSecretName, secretNS1.Name) + + var secretNS2 corev1.Secret + + clt.Create(ctx, &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: consts.BootstrapperInitSecretName, Namespace: ns2.Name}}) + + err = clt.Get(ctx, types.NamespacedName{Name: consts.BootstrapperInitSecretName, Namespace: ns2.Name}, &secretNS2) + require.NoError(t, err) + + require.NotEmpty(t, secretNS2) + assert.Equal(t, consts.BootstrapperInitSecretName, secretNS2.Name) + + dm := NewDynakubeMapper(ctx, clt, clt, "dynatrace", dkRemoteImage) + err = dm.UnmapFromDynaKube(namespaces) + require.NoError(t, err) + + var deletedSecretNS1 corev1.Secret + err = clt.Get(ctx, types.NamespacedName{Name: consts.BootstrapperInitSecretName, Namespace: ns.Name}, &deletedSecretNS1) + + require.Empty(t, deletedSecretNS1) + assert.NotEqual(t, consts.BootstrapperInitSecretName, deletedSecretNS1.Name) + assert.True(t, k8serrors.IsNotFound(err)) + + var deletedSecretNS2 corev1.Secret + err = clt.Get(ctx, types.NamespacedName{Name: consts.BootstrapperInitSecretName, Namespace: ns2.Name}, &deletedSecretNS2) + + require.Empty(t, deletedSecretNS2) + assert.NotEqual(t, consts.BootstrapperInitSecretName, deletedSecretNS2.Name) + assert.True(t, k8serrors.IsNotFound(err)) + }) } diff --git a/pkg/injection/namespace/mapper/mapper_test.go b/pkg/injection/namespace/mapper/mapper_test.go index 85fb5433fd..b170c421e0 100644 --- a/pkg/injection/namespace/mapper/mapper_test.go +++ b/pkg/injection/namespace/mapper/mapper_test.go @@ -53,6 +53,18 @@ func createDynakubeWithMetadataAndAppInjection(name string, selector metav1.Labe return dk } +func createDynakubeWithRemoteImageDownloadAndNoCSI(name string, selector metav1.LabelSelector) *dynakube.DynaKube { + dk := createBaseDynakube(name, true, false) + + dk.Annotations = make(map[string]string) + + dk.Annotations[dynakube.AnnotationFeatureRemoteImageDownload] = "true" + + dk.Spec.OneAgent.ApplicationMonitoring.NamespaceSelector = selector + + return dk +} + func createNamespace(name string, labels map[string]string) *corev1.Namespace { return &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/webhook/mutation/pod/oneagent/config.go b/pkg/webhook/mutation/pod/oneagent/config.go index 2059f25577..579693b53f 100644 --- a/pkg/webhook/mutation/pod/oneagent/config.go +++ b/pkg/webhook/mutation/pod/oneagent/config.go @@ -18,9 +18,10 @@ const ( releaseStageEnv = "DT_RELEASE_STAGE" releaseBuildVersionEnv = "DT_RELEASE_BUILD_VERSION" - EmptyConnectionInfoReason = "EmptyConnectionInfo" - UnknownCodeModuleReason = "UnknownCodeModule" - EmptyTenantUUIDReason = "EmptyTenantUUID" + EmptyConnectionInfoReason = "EmptyConnectionInfo" + UnknownCodeModuleReason = "UnknownCodeModule" + NoBootstrapperConfigReason = "NoBootstrapperConfig" + EmptyTenantUUIDReason = "EmptyTenantUUID" OneAgentBinVolumeName = "oneagent-bin" oneAgentShareVolumeName = "oneagent-share" diff --git a/pkg/webhook/mutation/pod/oneagent/mutator.go b/pkg/webhook/mutation/pod/oneagent/mutator.go index 5d237f6ad8..215c5e63aa 100644 --- a/pkg/webhook/mutation/pod/oneagent/mutator.go +++ b/pkg/webhook/mutation/pod/oneagent/mutator.go @@ -138,6 +138,17 @@ func (mut *Mutator) isInjectionPossible(request *dtwebhook.MutationRequest) (boo reasons = append(reasons, UnknownCodeModuleReason) } + if dk.FeatureBootstrapperInjection() { + var initSecret corev1.Secret + + secretObjectKey := client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: request.Namespace.Name} + if err := mut.apiReader.Get(request.Context, secretObjectKey, &initSecret); k8serrors.IsNotFound(err) { + log.Info("dynatrace-bootstrapper-config is not available, OneAgent cannot be injected", "pod", request.PodName()) + + reasons = append(reasons, NoBootstrapperConfigReason) + } + } + if len(reasons) > 0 { return false, strings.Join(reasons, ", ") } diff --git a/pkg/webhook/mutation/pod/oneagent/mutator_test.go b/pkg/webhook/mutation/pod/oneagent/mutator_test.go index af577420eb..bb89ca7be8 100644 --- a/pkg/webhook/mutation/pod/oneagent/mutator_test.go +++ b/pkg/webhook/mutation/pod/oneagent/mutator_test.go @@ -12,6 +12,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -293,6 +294,7 @@ func TestIsInjectionPossible(t *testing.T) { t.Run("not possible without communication route", injectionNotPossibleWithoutCommunicationRoute) t.Run("not possible without code modules version", injectionNotPossibleWithoutCodeModulesVersion) t.Run("not possible with multiple issues", injectionNotPossibleWithMultipleIssues) + t.Run("not possible with remote image download enabled and no csi driver", injectionNotPossibleWithRemoteImageDownloadEnabled) } func injectionPossibleWithValidTenantUUID(t *testing.T) { @@ -370,6 +372,19 @@ func injectionNotPossibleWithMultipleIssues(t *testing.T) { require.Contains(t, reason, UnknownCodeModuleReason) } +func injectionNotPossibleWithRemoteImageDownloadEnabled(t *testing.T) { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + + mutator := createTestPodMutator(nil) + dk := getRemoteImageDownloadDynakube() + request := createTestMutationRequest(dk, nil, getTestNamespace(nil)) + + ok, reason := mutator.isInjectionPossible(request) + + require.False(t, ok) + require.Contains(t, reason, NoBootstrapperConfigReason) +} + func createTestPodMutator(objects []client.Object) *Mutator { return &Mutator{ client: fake.NewClient(objects...), @@ -436,6 +451,22 @@ func getTestCSIDynakube() *dynakube.DynaKube { } } +func getRemoteImageDownloadDynakube() *dynakube.DynaKube { + dk := &dynakube.DynaKube{ + ObjectMeta: getTestDynakubeMeta(), + Spec: dynakube.DynaKubeSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, + }, + }, + Status: getTestDynakubeStatus(), + } + + dk.Annotations[dynakube.AnnotationFeatureRemoteImageDownload] = "true" + + return dk +} + func getTestReadOnlyCSIDynakube() *dynakube.DynaKube { dk := getTestCSIDynakube() dk.Annotations[dynakube.AnnotationFeatureReadOnlyCsiVolume] = "true" From 7cd16ea073f9709421995829888f0cc225886d0b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:39:50 +0000 Subject: [PATCH 275/426] fix(deps): update module golang.org/x/net to v0.36.0 (main) (#4548) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 43 ++----------------------------------------- 2 files changed, 3 insertions(+), 42 deletions(-) diff --git a/go.mod b/go.mod index 71c5e368b0..f61788eb10 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.23.0 - golang.org/x/net v0.35.0 + golang.org/x/net v0.36.0 golang.org/x/oauth2 v0.27.0 golang.org/x/sys v0.30.0 google.golang.org/grpc v1.70.0 diff --git a/go.sum b/go.sum index 9861ff8d98..63633719fa 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -28,8 +26,6 @@ github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZ github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= -github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= @@ -50,8 +46,6 @@ github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1 github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= @@ -70,8 +64,6 @@ github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYu github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -83,13 +75,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= -github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -119,8 +106,6 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= -github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -188,12 +173,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= -github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo= -github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vladimirvivien/gexe v0.2.0 h1:nbdAQ6vbZ+ZNsolCgSVb9Fno60kzSuvtzVh6Ytqi/xY= github.com/vladimirvivien/gexe v0.2.0/go.mod h1:LHQL00w/7gDUKIak24n801ABp8C+ni6eBht9vGVst8w= -github.com/vladimirvivien/gexe v0.4.1 h1:W9gWkp8vSPjDoXDu04Yp4KljpVMaSt8IQuHswLDd5LY= -github.com/vladimirvivien/gexe v0.4.1/go.mod h1:3gjgTqE2c0VyHnU5UOIwk7gyNzZDGulPb/DJPgcw64E= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -331,8 +312,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= -golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4= -golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= @@ -341,8 +320,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= -golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= +golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -364,8 +343,6 @@ golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= -golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -382,12 +359,8 @@ gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= -google.golang.org/genproto/googleapis/api v0.0.0-20250224174004-546df14abb99 h1:ilJhrCga0AptpJZXmUYG4MCrx/zf3l1okuYz7YK9PPw= -google.golang.org/genproto/googleapis/api v0.0.0-20250224174004-546df14abb99/go.mod h1:Xsh8gBVxGCcbV8ZeTB9wI5XPyZ5RvC6V3CTeeplHbiA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99 h1:ZSlhAUqC4r8TPzqLXQ0m3upBNZeF+Y8jQ3c4CR3Ujms= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= @@ -416,33 +389,21 @@ k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= -k8s.io/component-base v0.32.2 h1:1aUL5Vdmu7qNo4ZsE+569PV5zFatM9hl+lb3dEea2zU= -k8s.io/component-base v0.32.2/go.mod h1:PXJ61Vx9Lg+P5mS8TLd7bCIr+eMJRQTyXe8KvkrvJq0= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg= -k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= k8s.io/mount-utils v0.32.2 h1:aDwp+ucWiVnDr/LpRg88/dsXf/vm6gI1VZkYH3+3+Vw= k8s.io/mount-utils v0.32.2/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= -k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.20.2 h1:/439OZVxoEc02psi1h4QO3bHzTgu49bb347Xp4gW1pc= sigs.k8s.io/controller-runtime v0.20.2/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= -sigs.k8s.io/e2e-framework v0.6.0 h1:p7hFzHnLKO7eNsWGI2AbC1Mo2IYxidg49BiT4njxkrM= -sigs.k8s.io/e2e-framework v0.6.0/go.mod h1:IREnCHnKgRCioLRmNi0hxSJ1kJ+aAdjEKK/gokcZu4k= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= -sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk= -sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= From d877c68192badf5eab2008c0ad2330029e356e53 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 12:35:34 +0000 Subject: [PATCH 276/426] fix(deps): update module google.golang.org/grpc to v1.71.0 (main) (#4549) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f61788eb10..d37dad0c33 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( golang.org/x/net v0.36.0 golang.org/x/oauth2 v0.27.0 golang.org/x/sys v0.30.0 - google.golang.org/grpc v1.70.0 + google.golang.org/grpc v1.71.0 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.25.0 istio.io/client-go v1.24.3 diff --git a/go.sum b/go.sum index 63633719fa..9bfa753cc6 100644 --- a/go.sum +++ b/go.sum @@ -361,8 +361,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1: google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= -google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= +google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From a8f979550c8fb499d6b35a48bd1affa97bfb511b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 13:46:42 +0000 Subject: [PATCH 277/426] fix(deps): update module istio.io/client-go to v1.25.0 (main) (#4536) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index d37dad0c33..20d1f6e1f3 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( google.golang.org/grpc v1.71.0 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.25.0 - istio.io/client-go v1.24.3 + istio.io/client-go v1.25.0 k8s.io/api v0.32.2 k8s.io/apiextensions-apiserver v0.32.2 k8s.io/apimachinery v0.32.2 @@ -164,5 +164,5 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect ) diff --git a/go.sum b/go.sum index 9bfa753cc6..cd593a6572 100644 --- a/go.sum +++ b/go.sum @@ -379,8 +379,8 @@ gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= istio.io/api v1.25.0 h1:UVQNFUAz4R06NagA+QpEzLmi4sw+m+UuMgD6sIyXawA= istio.io/api v1.25.0/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= -istio.io/client-go v1.24.3 h1:TB8IcM3yyMCDzKRJo0YfFOUGNQmkhwH/JE/Yr3lzVAk= -istio.io/client-go v1.24.3/go.mod h1:zSyw/c4luKQKosFIHQaWAQOA0c3bODu4SahQCAMlKA4= +istio.io/client-go v1.25.0 h1:MMG8r1g+o2yEzVwi0AGSdB6EQyLEhYz8YMYQQIw8IZw= +istio.io/client-go v1.25.0/go.mod h1:Y4qIjNIVCkpZMiq/e3C7tMjOm7aYUbxT6ebtmai1TRY= k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4= @@ -403,7 +403,7 @@ sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk= +sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= From 0ae083e07ddef82a4d2922ab6f740289d8535c34 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 14:48:48 +0000 Subject: [PATCH 278/426] fix(deps): update module golang.org/x/mod to v0.24.0 (main) (#4550) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 20d1f6e1f3..3d77c3c8ea 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( go.opentelemetry.io/collector/service v0.121.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/mod v0.23.0 + golang.org/x/mod v0.24.0 golang.org/x/net v0.36.0 golang.org/x/oauth2 v0.27.0 golang.org/x/sys v0.30.0 diff --git a/go.sum b/go.sum index cd593a6572..4881034c9e 100644 --- a/go.sum +++ b/go.sum @@ -314,8 +314,8 @@ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From ccc166e538b7252e407e1e24deff3ed9cee406c4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 17:58:13 +0000 Subject: [PATCH 279/426] fix(deps): update module golang.org/x/oauth2 to v0.28.0 (main) (#4551) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3d77c3c8ea..a23fef0d4c 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.24.0 golang.org/x/net v0.36.0 - golang.org/x/oauth2 v0.27.0 + golang.org/x/oauth2 v0.28.0 golang.org/x/sys v0.30.0 google.golang.org/grpc v1.71.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 4881034c9e..4abfb88020 100644 --- a/go.sum +++ b/go.sum @@ -322,8 +322,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= +golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 37af15aa31108b2e3efaedbb51dd4360274dc025 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 23:13:10 +0000 Subject: [PATCH 280/426] fix(deps): update module golang.org/x/sys to v0.31.0 (main) (#4552) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a23fef0d4c..f7fc05520d 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( golang.org/x/mod v0.24.0 golang.org/x/net v0.36.0 golang.org/x/oauth2 v0.28.0 - golang.org/x/sys v0.30.0 + golang.org/x/sys v0.31.0 google.golang.org/grpc v1.71.0 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.25.0 diff --git a/go.sum b/go.sum index 4abfb88020..29a4b8ce73 100644 --- a/go.sum +++ b/go.sum @@ -333,8 +333,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 35ecc26d08a314d5d2536259db22ebdc89d85223 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 03:29:12 +0000 Subject: [PATCH 281/426] chore(deps): update module golang.org/x/tools to v0.31.0 (main) (#4555) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index a2ff16740d..7f76564780 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -7,7 +7,7 @@ golang_ci_cmd_version=v1.64.6 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools -golang_tools_version=v0.30.0 +golang_tools_version=v0.31.0 # renovate depName=github.com/vektra/mockery mockery_version=v2.53.0 # renovate depName=github.com/igorshubovych/markdownlint-cli From 4a743953e96a3bac2ef8bd14847bcda2c900c5f9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 06:25:52 +0000 Subject: [PATCH 282/426] fix(deps): update module golang.org/x/net to v0.37.0 (main) (#4556) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index f7fc05520d..84cf80c725 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.24.0 - golang.org/x/net v0.36.0 + golang.org/x/net v0.37.0 golang.org/x/oauth2 v0.28.0 golang.org/x/sys v0.31.0 google.golang.org/grpc v1.71.0 @@ -150,9 +150,9 @@ require ( go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/term v0.29.0 // indirect - golang.org/x/text v0.22.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/term v0.30.0 // indirect + golang.org/x/text v0.23.0 // indirect golang.org/x/time v0.8.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect diff --git a/go.sum b/go.sum index 29a4b8ce73..86b35b362f 100644 --- a/go.sum +++ b/go.sum @@ -320,27 +320,27 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= -golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From f235dbc856e86df53d759a717c3122122efd966e Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 6 Mar 2025 09:20:40 +0100 Subject: [PATCH 283/426] Remove old google-marketplace testing scripts (#4553) --- hack/helm/google-marketplace/README.md | 13 ------------ hack/helm/google-marketplace/upload_test.sh | 22 --------------------- hack/helm/google-marketplace/verify.sh | 15 -------------- hack/make/deploy/gke.mk | 9 --------- 4 files changed, 59 deletions(-) delete mode 100644 hack/helm/google-marketplace/README.md delete mode 100644 hack/helm/google-marketplace/upload_test.sh delete mode 100644 hack/helm/google-marketplace/verify.sh delete mode 100644 hack/make/deploy/gke.mk diff --git a/hack/helm/google-marketplace/README.md b/hack/helm/google-marketplace/README.md deleted file mode 100644 index 65bdf5fd35..0000000000 --- a/hack/helm/google-marketplace/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Hacking - -The `upload_test.sh` script will help you test your local changes. -It grabs your current selected gcloud project, an application name and a version, builds a new deployer image with all the corresponding files in your repository and pushes it. -Afterwards it applies the application CRD (from Google) and uses mpdev (needs to be part of $PATH) to deploy that new deployer image to your current Kubernetes cluster. - -The following environment variables needs to be provided: - -* gcloud project (REGISTRY bases on this) -* APP_NAME (defaults to "dynatrace-operator") -* VERSION (tag of the docker image - defaults to "test") - -The `verify.sh` script will run will build/push the necessary container then run `mpdev verify` on it. diff --git a/hack/helm/google-marketplace/upload_test.sh b/hack/helm/google-marketplace/upload_test.sh deleted file mode 100644 index f0b640a9c7..0000000000 --- a/hack/helm/google-marketplace/upload_test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -eu - -gcloud config set project dynatrace-marketplace-dev -# Set the registry to your project GCR repo. -export REGISTRY=gcr.io/$(gcloud config get-value project | tr ':' '/') -export APP_NAME=dynatrace-operator -export VERSION=test - -docker build --tag $REGISTRY/$APP_NAME/deployer:$VERSION ./.. --no-cache -docker push $REGISTRY/$APP_NAME/deployer:$VERSION - -kubectl apply -f "https://raw.githubusercontent.com/GoogleCloudPlatform/marketplace-k8s-app-tools/master/crd/app-crd.yaml" - -if kubectl get Application/dynatrace-operator -n dynatrace &> /dev/null; then - kubectl delete application dynatrace-operator -n dynatrace -fi - -kubectl create ns dynatrace -kubectl apply -k https://github.com/Dynatrace/dynatrace-operator/config/crd -mpdev /scripts/install --deployer=$REGISTRY/$APP_NAME/deployer:$VERSION --parameters='{ "name": "dynatrace-operator","namespace": "dynatrace" }' diff --git a/hack/helm/google-marketplace/verify.sh b/hack/helm/google-marketplace/verify.sh deleted file mode 100644 index 7237c1aeb5..0000000000 --- a/hack/helm/google-marketplace/verify.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -set -eu - -gcloud config set project dynatrace-marketplace-dev -# Set the registry to your project GCR repo. -export REGISTRY=gcr.io/$(gcloud config get-value project | tr ':' '/') -export APP_NAME=dynatrace-operator -export VERSION=test - -docker build --tag $REGISTRY/$APP_NAME/deployer:$VERSION ./.. --no-cache -docker push $REGISTRY/$APP_NAME/deployer:$VERSION - -kubectl apply -f https://github.com/Dynatrace/dynatrace-operator/releases/latest/download/dynatrace.com_dynakubes.yaml -mpdev verify --deployer=$REGISTRY/$APP_NAME/deployer:$VERSION \ No newline at end of file diff --git a/hack/make/deploy/gke.mk b/hack/make/deploy/gke.mk deleted file mode 100644 index d3ca978f71..0000000000 --- a/hack/make/deploy/gke.mk +++ /dev/null @@ -1,9 +0,0 @@ -## Deploys the operator using a snapshot deployer image for a standard GKE cluster -deploy/gke/deployer: - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/application/master/deploy/kube-app-manager-aio.yaml - ./hack/gcr/deploy.sh ":snapshot${SNAPSHOT_SUFFIX}" - -## Deploys the operator using a snapshot deployer image for an autopilot GKE cluster -deploy/gke-autopilot/deployer: - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/application/master/deploy/kube-app-manager-aio.yaml - ./hack/gcr/deploy.sh ":snapshot${SNAPSHOT_SUFFIX}" "gke-autopilot" From 960cc2ee943cd749e744cda3f80529b55243d91f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 11:31:01 +0000 Subject: [PATCH 284/426] fix(deps): update module github.com/dynatrace/dynatrace-bootstrapper to v1 (main) (#4558) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 84cf80c725..2f0eb98f0d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Dynatrace/dynatrace-operator go 1.23.4 require ( - github.com/Dynatrace/dynatrace-bootstrapper v0.2.1 + github.com/Dynatrace/dynatrace-bootstrapper v1.0.0 github.com/container-storage-interface/spec v1.11.0 github.com/docker/cli v28.0.1+incompatible github.com/evanphx/json-patch v5.9.11+incompatible diff --git a/go.sum b/go.sum index 86b35b362f..6304e3658b 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/Dynatrace/dynatrace-bootstrapper v0.2.1 h1:RgoDGe4dSaZ0YKVAz4+fo7j0F/v/Y1FKFpgSsrei2FA= github.com/Dynatrace/dynatrace-bootstrapper v0.2.1/go.mod h1:Vx5mNVnDs0eVQiDu6j5WYVTgzc0Qo42oGEtOA6NJpS4= +github.com/Dynatrace/dynatrace-bootstrapper v1.0.0 h1:VdZK+s3bI/RMOC0okKHSuhb2eRuXmcWYiooDe8Awa8k= +github.com/Dynatrace/dynatrace-bootstrapper v1.0.0/go.mod h1:umzzdF2rIRhUBpYHVHLGVjfvMJVa/SK8RXbLvtyA6Ts= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= From 66c11f8c8f220a00607e274964b103ccb77829fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 19:36:27 +0000 Subject: [PATCH 285/426] fix(deps): update module github.com/dynatrace/dynatrace-bootstrapper to v1.0.1 (main) (#4560) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 2f0eb98f0d..56ee09a46b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Dynatrace/dynatrace-operator go 1.23.4 require ( - github.com/Dynatrace/dynatrace-bootstrapper v1.0.0 + github.com/Dynatrace/dynatrace-bootstrapper v1.0.1 github.com/container-storage-interface/spec v1.11.0 github.com/docker/cli v28.0.1+incompatible github.com/evanphx/json-patch v5.9.11+incompatible diff --git a/go.sum b/go.sum index 6304e3658b..0794f772b4 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ -github.com/Dynatrace/dynatrace-bootstrapper v0.2.1 h1:RgoDGe4dSaZ0YKVAz4+fo7j0F/v/Y1FKFpgSsrei2FA= -github.com/Dynatrace/dynatrace-bootstrapper v0.2.1/go.mod h1:Vx5mNVnDs0eVQiDu6j5WYVTgzc0Qo42oGEtOA6NJpS4= -github.com/Dynatrace/dynatrace-bootstrapper v1.0.0 h1:VdZK+s3bI/RMOC0okKHSuhb2eRuXmcWYiooDe8Awa8k= -github.com/Dynatrace/dynatrace-bootstrapper v1.0.0/go.mod h1:umzzdF2rIRhUBpYHVHLGVjfvMJVa/SK8RXbLvtyA6Ts= +github.com/Dynatrace/dynatrace-bootstrapper v1.0.1 h1:AokYM0BuvMdn/UBC66d4Ug2TgGbFuPi1pk6idKbngwo= +github.com/Dynatrace/dynatrace-bootstrapper v1.0.1/go.mod h1:umzzdF2rIRhUBpYHVHLGVjfvMJVa/SK8RXbLvtyA6Ts= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= From 11df762641182beb5c002e9731c286a446db66ca Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 7 Mar 2025 13:10:12 +0100 Subject: [PATCH 286/426] Add setup-go to `build` step in release workflow (#4559) --- .github/workflows/release.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index bfc6f49892..3e4d4247a7 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -44,7 +44,11 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Prepare SBOM + - name: Setup Golang + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + with: + go-version-file: "${{ github.workspace }}/go.mod" + - name: Prepare SBOM # Needs setup-go, uses a binary installed via `go install` id: sbom run: | make release/gen-sbom From 6ce9df993a1e259a560145d2a7375ec1191fc1a7 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Fri, 7 Mar 2025 13:16:15 +0100 Subject: [PATCH 287/426] Create and add OpenSignal API credentials secret to OTelC pod (#4507) Co-authored-by: aorcholski <84514340+aorcholski@users.noreply.github.com> Co-authored-by: Stefan Hauth --- config/crd/bases/dynatrace.com_dynakubes.yaml | 4 +- .../Common/crd/dynatrace-operator-crd.yaml | 4 +- .../clusterole-telemetry-endpoints.yaml | 8 +- ...erviceaccount-opentelemetry-collector.yaml | 2 +- .../clusterrole-telemetry-endpoints_test.yaml | 8 +- ...eaccount-opentelemetry-collector_test.yaml | 2 +- config/helm/chart/default/values.yaml | 2 +- doc/api/dynakube-api-ref.md | 2 +- doc/roles/operator-roles.md | 2 +- pkg/api/v1beta3/dynakube/dynakube_types.go | 6 +- pkg/api/v1beta3/dynakube/extensions_props.go | 4 - pkg/api/v1beta3/dynakube/otelc_props.go | 5 + .../v1beta3/dynakube/telemetryingest/props.go | 36 +++ .../spec.go | 4 +- .../zz_generated.deepcopy.go | 2 +- .../dynakube/telemetryservice/props.go | 50 --- .../dynakube/telemetryservice_props.go | 8 +- .../v1beta3/dynakube/zz_generated.deepcopy.go | 8 +- .../validation/dynakube/telemetryservice.go | 56 ++-- .../dynakube/telemetryservice_test.go | 61 ++-- pkg/api/validation/dynakube/validation.go | 8 +- .../activegate/capability/capability.go | 2 +- .../activegate/capability/capability_test.go | 26 +- .../internal/statefulset/statefulset.go | 4 +- .../internal/statefulset/statefulset_test.go | 10 +- .../otelc/configuration/conditions.go | 3 + .../dynakube/otelc/configuration/config.go | 7 + .../otelc/configuration/reconciler.go | 140 ++++++++ .../otelc/configuration/reconciler_test.go | 56 ++++ .../dynakube/otelc/consts/consts.go | 14 + pkg/controllers/dynakube/otelc/reconciler.go | 36 ++- .../dynakube/otelc/secret/conditions.go | 5 + .../dynakube/otelc/secret/config.go | 7 + .../dynakube/otelc/secret/reconciler.go | 136 ++++++++ .../dynakube/otelc/secret/reconciler_test.go | 110 +++++++ .../dynakube/otelc/service/reconciler.go | 24 +- .../dynakube/otelc/service/reconciler_test.go | 46 +-- .../dynakube/otelc/statefulset/container.go | 16 +- .../otelc/statefulset/container_test.go | 40 +++ .../dynakube/otelc/statefulset/env.go | 57 +++- .../dynakube/otelc/statefulset/env_test.go | 108 +++++++ .../dynakube/otelc/statefulset/reconciler.go | 99 ++++-- .../otelc/statefulset/reconciler_test.go | 299 +++++------------- .../dynakube/otelc/statefulset/volumes.go | 112 ++++--- .../otelc/statefulset/volumes_test.go | 172 ++++++++++ pkg/controllers/dynakube/phase.go | 2 +- pkg/controllers/dynakube/phase_test.go | 8 +- pkg/otelcgen/exporters.go | 3 +- pkg/otelcgen/exporters_test.go | 4 +- pkg/otelcgen/extensions_test.go | 1 + pkg/otelcgen/otelcgen.go | 59 +++- pkg/otelcgen/otelcgen_test.go | 4 +- pkg/otelcgen/processors.go | 16 +- pkg/otelcgen/processors_test.go | 1 + pkg/otelcgen/receivers.go | 11 +- pkg/otelcgen/receivers_test.go | 15 +- pkg/otelcgen/services.go | 83 +++-- pkg/otelcgen/services_test.go | 31 ++ pkg/otelcgen/testdata/exporters_only.yaml | 1 + pkg/otelcgen/testdata/full_config.yaml | 10 +- pkg/otelcgen/testdata/processors_only.yaml | 1 + pkg/otelcgen/testdata/services_only.yaml | 6 +- .../testdata/services_statsd_only.yaml | 21 ++ .../testdata/services_zipkin_only.yaml | 20 ++ pkg/util/conditions/configmap.go | 44 +++ pkg/util/conditions/token.go | 20 ++ pkg/util/kubeobjects/labels/labels.go | 3 +- test/features/extensions/extensions.go | 2 +- .../support_archive/support_archive.go | 2 +- 69 files changed, 1595 insertions(+), 584 deletions(-) create mode 100644 pkg/api/v1beta3/dynakube/otelc_props.go create mode 100644 pkg/api/v1beta3/dynakube/telemetryingest/props.go rename pkg/api/v1beta3/dynakube/{telemetryservice => telemetryingest}/spec.go (86%) rename pkg/api/v1beta3/dynakube/{telemetryservice => telemetryingest}/zz_generated.deepcopy.go (97%) delete mode 100644 pkg/api/v1beta3/dynakube/telemetryservice/props.go create mode 100644 pkg/controllers/dynakube/otelc/configuration/conditions.go create mode 100644 pkg/controllers/dynakube/otelc/configuration/config.go create mode 100644 pkg/controllers/dynakube/otelc/configuration/reconciler.go create mode 100644 pkg/controllers/dynakube/otelc/configuration/reconciler_test.go create mode 100644 pkg/controllers/dynakube/otelc/consts/consts.go create mode 100644 pkg/controllers/dynakube/otelc/secret/conditions.go create mode 100644 pkg/controllers/dynakube/otelc/secret/config.go create mode 100644 pkg/controllers/dynakube/otelc/secret/reconciler.go create mode 100644 pkg/controllers/dynakube/otelc/secret/reconciler_test.go create mode 100644 pkg/controllers/dynakube/otelc/statefulset/container_test.go create mode 100644 pkg/controllers/dynakube/otelc/statefulset/env_test.go create mode 100644 pkg/controllers/dynakube/otelc/statefulset/volumes_test.go create mode 100644 pkg/otelcgen/testdata/services_statsd_only.yaml create mode 100644 pkg/otelcgen/testdata/services_zipkin_only.yaml create mode 100644 pkg/util/conditions/configmap.go create mode 100644 pkg/util/conditions/token.go diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index bcc60e4aa5..53a8dc927f 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -6214,8 +6214,8 @@ spec: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. Set to true if you want to skip certification validation checks. type: boolean - telemetryService: - description: When a TelemetryServiceSpec is provided, the OTEL collector + telemetryIngest: + description: When a TelemetryIngestSpec is provided, the OTEL collector is deployed by the operator. properties: protocols: diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 9381971800..2e2c26da21 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -6226,8 +6226,8 @@ spec: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. Set to true if you want to skip certification validation checks. type: boolean - telemetryService: - description: When a TelemetryServiceSpec is provided, the OTEL collector + telemetryIngest: + description: When a TelemetryIngestSpec is provided, the OTEL collector is deployed by the operator. properties: protocols: diff --git a/config/helm/chart/default/templates/Common/opentelemetry-collector/clusterole-telemetry-endpoints.yaml b/config/helm/chart/default/templates/Common/opentelemetry-collector/clusterole-telemetry-endpoints.yaml index 6a3449bd03..21af3c1c81 100644 --- a/config/helm/chart/default/templates/Common/opentelemetry-collector/clusterole-telemetry-endpoints.yaml +++ b/config/helm/chart/default/templates/Common/opentelemetry-collector/clusterole-telemetry-endpoints.yaml @@ -1,4 +1,4 @@ -{{- if .Values.rbac.telemetryService.create }} +{{- if .Values.rbac.telemetryIngest.create }} # Copyright 2021 Dynatrace LLC # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,7 +15,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: dynatrace-telemetry-service + name: dynatrace-telemetry-ingest namespace: {{ .Release.Namespace }} labels: {{- include "dynatrace-operator.openTelemetryCollectorLabels" . | nindent 4 }} @@ -52,14 +52,14 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: dynatrace-telemetry-service + name: dynatrace-telemetry-ingest namespace: {{ .Release.Namespace }} labels: {{- include "dynatrace-operator.openTelemetryCollectorLabels" . | nindent 4 }} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: dynatrace-telemetry-service + name: dynatrace-telemetry-ingest subjects: - kind: ServiceAccount name: dynatrace-opentelemetry-collector diff --git a/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml b/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml index 119e411e44..255d229edc 100644 --- a/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml +++ b/config/helm/chart/default/templates/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector.yaml @@ -1,4 +1,4 @@ -{{- if or (.Values.rbac.extensions.create) (.Values.rbac.telemetryService.create) }} +{{- if or (.Values.rbac.extensions.create) (.Values.rbac.telemetryIngest.create) }} # Copyright 2021 Dynatrace LLC # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml b/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml index 860c1c5012..8783e55215 100644 --- a/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml +++ b/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml @@ -14,7 +14,7 @@ tests: of: ClusterRole - equal: path: metadata.name - value: dynatrace-telemetry-service + value: dynatrace-telemetry-ingest - isNotEmpty: path: metadata.labels - isNotEmpty: @@ -52,7 +52,7 @@ tests: of: ClusterRole - equal: path: metadata.name - value: dynatrace-telemetry-service + value: dynatrace-telemetry-ingest - isNotEmpty: path: metadata.labels - contains: @@ -73,13 +73,13 @@ tests: of: ClusterRoleBinding - equal: path: metadata.name - value: dynatrace-telemetry-service + value: dynatrace-telemetry-ingest - isNotEmpty: path: metadata.labels - it: shouldn't exist if turned off set: - rbac.telemetryService.create: false + rbac.telemetryIngest.create: false asserts: - hasDocuments: count: 0 diff --git a/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml b/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml index 6dab0b2a2f..df2491dc47 100644 --- a/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml +++ b/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml @@ -20,7 +20,7 @@ tests: - it: shouldn't exist if turned off set: rbac.extensions.create: false - rbac.telemetryService.create: false + rbac.telemetryIngest.create: false asserts: - hasDocuments: count: 0 diff --git a/config/helm/chart/default/values.yaml b/config/helm/chart/default/values.yaml index 65c79db4aa..c6bf800c9d 100644 --- a/config/helm/chart/default/values.yaml +++ b/config/helm/chart/default/values.yaml @@ -208,7 +208,7 @@ rbac: extensions: create: true annotations: {} - telemetryService: + telemetryIngest: create: true annotations: {} logMonitoring: diff --git a/doc/api/dynakube-api-ref.md b/doc/api/dynakube-api-ref.md index 4adedce267..ff320db168 100644 --- a/doc/api/dynakube-api-ref.md +++ b/doc/api/dynakube-api-ref.md @@ -49,7 +49,7 @@ |:-|:-|:-|:-| |`ingestRuleMatchers`||-|array| -### .spec.telemetryService +### .spec.telemetryIngest |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| diff --git a/doc/roles/operator-roles.md b/doc/roles/operator-roles.md index 12d36d01ea..1df282de55 100644 --- a/doc/roles/operator-roles.md +++ b/doc/roles/operator-roles.md @@ -5,7 +5,7 @@ | Resources | Verbs | Comments | | ------------------------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | events | create, get, list | Required by operator SDK | -| services | create, update, delete, get, list, watch | Required for ActiveGate, OTEL Collector Operator TelemetryService, Extensions | +| services | create, update, delete, get, list, watch | Required for ActiveGate, OTEL Collector Operator TelemetryIngest, Extensions | | serviceentries.networking.istio.io | get, list, create, update, delete | Required by Istio Reconciler | | virtualservices.networking.istio.io | get, list, create, update, delete | Required by Istio Reconciler | | configmaps | get, list, watch, create, update, delete | Required to access trustedCAs, edgeConnect CA certs, ActiveGate/OneAgent Connection Info, Extension Custom Configuration, NodesController cache | diff --git a/pkg/api/v1beta3/dynakube/dynakube_types.go b/pkg/api/v1beta3/dynakube/dynakube_types.go index 3ceca7f9ef..8907a2d74d 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_types.go +++ b/pkg/api/v1beta3/dynakube/dynakube_types.go @@ -10,7 +10,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -93,9 +93,9 @@ type DynaKubeSpec struct { //nolint:revive // +kubebuilder:validation:Optional Extensions *ExtensionsSpec `json:"extensions,omitempty"` - // When a TelemetryServiceSpec is provided, the OTEL collector is deployed by the operator. + // When a TelemetryIngestSpec is provided, the OTEL collector is deployed by the operator. // +kubebuilder:validation:Optional - TelemetryService *telemetryservice.Spec `json:"telemetryService,omitempty"` + TelemetryIngest *telemetryingest.Spec `json:"telemetryIngest,omitempty"` // General configuration about OneAgent instances. // You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). diff --git a/pkg/api/v1beta3/dynakube/extensions_props.go b/pkg/api/v1beta3/dynakube/extensions_props.go index 6bfe4bba2a..acdd7a3911 100644 --- a/pkg/api/v1beta3/dynakube/extensions_props.go +++ b/pkg/api/v1beta3/dynakube/extensions_props.go @@ -32,10 +32,6 @@ func (dk *DynaKube) ExtensionsExecutionControllerStatefulsetName() string { return dk.Name + "-extensions-controller" } -func (dk *DynaKube) ExtensionsCollectorStatefulsetName() string { - return dk.Name + "-extensions-collector" -} - func (dk *DynaKube) ExtensionsTokenSecretName() string { return dk.Name + "-extensions-token" } diff --git a/pkg/api/v1beta3/dynakube/otelc_props.go b/pkg/api/v1beta3/dynakube/otelc_props.go new file mode 100644 index 0000000000..064ce39176 --- /dev/null +++ b/pkg/api/v1beta3/dynakube/otelc_props.go @@ -0,0 +1,5 @@ +package dynakube + +func (dk *DynaKube) OtelCollectorStatefulsetName() string { + return dk.Name + "-extensions-collector" +} diff --git a/pkg/api/v1beta3/dynakube/telemetryingest/props.go b/pkg/api/v1beta3/dynakube/telemetryingest/props.go new file mode 100644 index 0000000000..dd95cb9601 --- /dev/null +++ b/pkg/api/v1beta3/dynakube/telemetryingest/props.go @@ -0,0 +1,36 @@ +package telemetryingest + +import "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" + +const ( + nameSuffix = "-telemetry-ingest" +) + +func (spec *Spec) GetProtocols() otelcgen.Protocols { + if spec == nil { + return otelcgen.Protocols{} + } + + if len(spec.Protocols) == 0 { + return otelcgen.RegisteredProtocols + } + + protocols := make(otelcgen.Protocols, len(spec.Protocols)) + for i, proto := range spec.Protocols { + protocols[i] = otelcgen.Protocol(proto) + } + + return protocols +} + +func (ts *TelemetryIngest) SetName(name string) { + ts.name = name +} + +func (ts *TelemetryIngest) GetName() string { + return ts.name + nameSuffix +} + +func (ts *TelemetryIngest) IsEnabled() bool { + return ts.Spec != nil +} diff --git a/pkg/api/v1beta3/dynakube/telemetryservice/spec.go b/pkg/api/v1beta3/dynakube/telemetryingest/spec.go similarity index 86% rename from pkg/api/v1beta3/dynakube/telemetryservice/spec.go rename to pkg/api/v1beta3/dynakube/telemetryingest/spec.go index 81844ede76..e803e4dedc 100644 --- a/pkg/api/v1beta3/dynakube/telemetryservice/spec.go +++ b/pkg/api/v1beta3/dynakube/telemetryingest/spec.go @@ -1,6 +1,6 @@ -package telemetryservice +package telemetryingest -type TelemetryService struct { +type TelemetryIngest struct { *Spec name string diff --git a/pkg/api/v1beta3/dynakube/telemetryservice/zz_generated.deepcopy.go b/pkg/api/v1beta3/dynakube/telemetryingest/zz_generated.deepcopy.go similarity index 97% rename from pkg/api/v1beta3/dynakube/telemetryservice/zz_generated.deepcopy.go rename to pkg/api/v1beta3/dynakube/telemetryingest/zz_generated.deepcopy.go index a30d50258a..425966b834 100644 --- a/pkg/api/v1beta3/dynakube/telemetryservice/zz_generated.deepcopy.go +++ b/pkg/api/v1beta3/dynakube/telemetryingest/zz_generated.deepcopy.go @@ -16,7 +16,7 @@ limitations under the License. // Code generated by controller-gen. DO NOT EDIT. -package telemetryservice +package telemetryingest import () diff --git a/pkg/api/v1beta3/dynakube/telemetryservice/props.go b/pkg/api/v1beta3/dynakube/telemetryservice/props.go deleted file mode 100644 index b391039883..0000000000 --- a/pkg/api/v1beta3/dynakube/telemetryservice/props.go +++ /dev/null @@ -1,50 +0,0 @@ -package telemetryservice - -type Protocol string - -const ( - nameSuffix = "-telemetry" - - OtlpProtocol Protocol = "otlp" - ZipkinProtocol Protocol = "zipkin" - JaegerProtocol Protocol = "jaeger" - StatsdProtocol Protocol = "statsd" -) - -func KnownProtocols() []Protocol { - return []Protocol{ - OtlpProtocol, - ZipkinProtocol, - JaegerProtocol, - StatsdProtocol, - } -} - -func (spec *Spec) GetProtocols() []Protocol { - if spec == nil { - return []Protocol{} - } - - if len(spec.Protocols) == 0 { - return KnownProtocols() - } - - protocols := make([]Protocol, len(spec.Protocols)) - for i, proto := range spec.Protocols { - protocols[i] = Protocol(proto) - } - - return protocols -} - -func (ts *TelemetryService) SetName(name string) { - ts.name = name -} - -func (ts *TelemetryService) GetName() string { - return ts.name + nameSuffix -} - -func (ts *TelemetryService) IsEnabled() bool { - return ts.Spec != nil -} diff --git a/pkg/api/v1beta3/dynakube/telemetryservice_props.go b/pkg/api/v1beta3/dynakube/telemetryservice_props.go index 11fa60e724..591774afe8 100644 --- a/pkg/api/v1beta3/dynakube/telemetryservice_props.go +++ b/pkg/api/v1beta3/dynakube/telemetryservice_props.go @@ -1,12 +1,12 @@ package dynakube import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" ) -func (dk *DynaKube) TelemetryService() *telemetryservice.TelemetryService { - ts := &telemetryservice.TelemetryService{ - Spec: dk.Spec.TelemetryService, +func (dk *DynaKube) TelemetryIngest() *telemetryingest.TelemetryIngest { + ts := &telemetryingest.TelemetryIngest{ + Spec: dk.Spec.TelemetryIngest, } ts.SetName(dk.Name) diff --git a/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go b/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go index 11dcedeccf..637cad38ec 100644 --- a/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go +++ b/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go @@ -22,7 +22,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -116,9 +116,9 @@ func (in *DynaKubeSpec) DeepCopyInto(out *DynaKubeSpec) { *out = new(ExtensionsSpec) **out = **in } - if in.TelemetryService != nil { - in, out := &in.TelemetryService, &out.TelemetryService - *out = new(telemetryservice.Spec) + if in.TelemetryIngest != nil { + in, out := &in.TelemetryIngest, &out.TelemetryIngest + *out = new(telemetryingest.Spec) (*in).DeepCopyInto(*out) } in.OneAgent.DeepCopyInto(&out.OneAgent) diff --git a/pkg/api/validation/dynakube/telemetryservice.go b/pkg/api/validation/dynakube/telemetryservice.go index 45efd12bdd..627a73b595 100644 --- a/pkg/api/validation/dynakube/telemetryservice.go +++ b/pkg/api/validation/dynakube/telemetryservice.go @@ -7,63 +7,63 @@ import ( "strings" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" "k8s.io/apimachinery/pkg/util/validation" ) const ( - errorTelemetryServiceNotEnoughProtocols = `DynaKube's specification enables the TelemetryService feature, at least one Protocol has to be specified.` - errorTelemetryServiceUnknownProtocols = `DynaKube's specification enables the TelemetryService feature, unsupported protocols found on the Protocols list.` - errorTelemetryServiceDuplicatedProtocols = `DynaKube's specification enables the TelemetryService feature, duplicated protocols found on the Protocols list.` - errorTelemetryServiceNoDNS1053Label = `DynaKube's specification enables the TelemetryService feature, the telemetry service name violates DNS-1035. + errorTelemetryIngestNotEnoughProtocols = `DynaKube's specification enables the TelemetryIngest feature, at least one Protocol has to be specified.` + errorTelemetryIngestUnknownProtocols = `DynaKube's specification enables the TelemetryIngest feature, unsupported protocols found on the Protocols list.` + errorTelemetryIngestDuplicatedProtocols = `DynaKube's specification enables the TelemetryIngest feature, duplicated protocols found on the Protocols list.` + errorTelemetryIngestNoDNS1053Label = `DynaKube's specification enables the TelemetryIngest feature, the telemetry service name violates DNS-1035. [The length limit for the name is %d. Additionally a DNS-1035 name must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')] ` ) -func emptyTelemetryServiceProtocolsList(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - if !dk.TelemetryService().IsEnabled() { +func emptyTelemetryIngestProtocolsList(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryIngest().IsEnabled() { return "" } - if len(dk.TelemetryService().GetProtocols()) == 0 { + if len(dk.TelemetryIngest().GetProtocols()) == 0 { log.Info("requested dynakube specify empty list of Protocols") - return errorTelemetryServiceNotEnoughProtocols + return errorTelemetryIngestNotEnoughProtocols } return "" } -func unknownTelemetryServiceProtocols(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - if !dk.TelemetryService().IsEnabled() { +func unknownTelemetryIngestProtocols(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryIngest().IsEnabled() { return "" } var unknownProtocols []string - for _, protocol := range dk.TelemetryService().GetProtocols() { - if !slices.Contains(telemetryservice.KnownProtocols(), protocol) { + for _, protocol := range dk.TelemetryIngest().GetProtocols() { + if !slices.Contains(otelcgen.RegisteredProtocols, protocol) { unknownProtocols = append(unknownProtocols, string(protocol)) } } if len(unknownProtocols) > 0 { - log.Info("requested dynakube specify unknown TelemetryService protocol(s)", "protocols", strings.Join(unknownProtocols, ",")) + log.Info("requested dynakube specify unknown TelemetryIngest protocol(s)", "protocols", strings.Join(unknownProtocols, ",")) - return errorTelemetryServiceUnknownProtocols + return errorTelemetryIngestUnknownProtocols } return "" } -func duplicatedTelemetryServiceProtocols(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - if !dk.TelemetryService().IsEnabled() { +func duplicatedTelemetryIngestProtocols(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryIngest().IsEnabled() { return "" } - protocolsOccurrences := map[telemetryservice.Protocol]int{} + protocolsOccurrences := map[otelcgen.Protocol]int{} - for _, protocol := range dk.TelemetryService().GetProtocols() { + for _, protocol := range dk.TelemetryIngest().GetProtocols() { if _, ok := protocolsOccurrences[protocol]; !ok { protocolsOccurrences[protocol] = 1 } else { @@ -80,32 +80,32 @@ func duplicatedTelemetryServiceProtocols(_ context.Context, _ *Validator, dk *dy } if len(duplicatedProtocols) > 0 { - log.Info("requested dynakube specify duplicated TelemetryService protocol(s)", "protocols", strings.Join(duplicatedProtocols, ",")) + log.Info("requested dynakube specify duplicated TelemetryIngest protocol(s)", "protocols", strings.Join(duplicatedProtocols, ",")) - return errorTelemetryServiceDuplicatedProtocols + return errorTelemetryIngestDuplicatedProtocols } return "" } -func invalidTelemetryServiceName(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - if !dk.TelemetryService().IsEnabled() { +func invalidTelemetryIngestName(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryIngest().IsEnabled() { return "" } var errs []string - if dk.TelemetryService().ServiceName != "" { - errs = validation.IsDNS1035Label(dk.Spec.TelemetryService.ServiceName) + if dk.TelemetryIngest().ServiceName != "" { + errs = validation.IsDNS1035Label(dk.Spec.TelemetryIngest.ServiceName) } if len(errs) == 0 { return "" } - return invalidTelemetryServiceNameErrorMessage() + return invalidTelemetryIngestNameErrorMessage() } -func invalidTelemetryServiceNameErrorMessage() string { - return fmt.Sprintf(errorTelemetryServiceNoDNS1053Label, validation.DNS1035LabelMaxLength) +func invalidTelemetryIngestNameErrorMessage() string { + return fmt.Sprintf(errorTelemetryIngestNoDNS1053Label, validation.DNS1035LabelMaxLength) } diff --git a/pkg/api/validation/dynakube/telemetryservice_test.go b/pkg/api/validation/dynakube/telemetryservice_test.go index 894f39ea22..262c230eff 100644 --- a/pkg/api/validation/dynakube/telemetryservice_test.go +++ b/pkg/api/validation/dynakube/telemetryservice_test.go @@ -4,17 +4,18 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" ) -func TestTelemetryServiceProtocols(t *testing.T) { +func TestTelemetryIngestProtocols(t *testing.T) { t.Run(`no list of protocols`, func(t *testing.T) { assertAllowed(t, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - TelemetryService: &telemetryservice.Spec{ + TelemetryIngest: &telemetryingest.Spec{ Protocols: nil, }, }, @@ -27,7 +28,7 @@ func TestTelemetryServiceProtocols(t *testing.T) { ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - TelemetryService: &telemetryservice.Spec{ + TelemetryIngest: &telemetryingest.Spec{ Protocols: []string{}, }, }, @@ -36,15 +37,15 @@ func TestTelemetryServiceProtocols(t *testing.T) { t.Run(`unknown protocol`, func(t *testing.T) { assertDenied(t, - []string{errorTelemetryServiceUnknownProtocols}, + []string{errorTelemetryIngestUnknownProtocols}, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - TelemetryService: &telemetryservice.Spec{ + TelemetryIngest: &telemetryingest.Spec{ Protocols: []string{ - string(telemetryservice.ZipkinProtocol), - string(telemetryservice.OtlpProtocol), + string(otelcgen.ZipkinProtocol), + string(otelcgen.OtlpProtocol), "unknown", }, }, @@ -54,15 +55,15 @@ func TestTelemetryServiceProtocols(t *testing.T) { t.Run(`unknown protocols`, func(t *testing.T) { assertDenied(t, - []string{errorTelemetryServiceUnknownProtocols}, + []string{errorTelemetryIngestUnknownProtocols}, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - TelemetryService: &telemetryservice.Spec{ + TelemetryIngest: &telemetryingest.Spec{ Protocols: []string{ - string(telemetryservice.ZipkinProtocol), - string(telemetryservice.OtlpProtocol), + string(otelcgen.ZipkinProtocol), + string(otelcgen.OtlpProtocol), "unknown1", "unknown2", }, @@ -73,16 +74,16 @@ func TestTelemetryServiceProtocols(t *testing.T) { t.Run(`duplicated protocol`, func(t *testing.T) { assertDenied(t, - []string{errorTelemetryServiceDuplicatedProtocols}, + []string{errorTelemetryIngestDuplicatedProtocols}, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - TelemetryService: &telemetryservice.Spec{ + TelemetryIngest: &telemetryingest.Spec{ Protocols: []string{ - string(telemetryservice.ZipkinProtocol), - string(telemetryservice.OtlpProtocol), - string(telemetryservice.OtlpProtocol), + string(otelcgen.ZipkinProtocol), + string(otelcgen.OtlpProtocol), + string(otelcgen.OtlpProtocol), }, }, }, @@ -91,18 +92,18 @@ func TestTelemetryServiceProtocols(t *testing.T) { t.Run(`duplicated protocols`, func(t *testing.T) { assertDenied(t, - []string{errorTelemetryServiceDuplicatedProtocols}, + []string{errorTelemetryIngestDuplicatedProtocols}, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - TelemetryService: &telemetryservice.Spec{ + TelemetryIngest: &telemetryingest.Spec{ Protocols: []string{ - string(telemetryservice.ZipkinProtocol), - string(telemetryservice.ZipkinProtocol), - string(telemetryservice.OtlpProtocol), - string(telemetryservice.OtlpProtocol), - string(telemetryservice.JaegerProtocol), + string(otelcgen.ZipkinProtocol), + string(otelcgen.ZipkinProtocol), + string(otelcgen.OtlpProtocol), + string(otelcgen.OtlpProtocol), + string(otelcgen.JaegerProtocol), }, }, }, @@ -114,8 +115,8 @@ func TestTelemetryServiceProtocols(t *testing.T) { &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ - APIURL: testApiUrl, - TelemetryService: &telemetryservice.Spec{}, + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{}, }, }) }) @@ -132,12 +133,12 @@ func TestTelemetryServiceProtocols(t *testing.T) { t.Run(`service name too long`, func(t *testing.T) { assertDenied(t, - []string{invalidTelemetryServiceNameErrorMessage()}, + []string{invalidTelemetryIngestNameErrorMessage()}, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - TelemetryService: &telemetryservice.Spec{ + TelemetryIngest: &telemetryingest.Spec{ ServiceName: "a123456789012345678901234567890123456789012345678901234567890123", }, }, @@ -146,12 +147,12 @@ func TestTelemetryServiceProtocols(t *testing.T) { t.Run(`service name violates DNS-1035`, func(t *testing.T) { assertDenied(t, - []string{invalidTelemetryServiceNameErrorMessage()}, + []string{invalidTelemetryIngestNameErrorMessage()}, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, - TelemetryService: &telemetryservice.Spec{ + TelemetryIngest: &telemetryingest.Spec{ ServiceName: "0123", }, }, diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 3a9a0db898..9f7bfab7ef 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -55,10 +55,10 @@ var ( tooManyAGReplicas, missingKSPMImage, missingLogMonitoringImage, - emptyTelemetryServiceProtocolsList, - unknownTelemetryServiceProtocols, - duplicatedTelemetryServiceProtocols, - invalidTelemetryServiceName, + emptyTelemetryIngestProtocolsList, + unknownTelemetryIngestProtocols, + duplicatedTelemetryIngestProtocols, + invalidTelemetryIngestName, } validatorWarningFuncs = []validatorFunc{ missingActiveGateMemoryLimit, diff --git a/pkg/controllers/dynakube/activegate/capability/capability.go b/pkg/controllers/dynakube/activegate/capability/capability.go index 6224713353..2e2a585aae 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability.go +++ b/pkg/controllers/dynakube/activegate/capability/capability.go @@ -103,7 +103,7 @@ func NewMultiCapability(dk *dynakube.DynaKube) Capability { capabilityDisplayNames = append(capabilityDisplayNames, "extension_controller") } - if dk.IsOTLPingestEnabled() || dk.TelemetryService().IsEnabled() { + if dk.IsOTLPingestEnabled() || dk.TelemetryIngest().IsEnabled() { capabilityNames = append(capabilityNames, "log_analytics_collector", "generic_ingest_enabled", "otlp_ingest") capabilityDisplayNames = append(capabilityDisplayNames, "log_analytics_collector", "generic_ingest_enabled", "otlp_ingest") } diff --git a/pkg/controllers/dynakube/activegate/capability/capability_test.go b/pkg/controllers/dynakube/activegate/capability/capability_test.go index 8b551b9265..4b83dbc5e9 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability_test.go +++ b/pkg/controllers/dynakube/activegate/capability/capability_test.go @@ -5,7 +5,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -24,7 +24,7 @@ const ( expectedArgNameWithOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest_enabled,otlp_ingest" expectedArgNameWithOTLPingestOnly = "log_analytics_collector,generic_ingest_enabled,otlp_ingest" expectedArgNameWithExtensionsAndOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller,log_analytics_collector,generic_ingest_enabled,otlp_ingest" - expectedArgNameWithTelemetryService = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest_enabled,otlp_ingest" + expectedArgNameWithTelemetryIngest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest_enabled,otlp_ingest" ) var capabilities = []activegate.CapabilityDisplayName{ @@ -34,15 +34,15 @@ var capabilities = []activegate.CapabilityDisplayName{ activegate.DynatraceApiCapability.DisplayName, } -func buildDynakube(capabilities []activegate.CapabilityDisplayName, enableExtensions bool, enableOTLPingest bool, enableTelemetryService bool) *dynakube.DynaKube { +func buildDynakube(capabilities []activegate.CapabilityDisplayName, enableExtensions bool, enableOTLPingest bool, enableTelemetryIngest bool) *dynakube.DynaKube { extensionsSpec := &dynakube.ExtensionsSpec{} if !enableExtensions { extensionsSpec = nil } - telemetryServiceSpec := &telemetryservice.Spec{} - if !enableTelemetryService { - telemetryServiceSpec = nil + telemetryIngestSpec := &telemetryingest.Spec{} + if !enableTelemetryIngest { + telemetryIngestSpec = nil } return &dynakube.DynaKube{ @@ -56,7 +56,7 @@ func buildDynakube(capabilities []activegate.CapabilityDisplayName, enableExtens }, Extensions: extensionsSpec, EnableOTLPingest: enableOTLPingest, - TelemetryService: telemetryServiceSpec, + TelemetryIngest: telemetryIngestSpec, }, } } @@ -150,16 +150,16 @@ func TestNewMultiCapabilityWithExtensionsAndOTLPingest(t *testing.T) { }) } -func TestNewMultiCapabilityWithTelemetryService(t *testing.T) { - t.Run(`creates new multicapability with TelemetryService enabled`, func(t *testing.T) { +func TestNewMultiCapabilityWithTelemetryIngest(t *testing.T) { + t.Run(`creates new multicapability with TelemetryIngest enabled`, func(t *testing.T) { dk := buildDynakube(capabilities, false, false, true) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.True(t, mc.Enabled()) assert.Equal(t, expectedShortName, mc.ShortName()) - assert.Equal(t, expectedArgNameWithTelemetryService, mc.ArgName()) + assert.Equal(t, expectedArgNameWithTelemetryIngest, mc.ArgName()) }) - t.Run(`creates new multicapability without capabilities set in dynakube and TelemetryService enabled`, func(t *testing.T) { + t.Run(`creates new multicapability without capabilities set in dynakube and TelemetryIngest enabled`, func(t *testing.T) { var emptyCapabilites []activegate.CapabilityDisplayName dk := buildDynakube(emptyCapabilites, false, false, true) mc := NewMultiCapability(dk) @@ -170,8 +170,8 @@ func TestNewMultiCapabilityWithTelemetryService(t *testing.T) { }) } -func TestNewMultiCapabilityWithOTLPingestAndTelemetryService(t *testing.T) { - t.Run(`creates new multicapability without capabilities set in dynakube and with OTLPingest and TelemetryService enabled`, func(t *testing.T) { +func TestNewMultiCapabilityWithOTLPingestAndTelemetryIngest(t *testing.T) { + t.Run(`creates new multicapability without capabilities set in dynakube and with OTLPingest and TelemetryIngest enabled`, func(t *testing.T) { var emptyCapabilites []activegate.CapabilityDisplayName dk := buildDynakube(emptyCapabilites, false, true, true) mc := NewMultiCapability(dk) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index e5bf4d8053..6859d1ab13 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -145,7 +145,7 @@ func (statefulSetBuilder Builder) buildTopologySpreadConstraints(capability capa func (statefulSetBuilder Builder) buildVolumes() []corev1.Volume { volumes := []corev1.Volume{} - if !(statefulSetBuilder.dynakube.IsOTLPingestEnabled() || statefulSetBuilder.dynakube.TelemetryService().IsEnabled()) || statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume { + if !(statefulSetBuilder.dynakube.IsOTLPingestEnabled() || statefulSetBuilder.dynakube.TelemetryIngest().IsEnabled()) || statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume { volumes = append(volumes, corev1.Volume{ Name: consts.GatewayTmpVolumeName, VolumeSource: corev1.VolumeSource{ @@ -274,7 +274,7 @@ func (statefulSetBuilder Builder) nodeAffinity() *corev1.Affinity { } func (statefulSetBuilder Builder) addPersistentVolumeClaim(sts *appsv1.StatefulSet) { - if (statefulSetBuilder.dynakube.IsOTLPingestEnabled() || statefulSetBuilder.dynakube.TelemetryService().IsEnabled()) && !statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume { + if (statefulSetBuilder.dynakube.IsOTLPingestEnabled() || statefulSetBuilder.dynakube.TelemetryIngest().IsEnabled()) && !statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume { if statefulSetBuilder.dynakube.Spec.ActiveGate.PersistentVolumeClaim == nil { sts.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{ { diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index 2e45a39aea..918c55c097 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -9,7 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" @@ -584,14 +584,14 @@ func TestPVC(t *testing.T) { test(dk, multiCapability, myPVCspec) }) - t.Run("use custom PVC with TelemetryService", func(t *testing.T) { + t.Run("use custom PVC with TelemetryIngest", func(t *testing.T) { dk := getTestDynakube() multiCapability := capability.NewMultiCapability(&dk) myPVCspec := corev1.PersistentVolumeClaimSpec{ StorageClassName: ptr.To("test"), VolumeName: "foo-pv", } - dk.Spec.TelemetryService = &telemetryservice.Spec{} + dk.Spec.TelemetryIngest = &telemetryingest.Spec{} dk.Spec.ActiveGate.PersistentVolumeClaim = &myPVCspec test(dk, multiCapability, myPVCspec) @@ -603,9 +603,9 @@ func TestPVC(t *testing.T) { test(dk, multiCapability, defaultPVCSpec()) }) - t.Run("use default PVC with TelemetryService", func(t *testing.T) { + t.Run("use default PVC with TelemetryIngest", func(t *testing.T) { dk := getTestDynakube() - dk.Spec.TelemetryService = &telemetryservice.Spec{} + dk.Spec.TelemetryIngest = &telemetryingest.Spec{} multiCapability := capability.NewMultiCapability(&dk) test(dk, multiCapability, defaultPVCSpec()) diff --git a/pkg/controllers/dynakube/otelc/configuration/conditions.go b/pkg/controllers/dynakube/otelc/configuration/conditions.go new file mode 100644 index 0000000000..853bd5a929 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/configuration/conditions.go @@ -0,0 +1,3 @@ +package configuration + +const conditionType string = "OTELCConfigurationConfigMap" diff --git a/pkg/controllers/dynakube/otelc/configuration/config.go b/pkg/controllers/dynakube/otelc/configuration/config.go new file mode 100644 index 0000000000..00fe75dbf9 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/configuration/config.go @@ -0,0 +1,7 @@ +package configuration + +import "github.com/Dynatrace/dynatrace-operator/pkg/logd" + +var ( + log = logd.Get().WithName("otelc-config") +) diff --git a/pkg/controllers/dynakube/otelc/configuration/reconciler.go b/pkg/controllers/dynakube/otelc/configuration/reconciler.go new file mode 100644 index 0000000000..9c4341c970 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/configuration/reconciler.go @@ -0,0 +1,140 @@ +package configuration + +import ( + "path/filepath" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + k8sconfigmap "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/configmap" + k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + "golang.org/x/net/context" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Reconciler struct { + client client.Client + apiReader client.Reader + dk *dynakube.DynaKube +} + +func NewReconciler(clt client.Client, + apiReader client.Reader, + dk *dynakube.DynaKube) *Reconciler { + return &Reconciler{ + client: clt, + apiReader: apiReader, + dk: dk, + } +} + +func (r *Reconciler) Reconcile(ctx context.Context) error { + if !r.dk.TelemetryIngest().IsEnabled() { + if meta.FindStatusCondition(*r.dk.Conditions(), conditionType) == nil { + return nil // no condition == nothing is there to clean up + } + + query := k8sconfigmap.Query(r.client, r.apiReader, log) + err := query.Delete(ctx, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: GetConfigMapName(r.dk.Name), Namespace: r.dk.Namespace}}) + + if err != nil { + log.Error(err, "failed to clean-up OTELC configuration configmap") + } + + meta.RemoveStatusCondition(r.dk.Conditions(), conditionType) + + return nil + } + + return r.reconcileConfigMap(ctx) +} + +func (r *Reconciler) reconcileConfigMap(ctx context.Context) error { + query := k8sconfigmap.Query(r.client, r.apiReader, log) + + newConfigMap, err := r.prepareConfigMap() + if err != nil { + return err + } + + changed, err := query.CreateOrUpdate(ctx, newConfigMap) + if err != nil { + conditions.SetKubeApiError(r.dk.Conditions(), conditionType, err) + + return err + } else if changed { + conditions.SetConfigMapOutdated(r.dk.Conditions(), conditionType, newConfigMap.Name) // needed so the timestamp updates, will never actually show up in the status + } + + conditions.SetConfigMapCreatedOrUpdated(r.dk.Conditions(), conditionType, newConfigMap.Name) + + return nil +} + +func (r *Reconciler) prepareConfigMap() (*corev1.ConfigMap, error) { + data, err := r.getData() + if err != nil { + return nil, err + } + + coreLabels := k8slabels.NewCoreLabels(r.dk.Name, k8slabels.OtelCComponentLabel).BuildLabels() + + newSecret, err := k8sconfigmap.Build(r.dk, + GetConfigMapName(r.dk.Name), + data, + k8sconfigmap.SetLabels(coreLabels), + ) + if err != nil { + conditions.SetConfigMapGenFailed(r.dk.Conditions(), conditionType, err) + + return nil, err + } + + return newSecret, err +} + +func (r *Reconciler) getData() (map[string]string, error) { + myPodIp := "${env:MY_POD_IP}" + + options := []otelcgen.Option{ + otelcgen.WithApiToken("${env:" + otelcconsts.EnvDataIngestToken + "}"), + otelcgen.WithExportersEndpoint("${env:DT_ENDPOINT}"), + } + + if r.dk.TelemetryIngest().IsEnabled() && r.dk.TelemetryIngest().Spec.TlsRefName != "" { + options = append(options, otelcgen.WithTLS(filepath.Join(otelcconsts.CustomTlsCertMountPath, consts.TLSCrtDataName), filepath.Join(otelcconsts.CustomTlsCertMountPath, consts.TLSKeyDataName))) + } + + options = append(options, + otelcgen.WithExporters(), + otelcgen.WithProcessors(), + otelcgen.WithReceivers(), + otelcgen.WithExtensions(), + otelcgen.WithServices(), + ) + + config, err := otelcgen.NewConfig(myPodIp, r.dk.TelemetryIngest().GetProtocols(), options...) + if err != nil { + return nil, err + } + + configBytes, err := config.Marshal() + if err != nil { + return nil, err + } + + configMap := map[string]string{ + otelcconsts.ConfigFieldName: string(configBytes), + } + + return configMap, nil +} + +func GetConfigMapName(dkName string) string { + return dkName + otelcconsts.TelemetryCollectorConfigmapSuffix +} diff --git a/pkg/controllers/dynakube/otelc/configuration/reconciler_test.go b/pkg/controllers/dynakube/otelc/configuration/reconciler_test.go new file mode 100644 index 0000000000..2e5bec38d2 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/configuration/reconciler_test.go @@ -0,0 +1,56 @@ +package configuration + +import ( + "context" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +const ( + testDynakubeName = "dynakube" + testNamespaceName = "dynatrace" +) + +func getTestDynakube(telemetryIngestSpec *telemetryingest.Spec) *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakubeName, + Namespace: testNamespaceName, + }, + Spec: dynakube.DynaKubeSpec{ + TelemetryIngest: telemetryIngestSpec, + }, + Status: dynakube.DynaKubeStatus{}, + } +} + +func TestConfigurationConfigMap(t *testing.T) { + t.Run("create configmap if it does not exist", func(t *testing.T) { + mockK8sClient := fake.NewFakeClient() + dk := getTestDynakube(&telemetryingest.Spec{}) + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + configMap := &corev1.ConfigMap{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: GetConfigMapName(dk.Name), Namespace: dk.Namespace}, configMap) + require.NoError(t, err) + + _, ok := configMap.Data[consts.ConfigFieldName] + assert.True(t, ok) + + require.Len(t, dk.Status.Conditions, 1) + assert.Equal(t, conditionType, dk.Status.Conditions[0].Type) + assert.Equal(t, conditions.ConfigMapCreatedOrUpdatedReason, dk.Status.Conditions[0].Reason) + assert.Equal(t, metav1.ConditionTrue, dk.Status.Conditions[0].Status) + }) +} diff --git a/pkg/controllers/dynakube/otelc/consts/consts.go b/pkg/controllers/dynakube/otelc/consts/consts.go new file mode 100644 index 0000000000..db287b800d --- /dev/null +++ b/pkg/controllers/dynakube/otelc/consts/consts.go @@ -0,0 +1,14 @@ +package consts + +const ( + TelemetryApiCredentialsSecretName = "dynatrace-telemetry-api-credentials" + + ConfigFieldName = "telemetry.yaml" + TelemetryCollectorConfigmapSuffix = "-telemetry-collector-config" + + CustomTlsCertMountPath = "/tls/custom/telemetry" + TrustedCAVolumeMountPath = "/tls/custom/cacerts" + TrustedCAVolumePath = TrustedCAVolumeMountPath + "/certs" + + EnvDataIngestToken = "DT_DATA_INGEST_TOKEN" +) diff --git a/pkg/controllers/dynakube/otelc/reconciler.go b/pkg/controllers/dynakube/otelc/reconciler.go index 4ae09df19a..7ae6a0b480 100644 --- a/pkg/controllers/dynakube/otelc/reconciler.go +++ b/pkg/controllers/dynakube/otelc/reconciler.go @@ -5,28 +5,34 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/configuration" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/secret" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/service" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/statefulset" "sigs.k8s.io/controller-runtime/pkg/client" ) type Reconciler struct { - client client.Client - apiReader client.Reader - dk *dynakube.DynaKube - statefulsetReconciler controllers.Reconciler - serviceReconciler *service.Reconciler + client client.Client + apiReader client.Reader + dk *dynakube.DynaKube + statefulsetReconciler controllers.Reconciler + serviceReconciler *service.Reconciler + secretReconciler *secret.Reconciler + configurationReconciler *configuration.Reconciler } type ReconcilerBuilder func(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) controllers.Reconciler func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) controllers.Reconciler { //nolint return &Reconciler{ - client: client, - apiReader: apiReader, - dk: dk, - statefulsetReconciler: statefulset.NewReconciler(client, apiReader, dk), - serviceReconciler: service.NewReconciler(client, apiReader, dk), + client: client, + apiReader: apiReader, + dk: dk, + statefulsetReconciler: statefulset.NewReconciler(client, apiReader, dk), + serviceReconciler: service.NewReconciler(client, apiReader, dk), + secretReconciler: secret.NewReconciler(client, apiReader, dk), + configurationReconciler: configuration.NewReconciler(client, apiReader, dk), } } @@ -36,6 +42,16 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { return err } + err = r.secretReconciler.Reconcile(ctx) + if err != nil { + return err + } + + err = r.configurationReconciler.Reconcile(ctx) + if err != nil { + return err + } + err = r.statefulsetReconciler.Reconcile(ctx) if err != nil { log.Info("failed to reconcile Dynatrace OTELc statefulset") diff --git a/pkg/controllers/dynakube/otelc/secret/conditions.go b/pkg/controllers/dynakube/otelc/secret/conditions.go new file mode 100644 index 0000000000..ca554ad8a1 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/secret/conditions.go @@ -0,0 +1,5 @@ +package secret + +const ( + secretConditionType = "TelemetryIngestApiCredentialsSecret" +) diff --git a/pkg/controllers/dynakube/otelc/secret/config.go b/pkg/controllers/dynakube/otelc/secret/config.go new file mode 100644 index 0000000000..864bf9f281 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/secret/config.go @@ -0,0 +1,7 @@ +package secret + +import "github.com/Dynatrace/dynatrace-operator/pkg/logd" + +var ( + log = logd.Get().WithName("telemetry-ingest-api-credentials-secret") +) diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler.go b/pkg/controllers/dynakube/otelc/secret/reconciler.go new file mode 100644 index 0000000000..275ece8788 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/secret/reconciler.go @@ -0,0 +1,136 @@ +package secret + +import ( + "context" + "fmt" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" + k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Reconciler struct { + client client.Client + apiReader client.Reader + dk *dynakube.DynaKube +} + +type ReconcilerBuilder func(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler + +func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler { + return &Reconciler{ + client: client, + dk: dk, + apiReader: apiReader, + } +} + +func (r *Reconciler) Reconcile(ctx context.Context) error { + if r.dk.TelemetryIngest().IsEnabled() { + return r.ensureTelemetryIngestApiCredentialsSecret(ctx) + } + + return r.removeTelemetryIngestApiCredentialsSecret(ctx) +} + +func (r *Reconciler) ensureTelemetryIngestApiCredentialsSecret(ctx context.Context) error { + query := k8ssecret.Query(r.client, r.apiReader, log) + _, err := query.Get(ctx, types.NamespacedName{Name: consts.TelemetryApiCredentialsSecretName, Namespace: r.dk.Namespace}) + + if err != nil && k8serrors.IsNotFound(err) { + log.Info("creating new secret for telemetry api credentials") + + secretConfig, err := r.generateTelemetryIngestApiCredentialsSecret(consts.TelemetryApiCredentialsSecretName) + + if err != nil { + conditions.SetSecretGenFailed(r.dk.Conditions(), secretConditionType, err) + + return err + } + + _, err = hasher.GenerateHash(secretConfig.Data) + if err != nil { + conditions.SetSecretGenFailed(r.dk.Conditions(), secretConditionType, err) + + return err + } + + err = query.Create(ctx, secretConfig) + if err != nil { + log.Info("could not create secret for telemetry api credentials", "name", secretConfig.Name) + conditions.SetKubeApiError(r.dk.Conditions(), secretConditionType, err) + + return err + } + + conditions.SetSecretCreated(r.dk.Conditions(), secretConditionType, consts.TelemetryApiCredentialsSecretName) + } else if err != nil { + conditions.SetKubeApiError(r.dk.Conditions(), secretConditionType, err) + + return err + } + + return nil +} + +func (r *Reconciler) getDtEndpoint() ([]byte, error) { + tenantUUID, err := r.dk.TenantUUID() + if err != nil { + return nil, err + } + + if r.dk.ActiveGate().IsApiEnabled() { + return []byte(fmt.Sprintf("https://%s-activegate.dynatrace.svc/e/%s/api/v2/otlp", r.dk.Name, tenantUUID)), nil + } + + return []byte(fmt.Sprintf("https://%s.%s/api/v2/otlp", tenantUUID, r.dk.ApiUrlHost())), nil +} + +func (r *Reconciler) generateTelemetryIngestApiCredentialsSecret(name string) (secret *corev1.Secret, err error) { + secretData := make(map[string][]byte) + + dtEndpoint, err := r.getDtEndpoint() + if err != nil { + return nil, err + } + + secretData["DT_ENDPOINT"] = dtEndpoint + + secretConfig, err := k8ssecret.Build(r.dk, + name, + secretData, + k8ssecret.SetLabels(k8slabels.NewCoreLabels(r.dk.Name, k8slabels.OtelCComponentLabel).BuildLabels()), + ) + + if err != nil { + return nil, err + } + + return secretConfig, nil +} + +func (r *Reconciler) removeTelemetryIngestApiCredentialsSecret(ctx context.Context) error { + if meta.FindStatusCondition(*r.dk.Conditions(), secretConditionType) == nil { + return nil // no condition == nothing is there to clean up + } + + query := k8ssecret.Query(r.client, r.apiReader, log) + err := query.Delete(ctx, &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: consts.TelemetryApiCredentialsSecretName, Namespace: r.dk.Namespace}}) + + if err != nil { + log.Error(err, "could not delete apiCredential secret", "name", consts.TelemetryApiCredentialsSecretName) + } + + meta.RemoveStatusCondition(r.dk.Conditions(), secretConditionType) + + return nil +} diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler_test.go b/pkg/controllers/dynakube/otelc/secret/reconciler_test.go new file mode 100644 index 0000000000..0b68d12346 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/secret/reconciler_test.go @@ -0,0 +1,110 @@ +package secret + +import ( + "context" + "testing" + + schemeFake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +const ( + testApiToken = "apiTokenValue" + testTenantUUID = "abc12345" + testKubeSystemUUID = "12345" +) + +func TestSecretCreation(t *testing.T) { + ctx := context.Background() + + t.Run("creates secret if it does not exist", func(t *testing.T) { + dk := createDynaKube(true) + + testSecret, err := secret.Build(&dk, dk.Name, map[string][]byte{ + dtclient.ApiToken: []byte(testApiToken), + }) + require.NoError(t, err) + + clt := fake.NewFakeClient(testSecret) + + r := NewReconciler(clt, clt, &dk) + + err = r.ensureTelemetryIngestApiCredentialsSecret(ctx) + require.NoError(t, err) + + var apiCredsSecret corev1.Secret + err = clt.Get(ctx, types.NamespacedName{Name: consts.TelemetryApiCredentialsSecretName, Namespace: dk.Namespace}, &apiCredsSecret) + require.NoError(t, err) + assert.NotEmpty(t, apiCredsSecret) + require.NotNil(t, meta.FindStatusCondition(*dk.Conditions(), secretConditionType)) + assert.Equal(t, conditions.SecretCreatedReason, meta.FindStatusCondition(*dk.Conditions(), secretConditionType).Reason) + }) + + t.Run("removes secret if exists but we don't need it", func(t *testing.T) { + dk := createDynaKube(false) + conditions.SetSecretCreated(dk.Conditions(), secretConditionType, consts.TelemetryApiCredentialsSecretName) + + objs := []client.Object{ + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: consts.TelemetryApiCredentialsSecretName, + Namespace: dk.Namespace, + }, + }, + } + + clt := schemeFake.NewClient(objs...) + r := NewReconciler(clt, clt, &dk) + + err := r.Reconcile(ctx) + require.NoError(t, err) + + var apiTokenSecret corev1.Secret + err = clt.Get(ctx, types.NamespacedName{Name: consts.TelemetryApiCredentialsSecretName, Namespace: dk.Namespace}, &apiTokenSecret) + + require.Error(t, err) + assert.Empty(t, apiTokenSecret) + }) +} + +func createDynaKube(telemetryIngestEnabled bool) dynakube.DynaKube { + dk := dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-dk", + }, + Spec: dynakube.DynaKubeSpec{}, + Status: dynakube.DynaKubeStatus{ + ActiveGate: activegate.Status{ + ConnectionInfo: communication.ConnectionInfo{ + TenantUUID: testTenantUUID, + }, + VersionStatus: status.VersionStatus{}, + }, + KubeSystemUUID: testKubeSystemUUID, + }, + } + + if telemetryIngestEnabled { + dk.TelemetryIngest().Spec = &telemetryingest.Spec{} + } else { + dk.TelemetryIngest().Spec = nil + } + + return dk +} diff --git a/pkg/controllers/dynakube/otelc/service/reconciler.go b/pkg/controllers/dynakube/otelc/service/reconciler.go index f062718484..50c20bf3aa 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler.go @@ -2,7 +2,7 @@ package service import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/service" @@ -41,11 +41,11 @@ func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.D } func (r *Reconciler) Reconcile(ctx context.Context) error { - if !r.dk.TelemetryService().IsEnabled() { + if !r.dk.TelemetryIngest().IsEnabled() { return r.removeServiceOnce(ctx) } - if r.dk.TelemetryService().ServiceName != "" { + if r.dk.TelemetryIngest().ServiceName != "" { return r.removeServiceOnce(ctx) } @@ -91,7 +91,7 @@ func (r *Reconciler) createOrUpdateService(ctx context.Context) error { return err } - conditions.SetServiceCreated(r.dk.Conditions(), serviceConditionType, r.dk.TelemetryService().GetName()) + conditions.SetServiceCreated(r.dk.Conditions(), serviceConditionType, r.dk.TelemetryIngest().GetName()) return nil } @@ -102,12 +102,12 @@ func (r *Reconciler) buildService() (*corev1.Service, error) { appLabels := labels.NewAppLabels(labels.OtelCComponentLabel, r.dk.Name, labels.OtelCComponentLabel, "") var svcPorts []corev1.ServicePort - if r.dk.TelemetryService().IsEnabled() && r.dk.Spec.TelemetryService.ServiceName == "" { - svcPorts = buildServicePortList(r.dk.TelemetryService().GetProtocols()) + if r.dk.TelemetryIngest().IsEnabled() && r.dk.Spec.TelemetryIngest.ServiceName == "" { + svcPorts = buildServicePortList(r.dk.TelemetryIngest().GetProtocols()) } return service.Build(r.dk, - r.dk.TelemetryService().GetName(), + r.dk.TelemetryIngest().GetName(), appLabels.BuildMatchLabels(), svcPorts, service.SetLabels(coreLabels.BuildLabels()), @@ -115,7 +115,7 @@ func (r *Reconciler) buildService() (*corev1.Service, error) { ) } -func buildServicePortList(protocols []telemetryservice.Protocol) []corev1.ServicePort { +func buildServicePortList(protocols []otelcgen.Protocol) []corev1.ServicePort { if len(protocols) == 0 { return nil } @@ -124,14 +124,14 @@ func buildServicePortList(protocols []telemetryservice.Protocol) []corev1.Servic for _, protocol := range protocols { switch protocol { - case telemetryservice.ZipkinProtocol: + case otelcgen.ZipkinProtocol: svcPorts = append(svcPorts, corev1.ServicePort{ Name: portNameZipkin, Port: 9411, Protocol: corev1.ProtocolTCP, TargetPort: intstr.FromInt32(9411), }) - case telemetryservice.OtlpProtocol: + case otelcgen.OtlpProtocol: svcPorts = append(svcPorts, corev1.ServicePort{ Name: portNameOtlpGrpc, @@ -145,7 +145,7 @@ func buildServicePortList(protocols []telemetryservice.Protocol) []corev1.Servic Protocol: corev1.ProtocolTCP, TargetPort: intstr.FromInt32(4318), }) - case telemetryservice.JaegerProtocol: + case otelcgen.JaegerProtocol: svcPorts = append(svcPorts, corev1.ServicePort{ Name: portNameJaegerGrpc, @@ -171,7 +171,7 @@ func buildServicePortList(protocols []telemetryservice.Protocol) []corev1.Servic Protocol: corev1.ProtocolTCP, TargetPort: intstr.FromInt32(14268), }) - case telemetryservice.StatsdProtocol: + case otelcgen.StatsdProtocol: svcPorts = append(svcPorts, corev1.ServicePort{ Name: portNameStatsd, diff --git a/pkg/controllers/dynakube/otelc/service/reconciler_test.go b/pkg/controllers/dynakube/otelc/service/reconciler_test.go index 961f1c487a..e405f6bf81 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler_test.go @@ -5,7 +5,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -22,14 +23,14 @@ const ( testServiceName = "test-service-name" ) -func getTestDynakube(telemetryServiceSpec *telemetryservice.Spec) *dynakube.DynaKube { +func getTestDynakube(telemetryIngestSpec *telemetryingest.Spec) *dynakube.DynaKube { return &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Name: testDynakubeName, Namespace: testNamespaceName, }, Spec: dynakube.DynaKubeSpec{ - TelemetryService: telemetryServiceSpec, + TelemetryIngest: telemetryIngestSpec, }, Status: dynakube.DynaKubeStatus{}, } @@ -38,24 +39,23 @@ func getTestDynakube(telemetryServiceSpec *telemetryservice.Spec) *dynakube.Dyna func TestService(t *testing.T) { t.Run("create service if it does not exist", func(t *testing.T) { mockK8sClient := fake.NewFakeClient() - dk := getTestDynakube(&telemetryservice.Spec{}) + dk := getTestDynakube(&telemetryingest.Spec{}) err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) service := &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) require.NoError(t, err) require.Len(t, service.Spec.Ports, 8) assert.Equal(t, portNameOtlpGrpc, service.Spec.Ports[0].Name) assert.Equal(t, portNameOtlpHttp, service.Spec.Ports[1].Name) - assert.Equal(t, portNameZipkin, service.Spec.Ports[2].Name) - assert.Equal(t, portNameJaegerGrpc, service.Spec.Ports[3].Name) - assert.Equal(t, portNameJaegerThriftBinary, service.Spec.Ports[4].Name) - assert.Equal(t, portNameJaegerThriftCompact, service.Spec.Ports[5].Name) - assert.Equal(t, portNameJaegerThriftHttp, service.Spec.Ports[6].Name) - assert.Equal(t, portNameStatsd, service.Spec.Ports[7].Name) - + assert.Equal(t, portNameJaegerGrpc, service.Spec.Ports[2].Name) + assert.Equal(t, portNameJaegerThriftBinary, service.Spec.Ports[3].Name) + assert.Equal(t, portNameJaegerThriftCompact, service.Spec.Ports[4].Name) + assert.Equal(t, portNameJaegerThriftHttp, service.Spec.Ports[5].Name) + assert.Equal(t, portNameStatsd, service.Spec.Ports[6].Name) + assert.Equal(t, portNameZipkin, service.Spec.Ports[7].Name) require.Len(t, dk.Status.Conditions, 1) assert.Equal(t, serviceConditionType, dk.Status.Conditions[0].Type) assert.Equal(t, conditions.ServiceCreatedReason, dk.Status.Conditions[0].Reason) @@ -72,7 +72,7 @@ func TestService(t *testing.T) { mockK8sClient := fake.NewFakeClient() err := mockK8sClient.Create(context.Background(), &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: dk.TelemetryService().GetName(), + Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace, }, }) @@ -82,7 +82,7 @@ func TestService(t *testing.T) { require.NoError(t, err) service := &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) require.Error(t, err) assert.True(t, k8serrors.IsNotFound(err)) @@ -90,17 +90,17 @@ func TestService(t *testing.T) { }) t.Run("create service for specified protocols", func(t *testing.T) { mockK8sClient := fake.NewFakeClient() - dk := getTestDynakube(&telemetryservice.Spec{ + dk := getTestDynakube(&telemetryingest.Spec{ Protocols: []string{ - string(telemetryservice.ZipkinProtocol), - string(telemetryservice.StatsdProtocol), + string(otelcgen.ZipkinProtocol), + string(otelcgen.StatsdProtocol), }, }) err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) service := &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) require.NoError(t, err) require.Len(t, service.Spec.Ports, 2) @@ -114,7 +114,7 @@ func TestService(t *testing.T) { }) t.Run("custom service", func(t *testing.T) { mockK8sClient := fake.NewFakeClient() - dk := getTestDynakube(&telemetryservice.Spec{ + dk := getTestDynakube(&telemetryingest.Spec{ ServiceName: testServiceName, }) err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) @@ -129,12 +129,12 @@ func TestService(t *testing.T) { }) t.Run("update from default service to custom service", func(t *testing.T) { mockK8sClient := fake.NewFakeClient() - dk := getTestDynakube(&telemetryservice.Spec{}) + dk := getTestDynakube(&telemetryingest.Spec{}) err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) service := &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) require.NoError(t, err) require.Len(t, dk.Status.Conditions, 1) @@ -143,14 +143,14 @@ func TestService(t *testing.T) { assert.Equal(t, metav1.ConditionTrue, dk.Status.Conditions[0].Status) // update - dk.Spec.TelemetryService = &telemetryservice.Spec{ + dk.Spec.TelemetryIngest = &telemetryingest.Spec{ ServiceName: testServiceName, } err = NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) service = &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryService().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) require.Error(t, err) assert.True(t, k8serrors.IsNotFound(err)) diff --git a/pkg/controllers/dynakube/otelc/statefulset/container.go b/pkg/controllers/dynakube/otelc/statefulset/container.go index 64c1764f43..b3269861bb 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/container.go +++ b/pkg/controllers/dynakube/otelc/statefulset/container.go @@ -36,7 +36,21 @@ func getContainer(dk *dynakube.DynaKube) corev1.Container { SecurityContext: buildSecurityContext(), Env: getEnvs(dk), Resources: dk.Spec.Templates.OpenTelemetryCollector.Resources, - Args: []string{fmt.Sprintf("--config=eec://%s:%d/otcconfig/prometheusMetrics#refresh-interval=5s&auth-file=%s", dk.ExtensionsServiceNameFQDN(), consts.OtelCollectorComPort, otelcSecretTokenFilePath)}, + Args: buildArgs(dk), VolumeMounts: buildContainerVolumeMounts(dk), } } + +func buildArgs(dk *dynakube.DynaKube) []string { + args := []string{} + + if dk.IsExtensionsEnabled() { + args = append(args, fmt.Sprintf("--config=eec://%s:%d/otcconfig/prometheusMetrics#refresh-interval=5s&auth-file=%s", dk.ExtensionsServiceNameFQDN(), consts.OtelCollectorComPort, otelcSecretTokenFilePath)) + } + + if dk.TelemetryIngest().IsEnabled() { + args = append(args, "--config=file:///config/telemetry.yaml") + } + + return args +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/container_test.go b/pkg/controllers/dynakube/otelc/statefulset/container_test.go new file mode 100644 index 0000000000..aba058924d --- /dev/null +++ b/pkg/controllers/dynakube/otelc/statefulset/container_test.go @@ -0,0 +1,40 @@ +package statefulset + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/stretchr/testify/assert" +) + +func TestContainer(t *testing.T) { + t.Run("only TelemetryIngest enabled", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.TelemetryIngest = &telemetryingest.Spec{} + + assert.Equal(t, []string{"--config=file:///config/telemetry.yaml"}, buildArgs(dk)) + }) + + t.Run("only EEC enabled", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + assert.Equal( + t, + []string{"--config=eec://dynakube-extensions-controller.dynatrace:14599/otcconfig/prometheusMetrics#refresh-interval=5s&auth-file=/secrets/tokens/otelc.token"}, + buildArgs(dk), + ) + }) + + t.Run("TelemetryIngest and EEC enabled", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + dk.Spec.TelemetryIngest = &telemetryingest.Spec{} + + assert.Equal( + t, + []string{ + "--config=eec://dynakube-extensions-controller.dynatrace:14599/otcconfig/prometheusMetrics#refresh-interval=5s&auth-file=/secrets/tokens/otelc.token", + "--config=file:///config/telemetry.yaml", + }, + buildArgs(dk), + ) + }) +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/env.go b/pkg/controllers/dynakube/otelc/statefulset/env.go index 7eeb417491..f05987589a 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env.go @@ -4,7 +4,9 @@ import ( "strconv" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + otelcConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" corev1 "k8s.io/api/core/v1" ) @@ -19,6 +21,7 @@ const ( envShardId = "SHARD_ID" envPodNamePrefix = "POD_NAME_PREFIX" envPodName = "POD_NAME" + envMyPodIP = "MY_POD_IP" envOTLPgrpcPort = "OTLP_GRPC_PORT" envOTLPhttpPort = "OTLP_HTTP_PORT" envEECDStoken = "EEC_DS_TOKEN" @@ -26,6 +29,7 @@ const ( envK8sClusterName = "K8S_CLUSTER_NAME" envK8sClusterUid = "K8S_CLUSTER_UID" envDTentityK8sCluster = "DT_ENTITY_KUBERNETES_CLUSTER" + envDTendpoint = "DT_ENDPOINT" // certDirEnv is the environment variable that identifies which directory // to check for SSL certificate files. If set, this overrides the system default. // It is a colon separated list of directories. @@ -34,8 +38,6 @@ const ( envEECcontrollerTLS = "EXTENSIONS_CONTROLLER_TLS" // Volume names and paths - trustedCAVolumeMountPath = "/tls/custom/cacerts" - trustedCAVolumePath = trustedCAVolumeMountPath + "/certs" customEecTLSCertificatePath = "/tls/custom/eec" customEecTLSCertificateFullPath = customEecTLSCertificatePath + "/" + consts.TLSCrtDataName ) @@ -43,7 +45,7 @@ const ( func getEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { envs := []corev1.EnvVar{ {Name: envShards, Value: strconv.Itoa(int(getReplicas(dk)))}, - {Name: envPodNamePrefix, Value: dk.ExtensionsCollectorStatefulsetName()}, + {Name: envPodNamePrefix, Value: dk.OtelCollectorStatefulsetName()}, {Name: envPodName, ValueFrom: &corev1.EnvVarSource{ FieldRef: &corev1.ObjectFieldSelector{ FieldPath: "metadata.labels['statefulset.kubernetes.io/pod-name']", @@ -58,23 +60,50 @@ func getEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { }, {Name: envOTLPgrpcPort, Value: defaultOLTPgrpcPort}, {Name: envOTLPhttpPort, Value: defaultOLTPhttpPort}, - {Name: envEECDStoken, ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, - Key: consts.OtelcTokenSecretKey, - }, - }, - }, - {Name: envCertDir, Value: customEecTLSCertificatePath}, {Name: envK8sClusterName, Value: dk.Name}, {Name: envK8sClusterUid, Value: dk.Status.KubeSystemUUID}, {Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, } - if dk.Spec.TrustedCAs != "" { - envs = append(envs, corev1.EnvVar{Name: envTrustedCAs, Value: trustedCAVolumePath}) + + if dk.IsExtensionsEnabled() { + envs = append( + envs, + corev1.EnvVar{Name: envEECDStoken, ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, + Key: consts.OtelcTokenSecretKey, + }}, + }, + corev1.EnvVar{Name: envCertDir, Value: customEecTLSCertificatePath}, + corev1.EnvVar{Name: envEECcontrollerTLS, Value: customEecTLSCertificateFullPath}, + ) + } + + if dk.TelemetryIngest().IsEnabled() { + envs = append(envs, + corev1.EnvVar{Name: envDTendpoint, ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: otelcConsts.TelemetryApiCredentialsSecretName}, + Key: envDTendpoint, + }, + }}, + corev1.EnvVar{Name: envMyPodIP, ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "status.podIP", + }, + }}, + corev1.EnvVar{Name: otelcConsts.EnvDataIngestToken, ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: dk.Tokens()}, + Key: dynatrace.DataIngestToken, + }, + }}, + ) } - envs = append(envs, corev1.EnvVar{Name: envEECcontrollerTLS, Value: customEecTLSCertificateFullPath}) + if dk.Spec.TrustedCAs != "" { + envs = append(envs, corev1.EnvVar{Name: envTrustedCAs, Value: otelcConsts.TrustedCAVolumePath}) + } return envs } diff --git a/pkg/controllers/dynakube/otelc/statefulset/env_test.go b/pkg/controllers/dynakube/otelc/statefulset/env_test.go new file mode 100644 index 0000000000..c459c57000 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/statefulset/env_test.go @@ -0,0 +1,108 @@ +package statefulset + +import ( + "fmt" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + otelcConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" +) + +func TestEnvironmentVariables(t *testing.T) { + t.Run("environment variables with Extensions enabled", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + + statefulSet := getStatefulset(t, dk) + + assert.Equal(t, corev1.EnvVar{Name: envShards, Value: fmt.Sprintf("%d", getReplicas(dk))}, statefulSet.Spec.Template.Spec.Containers[0].Env[0]) + assert.Equal(t, corev1.EnvVar{Name: envPodNamePrefix, Value: dk.Name + "-extensions-collector"}, statefulSet.Spec.Template.Spec.Containers[0].Env[1]) + assert.Equal(t, corev1.EnvVar{Name: envPodName, ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.labels['statefulset.kubernetes.io/pod-name']", + }, + }}, statefulSet.Spec.Template.Spec.Containers[0].Env[2]) + assert.Equal(t, corev1.EnvVar{Name: envShardId, ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.labels['apps.kubernetes.io/pod-index']", + }, + }}, statefulSet.Spec.Template.Spec.Containers[0].Env[3]) + assert.Equal(t, corev1.EnvVar{Name: envOTLPgrpcPort, Value: defaultOLTPgrpcPort}, statefulSet.Spec.Template.Spec.Containers[0].Env[4]) + assert.Equal(t, corev1.EnvVar{Name: envOTLPhttpPort, Value: defaultOLTPhttpPort}, statefulSet.Spec.Template.Spec.Containers[0].Env[5]) + assert.Equal(t, corev1.EnvVar{Name: envK8sClusterName, Value: dk.Name}, statefulSet.Spec.Template.Spec.Containers[0].Env[6]) + assert.Equal(t, corev1.EnvVar{Name: envK8sClusterUid, Value: dk.Status.KubeSystemUUID}, statefulSet.Spec.Template.Spec.Containers[0].Env[7]) + assert.Equal(t, corev1.EnvVar{Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, statefulSet.Spec.Template.Spec.Containers[0].Env[8]) + assert.Equal(t, corev1.EnvVar{Name: envEECDStoken, ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, + Key: consts.OtelcTokenSecretKey, + }, + }}, statefulSet.Spec.Template.Spec.Containers[0].Env[9]) + assert.Equal(t, corev1.EnvVar{Name: envCertDir, Value: customEecTLSCertificatePath}, statefulSet.Spec.Template.Spec.Containers[0].Env[10]) + }) + t.Run("environment variables with trustedCA", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + dk.Spec.TrustedCAs = "test-trusted-ca" + + statefulSet := getStatefulset(t, dk) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envTrustedCAs, Value: otelcConsts.TrustedCAVolumePath}) + }) + t.Run("environment variables with custom EEC TLS certificate", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + dk.Spec.Templates.ExtensionExecutionController.TlsRefName = "test-tls-ca" + + statefulSet := getStatefulset(t, dk) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envEECcontrollerTLS, Value: customEecTLSCertificateFullPath}) + }) + t.Run("environment variables for open signal configuration", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.TelemetryIngest = &telemetryingest.Spec{} + + dataIngestToken := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &dataIngestToken, &configMap) + assert.Len(t, statefulSet.Spec.Template.Spec.Containers[0].Env, 12) + + assert.Equal(t, corev1.EnvVar{Name: envShards, Value: fmt.Sprintf("%d", getReplicas(dk))}, statefulSet.Spec.Template.Spec.Containers[0].Env[0]) + assert.Equal(t, corev1.EnvVar{Name: envPodNamePrefix, Value: dk.Name + "-extensions-collector"}, statefulSet.Spec.Template.Spec.Containers[0].Env[1]) + assert.Equal(t, corev1.EnvVar{Name: envPodName, ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.labels['statefulset.kubernetes.io/pod-name']", + }, + }}, statefulSet.Spec.Template.Spec.Containers[0].Env[2]) + assert.Equal(t, corev1.EnvVar{Name: envShardId, ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.labels['apps.kubernetes.io/pod-index']", + }, + }}, statefulSet.Spec.Template.Spec.Containers[0].Env[3]) + assert.Equal(t, corev1.EnvVar{Name: envOTLPgrpcPort, Value: defaultOLTPgrpcPort}, statefulSet.Spec.Template.Spec.Containers[0].Env[4]) + assert.Equal(t, corev1.EnvVar{Name: envOTLPhttpPort, Value: defaultOLTPhttpPort}, statefulSet.Spec.Template.Spec.Containers[0].Env[5]) + assert.Equal(t, corev1.EnvVar{Name: envK8sClusterName, Value: dk.Name}, statefulSet.Spec.Template.Spec.Containers[0].Env[6]) + assert.Equal(t, corev1.EnvVar{Name: envK8sClusterUid, Value: dk.Status.KubeSystemUUID}, statefulSet.Spec.Template.Spec.Containers[0].Env[7]) + assert.Equal(t, corev1.EnvVar{Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, statefulSet.Spec.Template.Spec.Containers[0].Env[8]) + + assert.Equal(t, corev1.EnvVar{Name: envDTendpoint, ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: otelcConsts.TelemetryApiCredentialsSecretName}, + Key: envDTendpoint, + }, + }}, statefulSet.Spec.Template.Spec.Containers[0].Env[9]) + assert.Equal(t, corev1.EnvVar{Name: envMyPodIP, ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "status.podIP", + }, + }}, statefulSet.Spec.Template.Spec.Containers[0].Env[10]) + + assert.Equal(t, corev1.EnvVar{Name: otelcConsts.EnvDataIngestToken, ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: dk.Tokens()}, + Key: dynatrace.DataIngestToken, + }, + }}, statefulSet.Spec.Template.Spec.Containers[0].Env[11]) + }) +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go index bc7a903585..aa7550bf1b 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go @@ -5,13 +5,17 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/configuration" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/configmap" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/statefulset" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/topology" + "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" @@ -20,8 +24,9 @@ import ( ) const ( - serviceAccountName = "dynatrace-opentelemetry-collector" - annotationTelemetryServiceSecretHash = api.InternalFlagPrefix + "telemetry-service-secret-hash" + serviceAccountName = "dynatrace-opentelemetry-collector" + annotationTelemetryIngestSecretHash = api.InternalFlagPrefix + "telemetry-ingest-secret-hash" + annotationTelemetryIngestConfigurationConfigMapHash = api.InternalFlagPrefix + "telemetry-ingest-config-hash" ) type Reconciler struct { @@ -41,15 +46,17 @@ func NewReconciler(clt client.Client, } func (r *Reconciler) Reconcile(ctx context.Context) error { - if !r.dk.IsExtensionsEnabled() { + if r.dk.IsExtensionsEnabled() || r.dk.TelemetryIngest().IsEnabled() { + return r.createOrUpdateStatefulset(ctx) + } else { // do cleanup or if meta.FindStatusCondition(*r.dk.Conditions(), conditionType) == nil { return nil } defer meta.RemoveStatusCondition(r.dk.Conditions(), conditionType) - sts, err := statefulset.Build(r.dk, r.dk.ExtensionsCollectorStatefulsetName(), corev1.Container{}) + sts, err := statefulset.Build(r.dk, r.dk.OtelCollectorStatefulsetName(), corev1.Container{}) if err != nil { - log.Error(err, "could not build "+r.dk.ExtensionsCollectorStatefulsetName()+" during cleanup") + log.Error(err, "could not build "+r.dk.OtelCollectorStatefulsetName()+" during cleanup") return err } @@ -57,18 +64,27 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { err = statefulset.Query(r.client, r.apiReader, log).Delete(ctx, sts) if err != nil { - log.Error(err, "failed to clean up "+r.dk.ExtensionsCollectorStatefulsetName()+" statufulset") + log.Error(err, "failed to clean up "+r.dk.OtelCollectorStatefulsetName()+" statufulset") return nil } return nil } - - return r.createOrUpdateStatefulset(ctx) } func (r *Reconciler) createOrUpdateStatefulset(ctx context.Context) error { + if r.dk.TelemetryIngest().IsEnabled() { + if !r.checkDataIngestTokenExists(ctx) { + msg := "data ingest token is missing, but it's required for otel controller" + conditions.SetDataIngestTokenMissing(r.dk.Conditions(), dynakube.TokenConditionType, msg) + + log.Error(errors.New(msg), "could not create or update statefulset") + + return nil + } + } + appLabels := buildAppLabels(r.dk.Name) templateAnnotations, err := r.buildTemplateAnnotations(ctx) @@ -81,7 +97,7 @@ func (r *Reconciler) createOrUpdateStatefulset(ctx context.Context) error { topologySpreadConstraints = r.dk.Spec.Templates.OpenTelemetryCollector.TopologySpreadConstraints } - sts, err := statefulset.Build(r.dk, r.dk.ExtensionsCollectorStatefulsetName(), getContainer(r.dk), + sts, err := statefulset.Build(r.dk, r.dk.OtelCollectorStatefulsetName(), getContainer(r.dk), statefulset.SetReplicas(getReplicas(r.dk)), statefulset.SetPodManagementPolicy(appsv1.ParallelPodManagement), statefulset.SetAllLabels(appLabels.BuildLabels(), appLabels.BuildMatchLabels(), appLabels.BuildLabels(), r.dk.Spec.Templates.OpenTelemetryCollector.Labels), @@ -110,7 +126,7 @@ func (r *Reconciler) createOrUpdateStatefulset(ctx context.Context) error { _, err = statefulset.Query(r.client, r.apiReader, log).WithOwner(r.dk).CreateOrUpdate(ctx, sts) if err != nil { - log.Info("failed to create/update " + r.dk.ExtensionsCollectorStatefulsetName() + " statefulset") + log.Info("failed to create/update " + r.dk.OtelCollectorStatefulsetName() + " statefulset") conditions.SetKubeApiError(r.dk.Conditions(), conditionType, err) return err @@ -124,24 +140,35 @@ func (r *Reconciler) createOrUpdateStatefulset(ctx context.Context) error { func (r *Reconciler) buildTemplateAnnotations(ctx context.Context) (map[string]string, error) { templateAnnotations := map[string]string{} - if r.dk.Spec.Templates.OpenTelemetryCollector.Annotations != nil { - templateAnnotations = r.dk.Spec.Templates.OpenTelemetryCollector.Annotations - } + if r.dk.IsExtensionsEnabled() { + if r.dk.Spec.Templates.OpenTelemetryCollector.Annotations != nil { + templateAnnotations = r.dk.Spec.Templates.OpenTelemetryCollector.Annotations + } - tlsSecretHash, err := r.calculateSecretHash(ctx, r.dk.ExtensionsTLSSecretName()) - if err != nil { - return nil, err + tlsSecretHash, err := r.calculateSecretHash(ctx, r.dk.ExtensionsTLSSecretName()) + if err != nil { + return nil, err + } + + templateAnnotations[api.AnnotationExtensionsSecretHash] = tlsSecretHash } - templateAnnotations[api.AnnotationExtensionsSecretHash] = tlsSecretHash + if r.dk.TelemetryIngest().IsEnabled() && r.dk.TelemetryIngest().Spec.TlsRefName != "" { + tlsSecretHash, err := r.calculateSecretHash(ctx, r.dk.TelemetryIngest().Spec.TlsRefName) + if err != nil { + return nil, err + } + + templateAnnotations[annotationTelemetryIngestSecretHash] = tlsSecretHash + } - if r.dk.TelemetryService().IsEnabled() && r.dk.TelemetryService().Spec.TlsRefName != "" { - tlsSecretHash, err = r.calculateSecretHash(ctx, r.dk.TelemetryService().Spec.TlsRefName) + if r.dk.TelemetryIngest().IsEnabled() { + configConfigMapHash, err := r.calculateConfigMapHash(ctx, configuration.GetConfigMapName(r.dk.Name)) if err != nil { return nil, err } - templateAnnotations[annotationTelemetryServiceSecretHash] = tlsSecretHash + templateAnnotations[annotationTelemetryIngestConfigurationConfigMapHash] = configConfigMapHash } return templateAnnotations, nil @@ -166,6 +193,36 @@ func (r *Reconciler) calculateSecretHash(ctx context.Context, secretName string) return tlsSecretHash, nil } +func (r *Reconciler) calculateConfigMapHash(ctx context.Context, configMapName string) (string, error) { + query := configmap.Query(r.client, r.client, log) + + configConfigMap, err := query.Get(ctx, types.NamespacedName{ + Name: configMapName, + Namespace: r.dk.Namespace, + }) + if err != nil { + return "", err + } + + configConfigMaptHash, err := hasher.GenerateHash(configConfigMap.Data) + if err != nil { + return "", err + } + + return configConfigMaptHash, nil +} + +func (r *Reconciler) checkDataIngestTokenExists(ctx context.Context) bool { + tokenReader := token.NewReader(r.apiReader, r.dk) + + tokens, err := tokenReader.ReadTokens(ctx) + if err != nil { + return false + } + + return token.CheckForDataIngestToken(tokens) +} + func getReplicas(dk *dynakube.DynaKube) int32 { if dk.Spec.Templates.OpenTelemetryCollector.Replicas != nil { return *dk.Spec.Templates.OpenTelemetryCollector.Replicas @@ -194,7 +251,7 @@ func buildAppLabels(dkName string) *labels.AppLabels { // TODO: when version is available version := "0.0.0" - return labels.NewAppLabels(labels.CollectorComponentLabel, dkName, labels.CollectorComponentLabel, version) + return labels.NewAppLabels(labels.OtelCComponentLabel, dkName, labels.OtelCComponentLabel, version) } func buildAffinity() corev1.Affinity { diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go index 8d3a0c0dbf..43e98a1851 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go @@ -2,14 +2,14 @@ package statefulset import ( "context" - "fmt" "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" + dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/topology" @@ -23,22 +23,21 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) const ( - testDynakubeName = "dynakube" - testNamespaceName = "dynatrace" - testOtelPullSecret = "otelc-pull-secret" - testTelemetryServiceSecret = "test-ts-secret" + testDynakubeName = "dynakube" + testNamespaceName = "dynatrace" + testOtelPullSecret = "otelc-pull-secret" + testTelemetryIngestSecret = "test-ts-secret" ) func TestReconcile(t *testing.T) { ctx := context.Background() t.Run("Create and update works with minimal setup", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() mockK8sClient := fake.NewClient() mockK8sClient = mockTLSSecret(t, mockK8sClient, dk) @@ -60,18 +59,18 @@ func TestReconcile(t *testing.T) { var sts appsv1.StatefulSet err = mockK8sClient.Get(ctx, types.NamespacedName{ - Name: dk.ExtensionsCollectorStatefulsetName(), + Name: dk.OtelCollectorStatefulsetName(), Namespace: dk.Namespace, }, &sts) require.False(t, k8serrors.IsNotFound(err)) assert.NotEmpty(t, sts) }) t.Run("Only runs when required, and cleans up condition + statefulset", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() dk.Spec.Extensions = nil previousSts := appsv1.StatefulSet{} - previousSts.Name = dk.ExtensionsCollectorStatefulsetName() + previousSts.Name = dk.OtelCollectorStatefulsetName() previousSts.Namespace = dk.Namespace mockK8sClient := fake.NewClient(&previousSts) mockK8sClient = mockTLSSecret(t, mockK8sClient, dk) @@ -86,7 +85,7 @@ func TestReconcile(t *testing.T) { var sts appsv1.StatefulSet err = mockK8sClient.Get(ctx, types.NamespacedName{ - Name: dk.ExtensionsCollectorStatefulsetName(), + Name: dk.OtelCollectorStatefulsetName(), Namespace: dk.Namespace, }, &sts) require.True(t, k8serrors.IsNotFound(err)) @@ -95,7 +94,7 @@ func TestReconcile(t *testing.T) { func TestSecretHashAnnotation(t *testing.T) { t.Run("annotation is set with self-signed tls secret", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() dk.Spec.Templates.ExtensionExecutionController.TlsRefName = "" statefulSet := getStatefulset(t, dk) @@ -103,7 +102,7 @@ func TestSecretHashAnnotation(t *testing.T) { assert.NotEmpty(t, statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash]) }) t.Run("annotation is set with tlsRefName", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() dk.Spec.Templates.ExtensionExecutionController.TlsRefName = "dummy-secret" statefulSet := getStatefulset(t, dk) @@ -112,7 +111,7 @@ func TestSecretHashAnnotation(t *testing.T) { }) t.Run("annotation is updated when TLS Secret gets updated", func(t *testing.T) { statefulSet := &appsv1.StatefulSet{} - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() // first reconcile a basic setup - TLS Secret gets created mockK8sClient := fake.NewClient(dk) @@ -122,7 +121,7 @@ func TestSecretHashAnnotation(t *testing.T) { err := reconciler.Reconcile(context.Background()) require.NoError(t, err) - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.OtelCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) originalSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash] @@ -134,7 +133,7 @@ func TestSecretHashAnnotation(t *testing.T) { err = reconciler.Reconcile(context.Background()) require.NoError(t, err) - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.OtelCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) resultingSecretHash := statefulSet.Spec.Template.Annotations[api.AnnotationExtensionsSecretHash] @@ -146,13 +145,13 @@ func TestSecretHashAnnotation(t *testing.T) { func TestStatefulsetBase(t *testing.T) { t.Run("replicas", func(t *testing.T) { - statefulSet := getStatefulset(t, getTestDynakube()) + statefulSet := getStatefulset(t, getTestDynakubeWithExtensions()) assert.Equal(t, int32(1), *statefulSet.Spec.Replicas) }) t.Run("pod management policy", func(t *testing.T) { - statefulSet := getStatefulset(t, getTestDynakube()) + statefulSet := getStatefulset(t, getTestDynakubeWithExtensions()) assert.Equal(t, appsv1.ParallelPodManagement, statefulSet.Spec.PodManagementPolicy) }) @@ -160,7 +159,7 @@ func TestStatefulsetBase(t *testing.T) { func TestServiceAccountName(t *testing.T) { t.Run("serviceAccountName is set", func(t *testing.T) { - statefulSet := getStatefulset(t, getTestDynakube()) + statefulSet := getStatefulset(t, getTestDynakubeWithExtensions()) assert.Equal(t, serviceAccountName, statefulSet.Spec.Template.Spec.ServiceAccountName) assert.Equal(t, serviceAccountName, statefulSet.Spec.Template.Spec.DeprecatedServiceAccount) @@ -169,14 +168,14 @@ func TestServiceAccountName(t *testing.T) { func TestTopologySpreadConstraints(t *testing.T) { t.Run("the default TopologySpreadConstraints", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() statefulSet := getStatefulset(t, dk) appLabels := buildAppLabels(dk.Name) assert.Equal(t, topology.MaxOnePerNode(appLabels), statefulSet.Spec.Template.Spec.TopologySpreadConstraints) }) t.Run("custom TopologySpreadConstraints", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() customTopologySpreadConstraints := []corev1.TopologySpreadConstraint{ { @@ -199,59 +198,9 @@ func TestTopologySpreadConstraints(t *testing.T) { }) } -func TestEnvironmentVariables(t *testing.T) { - t.Run("environment variables", func(t *testing.T) { - dk := getTestDynakube() - - statefulSet := getStatefulset(t, dk) - - assert.Equal(t, corev1.EnvVar{Name: envShards, Value: fmt.Sprintf("%d", getReplicas(dk))}, statefulSet.Spec.Template.Spec.Containers[0].Env[0]) - assert.Equal(t, corev1.EnvVar{Name: envPodNamePrefix, Value: dk.Name + "-extensions-collector"}, statefulSet.Spec.Template.Spec.Containers[0].Env[1]) - assert.Equal(t, corev1.EnvVar{Name: envPodName, ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.labels['statefulset.kubernetes.io/pod-name']", - }, - }}, statefulSet.Spec.Template.Spec.Containers[0].Env[2]) - assert.Equal(t, corev1.EnvVar{Name: envShardId, ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.labels['apps.kubernetes.io/pod-index']", - }, - }}, statefulSet.Spec.Template.Spec.Containers[0].Env[3]) - assert.Equal(t, corev1.EnvVar{Name: envOTLPgrpcPort, Value: defaultOLTPgrpcPort}, statefulSet.Spec.Template.Spec.Containers[0].Env[4]) - assert.Equal(t, corev1.EnvVar{Name: envOTLPhttpPort, Value: defaultOLTPhttpPort}, statefulSet.Spec.Template.Spec.Containers[0].Env[5]) - assert.Equal(t, corev1.EnvVar{Name: envEECDStoken, ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: dk.ExtensionsTokenSecretName()}, - Key: consts.OtelcTokenSecretKey, - }, - }}, statefulSet.Spec.Template.Spec.Containers[0].Env[6]) - assert.Equal(t, corev1.EnvVar{Name: envCertDir, Value: customEecTLSCertificatePath}, statefulSet.Spec.Template.Spec.Containers[0].Env[7]) - assert.Equal(t, corev1.EnvVar{Name: envK8sClusterName, Value: dk.Name}, statefulSet.Spec.Template.Spec.Containers[0].Env[8]) - assert.Equal(t, corev1.EnvVar{Name: envK8sClusterUid, Value: dk.Status.KubeSystemUUID}, statefulSet.Spec.Template.Spec.Containers[0].Env[9]) - assert.Equal(t, corev1.EnvVar{Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, statefulSet.Spec.Template.Spec.Containers[0].Env[10]) - }) - t.Run("environment variables with trustedCA", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.TrustedCAs = "test-trusted-ca" - - statefulSet := getStatefulset(t, dk) - - assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envTrustedCAs, Value: trustedCAVolumePath}) - }) - - t.Run("environment variables with custom EEC TLS certificate", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.Templates.ExtensionExecutionController.TlsRefName = "test-tls-ca" - - statefulSet := getStatefulset(t, dk) - - assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envEECcontrollerTLS, Value: customEecTLSCertificateFullPath}) - }) -} - func TestAffinity(t *testing.T) { t.Run("affinity", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() statefulSet := getStatefulset(t, dk) expectedAffinity := node.Affinity() @@ -262,13 +211,13 @@ func TestAffinity(t *testing.T) { func TestImagePullSecrets(t *testing.T) { t.Run("the default image pull secret only", func(t *testing.T) { - statefulSet := getStatefulset(t, getTestDynakube()) + statefulSet := getStatefulset(t, getTestDynakubeWithExtensions()) assert.Len(t, statefulSet.Spec.Template.Spec.ImagePullSecrets, 1) }) t.Run("custom pull secret", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() dk.Spec.CustomPullSecret = testOtelPullSecret statefulSet := getStatefulset(t, dk) @@ -281,14 +230,14 @@ func TestImagePullSecrets(t *testing.T) { func TestResources(t *testing.T) { t.Run("no resources", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() statefulSet := getStatefulset(t, dk) assert.Empty(t, statefulSet.Spec.Template.Spec.Containers[0].Resources) }) t.Run("custom resources", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() dk.Spec.Templates.ExtensionExecutionController.Resources = corev1.ResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceMemory: resource.MustParse("1Gi"), @@ -303,7 +252,7 @@ func TestResources(t *testing.T) { func TestLabels(t *testing.T) { t.Run("the default labels", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() statefulSet := getStatefulset(t, dk) @@ -315,7 +264,7 @@ func TestLabels(t *testing.T) { }) t.Run("custom labels", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() customLabels := map[string]string{ "a": "b", } @@ -334,7 +283,7 @@ func TestLabels(t *testing.T) { func TestAnnotations(t *testing.T) { t.Run("the default annotations", func(t *testing.T) { - statefulSet := getStatefulset(t, getTestDynakube()) + statefulSet := getStatefulset(t, getTestDynakubeWithExtensions()) assert.Len(t, statefulSet.ObjectMeta.Annotations, 1) require.Len(t, statefulSet.Spec.Template.ObjectMeta.Annotations, 1) @@ -342,7 +291,7 @@ func TestAnnotations(t *testing.T) { }) t.Run("custom annotations", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() customAnnotations := map[string]string{ "a": "b", } @@ -360,13 +309,13 @@ func TestAnnotations(t *testing.T) { func TestTolerations(t *testing.T) { t.Run("the default tolerations", func(t *testing.T) { - statefulSet := getStatefulset(t, getTestDynakube()) + statefulSet := getStatefulset(t, getTestDynakubeWithExtensions()) assert.Empty(t, statefulSet.Spec.Template.Spec.Tolerations) }) t.Run("custom tolerations", func(t *testing.T) { - dk := getTestDynakube() + dk := getTestDynakubeWithExtensions() customTolerations := []corev1.Toleration{ { @@ -386,7 +335,7 @@ func TestTolerations(t *testing.T) { func TestSecurityContext(t *testing.T) { t.Run("the default securityContext is set", func(t *testing.T) { - statefulSet := getStatefulset(t, getTestDynakube()) + statefulSet := getStatefulset(t, getTestDynakubeWithExtensions()) assert.NotNil(t, statefulSet.Spec.Template.Spec.SecurityContext) assert.NotNil(t, statefulSet.Spec.Template.Spec.Containers[0].SecurityContext) @@ -395,152 +344,14 @@ func TestSecurityContext(t *testing.T) { func TestUpdateStrategy(t *testing.T) { t.Run("the default update strategy is set", func(t *testing.T) { - statefulSet := getStatefulset(t, getTestDynakube()) + statefulSet := getStatefulset(t, getTestDynakubeWithExtensions()) assert.NotNil(t, statefulSet.Spec.UpdateStrategy.RollingUpdate.Partition) assert.NotEmpty(t, statefulSet.Spec.UpdateStrategy.Type) }) } -func TestVolumes(t *testing.T) { - t.Run("volume mounts with trusted CAs", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.TrustedCAs = "test-trusted-cas" - statefulSet := getStatefulset(t, dk) - - expectedVolumeMount := corev1.VolumeMount{ - Name: caCertsVolumeName, - MountPath: trustedCAVolumeMountPath, - ReadOnly: true, - } - assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) - }) - t.Run("volume mounts without trusted CAs", func(t *testing.T) { - dk := getTestDynakube() - statefulSet := getStatefulset(t, dk) - - expectedVolumeMount := corev1.VolumeMount{ - Name: caCertsVolumeName, - MountPath: trustedCAVolumeMountPath, - ReadOnly: true, - } - - assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) - }) - t.Run("volumes and volume mounts with custom EEC TLS certificate", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.Templates.ExtensionExecutionController.TlsRefName = "test-tls-name" - statefulSet := getStatefulset(t, dk) - - expectedVolumeMount := corev1.VolumeMount{ - Name: dk.ExtensionsTLSSecretName(), - MountPath: customEecTLSCertificatePath, - ReadOnly: true, - } - - expectedVolume := corev1.Volume{Name: dk.Spec.Templates.ExtensionExecutionController.TlsRefName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: dk.Spec.Templates.ExtensionExecutionController.TlsRefName, - Items: []corev1.KeyToPath{ - { - Key: consts.TLSCrtDataName, - Path: consts.TLSCrtDataName, - }, - }, - }, - }} - - assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) - assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) - }) - t.Run("volumes with trusted CAs", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.TrustedCAs = "test-trusted-cas" - statefulSet := getStatefulset(t, dk) - - expectedVolume := corev1.Volume{ - Name: caCertsVolumeName, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: dk.Spec.TrustedCAs, - }, - Items: []corev1.KeyToPath{ - { - Key: "certs", - Path: trustedCAsFile, - }, - }, - }, - }, - } - assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) - }) - t.Run("volumes with otelc token", func(t *testing.T) { - dk := getTestDynakube() - statefulSet := getStatefulset(t, dk) - - expectedVolume := corev1.Volume{ - Name: consts.ExtensionsTokensVolumeName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: dk.ExtensionsTokenSecretName(), - Items: []corev1.KeyToPath{ - { - Key: consts.OtelcTokenSecretKey, - Path: consts.OtelcTokenSecretKey, - }, - }, - DefaultMode: ptr.To(int32(420)), - }, - }, - } - - assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) - }) - - t.Run("volumes and volume mounts with telemetry service custom TLS certificate", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.TelemetryService = &telemetryservice.Spec{ - TlsRefName: testTelemetryServiceSecret, - } - - tlsSecret := getTLSSecret(dk.TelemetryService().Spec.TlsRefName, dk.Namespace, "crt", "key") - statefulSet := getStatefulset(t, dk, &tlsSecret) - - expectedVolume := corev1.Volume{ - Name: customTlsCertVolumeName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: dk.TelemetryService().Spec.TlsRefName, - Items: []corev1.KeyToPath{ - { - Key: consts.TLSCrtDataName, - Path: consts.TLSCrtDataName, - }, - { - Key: consts.TLSKeyDataName, - Path: consts.TLSKeyDataName, - }, - }, - }, - }, - } - - assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) - - expectedVolumeMount := corev1.VolumeMount{ - Name: customTlsCertVolumeName, - MountPath: customTlsCertMountPath, - ReadOnly: true, - } - - assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) - }) -} - -func getTestDynakube() *dynakube.DynaKube { +func getTestDynakubeWithExtensions() *dynakube.DynaKube { return &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Name: testDynakubeName, @@ -554,6 +365,19 @@ func getTestDynakube() *dynakube.DynaKube { } } +func getTestDynakube() *dynakube.DynaKube { + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakubeName, + Namespace: testNamespaceName, + Annotations: map[string]string{}, + }, + Spec: dynakube.DynaKubeSpec{}, + } + + return dk +} + func getStatefulset(t *testing.T, dk *dynakube.DynaKube, objs ...client.Object) *appsv1.StatefulSet { mockK8sClient := fake.NewClient(dk) mockK8sClient = mockTLSSecret(t, mockK8sClient, dk) @@ -567,7 +391,7 @@ func getStatefulset(t *testing.T, dk *dynakube.DynaKube, objs ...client.Object) require.NoError(t, err) statefulSet := &appsv1.StatefulSet{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.ExtensionsCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.OtelCollectorStatefulsetName(), Namespace: dk.Namespace}, statefulSet) require.NoError(t, err) return statefulSet @@ -582,6 +406,19 @@ func mockTLSSecret(t *testing.T, client client.Client, dk *dynakube.DynaKube) cl return client } +func getTokens(name string, namespace string) corev1.Secret { + return corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Data: map[string][]byte{ + dtclient.ApiToken: []byte("test"), + dtclient.DataIngestToken: []byte("test"), + }, + } +} + func getTLSSecret(name string, namespace string, crt string, key string) corev1.Secret { return corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -594,3 +431,15 @@ func getTLSSecret(name string, namespace string, crt string, key string) corev1. }, } } + +func getConfigConfigMap(name string, namespace string) corev1.ConfigMap { + return corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: name + otelcconsts.TelemetryCollectorConfigmapSuffix, + Namespace: namespace, + }, + Data: map[string]string{ + otelcconsts.ConfigFieldName: "test", + }, + } +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/volumes.go b/pkg/controllers/dynakube/otelc/statefulset/volumes.go index 64058081e6..715b4c9bc4 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/volumes.go +++ b/pkg/controllers/dynakube/otelc/statefulset/volumes.go @@ -3,6 +3,8 @@ package statefulset import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/configuration" + otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/utils/ptr" @@ -14,14 +16,19 @@ const ( trustedCAsFile = "rootca.pem" - customTlsCertVolumeName = "telemetry-custom-tls" - customTlsCertMountPath = "/tls/custom/telemetry" + customTlsCertVolumeName = "telemetry-ingest-custom-tls" + extensionsControllerTLSVolumeName = "extensions-controller-tls" + telemetryCollectorConfigVolumeName = "telemetry-collector-config" + telemetryCollectorConfigPath = "/config" ) func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { - return func(o *appsv1.StatefulSet) { - o.Spec.Template.Spec.Volumes = []corev1.Volume{ - { + var volumes []corev1.Volume + + if dk.IsExtensionsEnabled() { + volumes = append( + volumes, + corev1.Volume{ Name: consts.ExtensionsTokensVolumeName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ @@ -36,47 +43,49 @@ func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { }, }, }, - } - if dk.Spec.TrustedCAs != "" { - o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ - Name: caCertsVolumeName, + corev1.Volume{ + Name: extensionsControllerTLSVolumeName, VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: dk.Spec.TrustedCAs, - }, + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTLSSecretName(), Items: []corev1.KeyToPath{ { - Key: "certs", - Path: trustedCAsFile, + Key: consts.TLSCrtDataName, + Path: consts.TLSCrtDataName, }, }, }, }, - }) - } + }, + ) + } - o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ - Name: dk.ExtensionsTLSSecretName(), + if dk.Spec.TrustedCAs != "" { + volumes = append(volumes, corev1.Volume{ + Name: caCertsVolumeName, VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: dk.ExtensionsTLSSecretName(), + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: dk.Spec.TrustedCAs, + }, Items: []corev1.KeyToPath{ { - Key: consts.TLSCrtDataName, - Path: consts.TLSCrtDataName, + Key: "certs", + Path: trustedCAsFile, }, }, }, }, }) + } - if dk.TelemetryService().IsEnabled() && dk.TelemetryService().Spec.TlsRefName != "" { - o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ + if dk.TelemetryIngest().IsEnabled() { + if dk.TelemetryIngest().Spec.TlsRefName != "" { + volumes = append(volumes, corev1.Volume{ Name: customTlsCertVolumeName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: dk.TelemetryService().Spec.TlsRefName, + SecretName: dk.TelemetryIngest().Spec.TlsRefName, Items: []corev1.KeyToPath{ { Key: consts.TLSCrtDataName, @@ -91,32 +100,61 @@ func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { }, }) } + + volumes = append(volumes, corev1.Volume{ + Name: telemetryCollectorConfigVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: configuration.GetConfigMapName(dk.Name), + }, + }, + }, + }) + } + + return func(o *appsv1.StatefulSet) { + o.Spec.Template.Spec.Volumes = volumes } } func buildContainerVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { - vm := []corev1.VolumeMount{ - {Name: consts.ExtensionsTokensVolumeName, ReadOnly: true, MountPath: secretsTokensPath}, + var vm []corev1.VolumeMount + + if dk.IsExtensionsEnabled() { + vm = append( + vm, + corev1.VolumeMount{ + Name: consts.ExtensionsTokensVolumeName, ReadOnly: true, MountPath: secretsTokensPath, + }, + corev1.VolumeMount{ + Name: extensionsControllerTLSVolumeName, + MountPath: customEecTLSCertificatePath, + ReadOnly: true, + }, + ) } if dk.Spec.TrustedCAs != "" { vm = append(vm, corev1.VolumeMount{ Name: caCertsVolumeName, - MountPath: trustedCAVolumeMountPath, + MountPath: otelcconsts.TrustedCAVolumeMountPath, ReadOnly: true, }) } - vm = append(vm, corev1.VolumeMount{ - Name: dk.ExtensionsTLSSecretName(), - MountPath: customEecTLSCertificatePath, - ReadOnly: true, - }) + if dk.TelemetryIngest().IsEnabled() { + if dk.TelemetryIngest().Spec.TlsRefName != "" { + vm = append(vm, corev1.VolumeMount{ + Name: customTlsCertVolumeName, + MountPath: otelcconsts.CustomTlsCertMountPath, + ReadOnly: true, + }) + } - if dk.TelemetryService().IsEnabled() && dk.TelemetryService().Spec.TlsRefName != "" { vm = append(vm, corev1.VolumeMount{ - Name: customTlsCertVolumeName, - MountPath: customTlsCertMountPath, + Name: telemetryCollectorConfigVolumeName, + MountPath: telemetryCollectorConfigPath, ReadOnly: true, }) } diff --git a/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go b/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go new file mode 100644 index 0000000000..15d226dc14 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go @@ -0,0 +1,172 @@ +package statefulset + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" +) + +func TestVolumes(t *testing.T) { + t.Run("volume mounts with trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + dk.Spec.TrustedCAs = "test-trusted-cas" + statefulSet := getStatefulset(t, dk) + + expectedVolumeMount := corev1.VolumeMount{ + Name: caCertsVolumeName, + MountPath: otelcconsts.TrustedCAVolumeMountPath, + ReadOnly: true, + } + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + }) + t.Run("volume mounts without trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + statefulSet := getStatefulset(t, dk) + + expectedVolumeMount := corev1.VolumeMount{ + Name: caCertsVolumeName, + MountPath: otelcconsts.TrustedCAVolumeMountPath, + ReadOnly: true, + } + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + }) + t.Run("volumes and volume mounts with custom EEC TLS certificate", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + dk.Spec.Templates.ExtensionExecutionController.TlsRefName = "test-tls-name" + statefulSet := getStatefulset(t, dk) + + expectedVolumeMount := corev1.VolumeMount{ + Name: extensionsControllerTLSVolumeName, + MountPath: customEecTLSCertificatePath, + ReadOnly: true, + } + + expectedVolumes := []corev1.Volume{ + { + Name: consts.ExtensionsTokensVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTokenSecretName(), + Items: []corev1.KeyToPath{ + { + Key: consts.OtelcTokenSecretKey, + Path: consts.OtelcTokenSecretKey, + }, + }, + DefaultMode: ptr.To(int32(420)), + }, + }, + }, + { + Name: extensionsControllerTLSVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "test-tls-name", + Items: []corev1.KeyToPath{ + { + Key: consts.TLSCrtDataName, + Path: consts.TLSCrtDataName, + }, + }, + }, + }, + }, + } + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + assert.Equal(t, expectedVolumes, statefulSet.Spec.Template.Spec.Volumes) + }) + t.Run("volumes with trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + dk.Spec.TrustedCAs = "test-trusted-cas" + statefulSet := getStatefulset(t, dk) + + expectedVolume := corev1.Volume{ + Name: caCertsVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: dk.Spec.TrustedCAs, + }, + Items: []corev1.KeyToPath{ + { + Key: "certs", + Path: trustedCAsFile, + }, + }, + }, + }, + } + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) + }) + t.Run("volumes with otelc token", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + statefulSet := getStatefulset(t, dk) + + expectedVolume := corev1.Volume{ + Name: consts.ExtensionsTokensVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTokenSecretName(), + Items: []corev1.KeyToPath{ + { + Key: consts.OtelcTokenSecretKey, + Path: consts.OtelcTokenSecretKey, + }, + }, + DefaultMode: ptr.To(int32(420)), + }, + }, + } + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) + }) + + t.Run("volumes and volume mounts with telemetry service custom TLS certificate", func(t *testing.T) { + dk := getTestDynakubeWithExtensions() + dk.Spec.TelemetryIngest = &telemetryingest.Spec{ + TlsRefName: testTelemetryIngestSecret, + } + + tlsSecret := getTLSSecret(dk.TelemetryIngest().Spec.TlsRefName, dk.Namespace, "crt", "key") + dataIngestToken := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + + statefulSet := getStatefulset(t, dk, &tlsSecret, &dataIngestToken, &configMap) + + expectedVolume := corev1.Volume{ + Name: customTlsCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.TelemetryIngest().Spec.TlsRefName, + Items: []corev1.KeyToPath{ + { + Key: consts.TLSCrtDataName, + Path: consts.TLSCrtDataName, + }, + { + Key: consts.TLSKeyDataName, + Path: consts.TLSKeyDataName, + }, + }, + }, + }, + } + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) + + expectedVolumeMount := corev1.VolumeMount{ + Name: customTlsCertVolumeName, + MountPath: otelcconsts.CustomTlsCertMountPath, + ReadOnly: true, + } + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + }) +} diff --git a/pkg/controllers/dynakube/phase.go b/pkg/controllers/dynakube/phase.go index 371cabaf19..96a3168739 100644 --- a/pkg/controllers/dynakube/phase.go +++ b/pkg/controllers/dynakube/phase.go @@ -59,7 +59,7 @@ func (controller *Controller) determineExtensionsExecutionControllerPhase(dk *dy } func (controller *Controller) determineExtensionsCollectorPhase(dk *dynakube.DynaKube) status.DeploymentPhase { - return controller.determinePrometheusStatefulsetPhase(dk, dk.ExtensionsCollectorStatefulsetName()) + return controller.determinePrometheusStatefulsetPhase(dk, dk.OtelCollectorStatefulsetName()) } func (controller *Controller) determinePrometheusStatefulsetPhase(dk *dynakube.DynaKube, statefulsetName string) status.DeploymentPhase { diff --git a/pkg/controllers/dynakube/phase_test.go b/pkg/controllers/dynakube/phase_test.go index ca7c86fa09..b36ff6ccac 100644 --- a/pkg/controllers/dynakube/phase_test.go +++ b/pkg/controllers/dynakube/phase_test.go @@ -241,7 +241,7 @@ func TestExtensionsCollectorPhaseChanges(t *testing.T) { assert.Equal(t, status.Error, phase) }) t.Run("otelc pods not ready -> deploying", func(t *testing.T) { - fakeClient := fake.NewClient(createStatefulset(testNamespace, dk.ExtensionsCollectorStatefulsetName(), 2, 1)) + fakeClient := fake.NewClient(createStatefulset(testNamespace, dk.OtelCollectorStatefulsetName(), 2, 1)) controller := &Controller{ client: fakeClient, @@ -251,7 +251,7 @@ func TestExtensionsCollectorPhaseChanges(t *testing.T) { assert.Equal(t, status.Deploying, phase) }) t.Run("otelc deployed -> running", func(t *testing.T) { - fakeClient := fake.NewClient(createStatefulset(testNamespace, dk.ExtensionsCollectorStatefulsetName(), 2, 2)) + fakeClient := fake.NewClient(createStatefulset(testNamespace, dk.OtelCollectorStatefulsetName(), 2, 2)) controller := &Controller{ client: fakeClient, @@ -399,8 +399,8 @@ func TestDynakubePhaseChanges(t *testing.T) { agNotReady := createStatefulset(testNamespace, "test-name-activegate", 1, 0) eecReady := createStatefulset(testNamespace, dk.ExtensionsExecutionControllerStatefulsetName(), 1, 1) eecNotReady := createStatefulset(testNamespace, dk.ExtensionsExecutionControllerStatefulsetName(), 1, 0) - otelcReady := createStatefulset(testNamespace, dk.ExtensionsCollectorStatefulsetName(), 2, 2) - otelcNotReady := createStatefulset(testNamespace, dk.ExtensionsCollectorStatefulsetName(), 2, 1) + otelcReady := createStatefulset(testNamespace, dk.OtelCollectorStatefulsetName(), 2, 2) + otelcNotReady := createStatefulset(testNamespace, dk.OtelCollectorStatefulsetName(), 2, 1) oaReady := createDaemonSet(testNamespace, "test-name-oneagent", 3, 3) oaNotReady := createDaemonSet(testNamespace, "test-name-oneagent", 3, 2) logAgentReady := createDaemonSet(testNamespace, dk.LogMonitoring().GetDaemonSetName(), 3, 3) diff --git a/pkg/otelcgen/exporters.go b/pkg/otelcgen/exporters.go index 6cbea0be92..703d02d9fb 100644 --- a/pkg/otelcgen/exporters.go +++ b/pkg/otelcgen/exporters.go @@ -10,7 +10,7 @@ var ( func (c *Config) buildExporters() map[component.ID]component.Config { serverConfig := &ServerConfig{ - Endpoint: c.buildEndpointWithoutPort(), + Endpoint: c.buildExportersEndpoint(), TLSSetting: &TLSSetting{}, } @@ -24,6 +24,7 @@ func (c *Config) buildExporters() map[component.ID]component.Config { } return map[component.ID]component.Config{ + debug: nil, otlphttp: serverConfig, } } diff --git a/pkg/otelcgen/exporters_test.go b/pkg/otelcgen/exporters_test.go index 7420c88258..594115ff42 100644 --- a/pkg/otelcgen/exporters_test.go +++ b/pkg/otelcgen/exporters_test.go @@ -11,7 +11,9 @@ import ( func TestNewConfigWithExporters(t *testing.T) { cfg, err := NewConfig( - "test", + "", + RegisteredProtocols, + WithExportersEndpoint("test"), WithCA("/run/opensignals/cacerts/certs"), WithApiToken("test-token"), WithExporters(), diff --git a/pkg/otelcgen/extensions_test.go b/pkg/otelcgen/extensions_test.go index 4f02e89595..a439035b53 100644 --- a/pkg/otelcgen/extensions_test.go +++ b/pkg/otelcgen/extensions_test.go @@ -12,6 +12,7 @@ import ( func TestNewConfigWithExtensions(t *testing.T) { cfg, err := NewConfig( "test", + RegisteredProtocols, WithExtensions(), ) require.NoError(t, err) diff --git a/pkg/otelcgen/otelcgen.go b/pkg/otelcgen/otelcgen.go index 1aaf114417..bc9f9bcb09 100644 --- a/pkg/otelcgen/otelcgen.go +++ b/pkg/otelcgen/otelcgen.go @@ -65,6 +65,8 @@ var ( OtlpID = component.MustNewID(string(OtlpProtocol)) StatsdID = component.MustNewID(string(StatsdProtocol)) ZipkinID = component.MustNewID(string(ZipkinProtocol)) + + RegisteredProtocols = Protocols{OtlpProtocol, JaegerProtocol, StatsdProtocol, ZipkinProtocol} ) type Config struct { @@ -83,20 +85,23 @@ type Config struct { // Extensions is a map of ComponentID to extensions. Extensions map[component.ID]component.Config `mapstructure:"extensions"` - tlsKey string - tlsCert string - caFile string - podIP string - apiToken string + tlsKey string + tlsCert string + caFile string + podIP string + endpoint string + apiToken string + protocols Protocols Service ServiceConfig `mapstructure:"service"` } type Option func(c *Config) error -func NewConfig(podIP string, options ...Option) (*Config, error) { +func NewConfig(podIP string, protocols Protocols, options ...Option) (*Config, error) { c := Config{ - podIP: podIP, + podIP: podIP, + protocols: protocols, } for _, opt := range options { @@ -119,7 +124,12 @@ func (c *Config) Marshal() ([]byte, error) { } func (c *Config) buildTLSSetting() *TLSSetting { + if c.tlsCert == "" && c.tlsKey == "" { + return nil + } + tls := &TLSSetting{} + if c.tlsCert != "" { tls.CertFile = c.tlsCert } @@ -135,13 +145,32 @@ func (c *Config) buildEndpoint(port uint) string { return fmt.Sprintf("%s:%d", c.podIP, port) } -func (c *Config) buildEndpointWithoutPort() string { - return c.podIP +func (c *Config) buildExportersEndpoint() string { + return c.endpoint } -func WithProtocols(protocols ...string) Option { +func (c *Config) protocolsToIDs() []component.ID { + ids := []component.ID{} + + for _, p := range c.protocols { + switch p { + case JaegerProtocol: + ids = append(ids, JaegerID) + case ZipkinProtocol: + ids = append(ids, ZipkinID) + case StatsdProtocol: + ids = append(ids, StatsdID) + case OtlpProtocol: + ids = append(ids, OtlpID) + } + } + + return ids +} + +func WithReceivers() Option { return func(c *Config) error { - receivers, err := c.buildReceivers(protocols) + receivers, err := c.buildReceivers() if err != nil { return err } @@ -216,3 +245,11 @@ func WithApiToken(apiToken string) Option { return nil } } + +func WithExportersEndpoint(endpoint string) Option { + return func(c *Config) error { + c.endpoint = endpoint + + return nil + } +} diff --git a/pkg/otelcgen/otelcgen_test.go b/pkg/otelcgen/otelcgen_test.go index aa1652f171..1d9b2c4fb7 100644 --- a/pkg/otelcgen/otelcgen_test.go +++ b/pkg/otelcgen/otelcgen_test.go @@ -12,10 +12,12 @@ import ( func TestNewConfigFull(t *testing.T) { cfg, err := NewConfig( "test", + Protocols{OtlpProtocol, JaegerProtocol, StatsdProtocol, ZipkinProtocol}, WithCA("/run/opensignals/cacerts/certs"), WithApiToken("test-token"), WithTLS("/run/opensignals/tls/tls.crt", "/run/opensignals/tls/tls.key"), - WithProtocols("otlp", "jaeger", "zipkin", "statsd"), + WithReceivers(), + WithExportersEndpoint("exporters-test-endpoint"), WithExtensions(), WithExporters(), WithServices(), diff --git a/pkg/otelcgen/processors.go b/pkg/otelcgen/processors.go index ff9e57552e..de8151c26d 100644 --- a/pkg/otelcgen/processors.go +++ b/pkg/otelcgen/processors.go @@ -25,13 +25,14 @@ type MemoryLimiter struct { // More details, about how to configure `processors,` can be found // https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/batchprocessor/README.md var ( - k8sattributes = component.MustNewID("k8sattributes") - transform = component.MustNewID("transform") - batch = component.MustNewType("batch") - batchTraces = component.NewIDWithName(batch, "traces") - batchMetrics = component.NewIDWithName(batch, "metrics") - batchLogs = component.NewIDWithName(batch, "logs") - memoryLimiter = component.MustNewID("memory_limiter") + k8sattributes = component.MustNewID("k8sattributes") + transform = component.MustNewID("transform") + batch = component.MustNewType("batch") + batchTraces = component.NewIDWithName(batch, "traces") + batchMetrics = component.NewIDWithName(batch, "metrics") + batchLogs = component.NewIDWithName(batch, "logs") + memoryLimiter = component.MustNewID("memory_limiter") + cumulativeToDelta = component.MustNewID("cumulativetodelta") defaultK8Sattributes = []string{ "k8s.cluster.uid", @@ -51,6 +52,7 @@ var ( func (c *Config) buildProcessors() map[component.ID]component.Config { return map[component.ID]component.Config{ + cumulativeToDelta: map[string]any{}, k8sattributes: map[string]any{ "extract": map[string]any{ "metadata": defaultK8Sattributes, diff --git a/pkg/otelcgen/processors_test.go b/pkg/otelcgen/processors_test.go index aff42a651a..84c2318bf4 100644 --- a/pkg/otelcgen/processors_test.go +++ b/pkg/otelcgen/processors_test.go @@ -12,6 +12,7 @@ import ( func TestNewConfigWithProcessors(t *testing.T) { cfg, err := NewConfig( "", + RegisteredProtocols, WithProcessors(), ) require.NoError(t, err) diff --git a/pkg/otelcgen/receivers.go b/pkg/otelcgen/receivers.go index 2bb33372fe..913ca1e657 100644 --- a/pkg/otelcgen/receivers.go +++ b/pkg/otelcgen/receivers.go @@ -44,16 +44,11 @@ func (c *Config) buildReceiverComponent(componentID component.ID) component.Conf return nil } -func (c *Config) buildReceivers(protocols []string) (map[component.ID]component.Config, error) { - if len(protocols) == 0 { - // means all protocols are enabled - protocols = []string{string(StatsdProtocol), string(ZipkinProtocol), string(JaegerProtocol), string(OtlpProtocol)} - } - +func (c *Config) buildReceivers() (map[component.ID]component.Config, error) { receivers := make(map[component.ID]component.Config) - for _, p := range protocols { - switch Protocol(p) { + for _, p := range c.protocols { + switch p { case StatsdProtocol: receivers[StatsdID] = c.buildReceiverComponent(StatsdID) case ZipkinProtocol: diff --git a/pkg/otelcgen/receivers_test.go b/pkg/otelcgen/receivers_test.go index 037e51cd49..c9b611d612 100644 --- a/pkg/otelcgen/receivers_test.go +++ b/pkg/otelcgen/receivers_test.go @@ -13,7 +13,8 @@ func TestNewConfig(t *testing.T) { t.Run("with statsd protocol only", func(t *testing.T) { cfg, err := NewConfig( "test", - WithProtocols("statsd"), + Protocols{StatsdProtocol}, + WithReceivers(), ) require.NoError(t, err) c, err := cfg.Marshal() @@ -28,8 +29,9 @@ func TestNewConfig(t *testing.T) { t.Run("with zipkin protocol only with tls key and tls cert", func(t *testing.T) { cfg, err := NewConfig( "test", + Protocols{ZipkinProtocol}, WithTLS("/run/opensignals/tls/tls.crt", "/run/opensignals/tls/tls.key"), - WithProtocols("zipkin"), + WithReceivers(), ) require.NoError(t, err) c, err := cfg.Marshal() @@ -43,8 +45,9 @@ func TestNewConfig(t *testing.T) { t.Run("with jaeger protocol only with tls key and tls cert", func(t *testing.T) { cfg, err := NewConfig( "test", + Protocols{JaegerProtocol}, WithTLS("/run/opensignals/tls/tls.crt", "/run/opensignals/tls/tls.key"), - WithProtocols("jaeger"), + WithReceivers(), ) require.NoError(t, err) c, err := cfg.Marshal() @@ -59,8 +62,9 @@ func TestNewConfig(t *testing.T) { t.Run("with otlp protocol only with tls key and tls cert", func(t *testing.T) { cfg, err := NewConfig( "test", + Protocols{OtlpProtocol}, WithTLS("/run/opensignals/tls/tls.crt", "/run/opensignals/tls/tls.key"), - WithProtocols("otlp"), + WithReceivers(), ) require.NoError(t, err) c, err := cfg.Marshal() @@ -75,7 +79,8 @@ func TestNewConfig(t *testing.T) { t.Run("with unknown protocol", func(t *testing.T) { _, err := NewConfig( "", - WithProtocols("unknown"), + Protocols{"unknown"}, + WithReceivers(), ) require.Error(t, err) assert.Contains(t, err.Error(), "unknown protocol") diff --git a/pkg/otelcgen/services.go b/pkg/otelcgen/services.go index 150d60fd47..a84c979ee9 100644 --- a/pkg/otelcgen/services.go +++ b/pkg/otelcgen/services.go @@ -1,6 +1,8 @@ package otelcgen import ( + "slices" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/pipeline" "go.opentelemetry.io/collector/service/extensions" @@ -13,6 +15,17 @@ var ( metrics = pipeline.MustNewID("metrics") logs = pipeline.MustNewID("logs") debug = component.MustNewID("debug") + + allowedPipelinesLogsReceiversIDs = []component.ID{OtlpID} + + // based on + // stasd https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/d4372922ec79cb052c7f7e2fcc0fba9f492bd948/receiver/statsdreceiver/factory.go#L33 + allowedPipelinesMetricsReceiversIDs = []component.ID{OtlpID, StatsdID} + + // based on + // zipkin https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/d4372922ec79cb052c7f7e2fcc0fba9f492bd948/receiver/zipkinreceiver/factory.go#L24 + // jaeger https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/d4372922ec79cb052c7f7e2fcc0fba9f492bd948/receiver/jaegerreceiver/factory.go + allowedPipelinesTracesReceiversIDs = []component.ID{OtlpID, JaegerID, ZipkinID} ) // ServiceConfig defines the configurable components of the Service. @@ -29,32 +42,48 @@ type ServiceConfig struct { } func (c *Config) buildServices() ServiceConfig { + pipelinesCfg := pipelines.Config{} + + // traces + tracesReceivers := c.buildPipelinesReceivers(allowedPipelinesTracesReceiversIDs) + if len(tracesReceivers) != 0 { + pipelinesCfg[traces] = &pipelines.PipelineConfig{ + Receivers: tracesReceivers, + Processors: append(buildProcessors(), batchTraces), + Exporters: buildExporters(), + } + } + + // metrics + metricsReceivers := c.buildPipelinesReceivers(allowedPipelinesMetricsReceiversIDs) + if len(metricsReceivers) != 0 { + pipelinesCfg[metrics] = &pipelines.PipelineConfig{ + Receivers: metricsReceivers, + Processors: append(buildProcessors(), cumulativeToDelta, batchMetrics), + Exporters: buildExporters(), + } + } + + // logs + logsReceivers := c.buildPipelinesReceivers(allowedPipelinesLogsReceiversIDs) + if len(logsReceivers) != 0 { + pipelinesCfg[logs] = &pipelines.PipelineConfig{ + Receivers: logsReceivers, + Processors: append(buildProcessors(), batchLogs), + Exporters: buildExporters(), + } + } + return ServiceConfig{ Extensions: extensions.Config{healthCheck}, - Pipelines: pipelines.Config{ - traces: &pipelines.PipelineConfig{ - Receivers: buildReceivers(), - Processors: append(buildProcessors(), batchTraces), - Exporters: buildExporters(), - }, - metrics: &pipelines.PipelineConfig{ - Receivers: buildReceivers(), - Processors: append(buildProcessors(), batchMetrics), - Exporters: buildExporters(), - }, - logs: &pipelines.PipelineConfig{ - Receivers: buildReceivers(), - Processors: append(buildProcessors(), batchLogs), - Exporters: buildExporters(), - }, - }, + Pipelines: pipelinesCfg, } } -func buildReceivers() []component.ID { - return []component.ID{ - OtlpID, JaegerID, ZipkinID, - } +func (c *Config) buildPipelinesReceivers(allowed []component.ID) []component.ID { + return filter(c.protocolsToIDs(), func(id component.ID) bool { + return slices.Contains(allowed, id) + }) } func buildExporters() []component.ID { @@ -68,3 +97,15 @@ func buildProcessors() []component.ID { memoryLimiter, k8sattributes, transform, } } + +func filter(componentIDs []component.ID, f func(component.ID) bool) []component.ID { + filtered := make([]component.ID, 0) + + for _, componentID := range componentIDs { + if f(componentID) { + filtered = append(filtered, componentID) + } + } + + return filtered +} diff --git a/pkg/otelcgen/services_test.go b/pkg/otelcgen/services_test.go index 2448761062..69255f38db 100644 --- a/pkg/otelcgen/services_test.go +++ b/pkg/otelcgen/services_test.go @@ -12,6 +12,7 @@ import ( func TestNewConfigWithServices(t *testing.T) { cfg, err := NewConfig( "", + RegisteredProtocols, WithServices(), ) require.NoError(t, err) @@ -22,3 +23,33 @@ func TestNewConfigWithServices(t *testing.T) { require.NoError(t, err) assert.YAMLEq(t, string(expectedOutput), string(c)) } + +func TestNewConfigWithServicesZipkinOnly(t *testing.T) { + cfg, err := NewConfig( + "", + Protocols{ZipkinProtocol}, + WithServices(), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "services_zipkin_only.yaml")) + require.NoError(t, err) + assert.YAMLEq(t, string(expectedOutput), string(c)) +} + +func TestNewConfigWithServicesStatsdOnly(t *testing.T) { + cfg, err := NewConfig( + "", + Protocols{StatsdProtocol}, + WithServices(), + ) + require.NoError(t, err) + c, err := cfg.Marshal() + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join("testdata", "services_statsd_only.yaml")) + require.NoError(t, err) + assert.YAMLEq(t, string(expectedOutput), string(c)) +} diff --git a/pkg/otelcgen/testdata/exporters_only.yaml b/pkg/otelcgen/testdata/exporters_only.yaml index a5defb4bea..7a55098a1f 100644 --- a/pkg/otelcgen/testdata/exporters_only.yaml +++ b/pkg/otelcgen/testdata/exporters_only.yaml @@ -1,5 +1,6 @@ connectors: {} exporters: + debug: otlphttp: endpoint: "test" tls: diff --git a/pkg/otelcgen/testdata/full_config.yaml b/pkg/otelcgen/testdata/full_config.yaml index 2dcda80b45..7a041adf3c 100644 --- a/pkg/otelcgen/testdata/full_config.yaml +++ b/pkg/otelcgen/testdata/full_config.yaml @@ -1,7 +1,8 @@ connectors: {} exporters: + debug: otlphttp: - endpoint: "test" + endpoint: "exporters-test-endpoint" tls: ca_file: "/run/opensignals/cacerts/certs" headers: @@ -10,6 +11,7 @@ extensions: health_check: endpoint: test:13133 processors: + cumulativetodelta: {} k8sattributes: extract: annotations: @@ -198,8 +200,6 @@ service: - debug receivers: - otlp - - jaeger - - zipkin processors: - memory_limiter - k8sattributes @@ -211,12 +211,12 @@ service: - debug receivers: - otlp - - jaeger - - zipkin + - statsd processors: - memory_limiter - k8sattributes - transform + - cumulativetodelta - batch/metrics traces: exporters: diff --git a/pkg/otelcgen/testdata/processors_only.yaml b/pkg/otelcgen/testdata/processors_only.yaml index 5fc43bd435..64a69c6cdd 100644 --- a/pkg/otelcgen/testdata/processors_only.yaml +++ b/pkg/otelcgen/testdata/processors_only.yaml @@ -2,6 +2,7 @@ connectors: {} exporters: {} extensions: {} processors: + cumulativetodelta: {} k8sattributes: extract: annotations: diff --git a/pkg/otelcgen/testdata/services_only.yaml b/pkg/otelcgen/testdata/services_only.yaml index 05c47b8ae8..e45b6a4c61 100644 --- a/pkg/otelcgen/testdata/services_only.yaml +++ b/pkg/otelcgen/testdata/services_only.yaml @@ -13,8 +13,6 @@ service: - debug receivers: - otlp - - jaeger - - zipkin processors: - memory_limiter - k8sattributes @@ -26,12 +24,12 @@ service: - debug receivers: - otlp - - jaeger - - zipkin + - statsd processors: - memory_limiter - k8sattributes - transform + - cumulativetodelta - batch/metrics traces: exporters: diff --git a/pkg/otelcgen/testdata/services_statsd_only.yaml b/pkg/otelcgen/testdata/services_statsd_only.yaml new file mode 100644 index 0000000000..6ac5c6ac89 --- /dev/null +++ b/pkg/otelcgen/testdata/services_statsd_only.yaml @@ -0,0 +1,21 @@ +connectors: {} +exporters: {} +extensions: {} +processors: {} +receivers: {} +service: + extensions: + - health_check + pipelines: + metrics: + exporters: + - otlphttp + - debug + receivers: + - statsd + processors: + - memory_limiter + - k8sattributes + - transform + - cumulativetodelta + - batch/metrics diff --git a/pkg/otelcgen/testdata/services_zipkin_only.yaml b/pkg/otelcgen/testdata/services_zipkin_only.yaml new file mode 100644 index 0000000000..b737bc766f --- /dev/null +++ b/pkg/otelcgen/testdata/services_zipkin_only.yaml @@ -0,0 +1,20 @@ +connectors: {} +exporters: {} +extensions: {} +processors: {} +receivers: {} +service: + extensions: + - health_check + pipelines: + traces: + exporters: + - otlphttp + - debug + receivers: + - zipkin + processors: + - memory_limiter + - k8sattributes + - transform + - batch/traces diff --git a/pkg/util/conditions/configmap.go b/pkg/util/conditions/configmap.go new file mode 100644 index 0000000000..7218cd668e --- /dev/null +++ b/pkg/util/conditions/configmap.go @@ -0,0 +1,44 @@ +package conditions + +import ( + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + ConfigMapCreatedReason = "ConfigMapCreated" + ConfigMapUpdatedReason = "ConfigMapUpdated" + ConfigMapCreatedOrUpdatedReason = "ConfigMapCreatedOrUpdated" + ConfigMapOutdatedReason = "ConfigMapOutdated" + ConfigMapGenerationFailed = "ConfigMapGenerationFailed" +) + +func SetConfigMapCreatedOrUpdated(conditions *[]metav1.Condition, conditionType, name string) { + condition := metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionTrue, + Reason: ConfigMapCreatedOrUpdatedReason, + Message: appendCreatedOrUpdatedSuffix(name), + } + _ = meta.SetStatusCondition(conditions, condition) +} + +func SetConfigMapGenFailed(conditions *[]metav1.Condition, conditionType string, err error) { + condition := metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + Reason: ConfigMapGenerationFailed, + Message: "Failed to generate configmap: " + err.Error(), + } + _ = meta.SetStatusCondition(conditions, condition) +} + +func SetConfigMapOutdated(conditions *[]metav1.Condition, conditionType, message string) { + condition := metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + Reason: ConfigMapOutdatedReason, + Message: message, + } + _ = meta.SetStatusCondition(conditions, condition) +} diff --git a/pkg/util/conditions/token.go b/pkg/util/conditions/token.go new file mode 100644 index 0000000000..aaceafc14e --- /dev/null +++ b/pkg/util/conditions/token.go @@ -0,0 +1,20 @@ +package conditions + +import ( + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + DataIngestTokenMissing string = "DataIngestTokenMissing" +) + +func SetDataIngestTokenMissing(conditions *[]metav1.Condition, conditionType string, msg string) { + condition := metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + Reason: DataIngestTokenMissing, + Message: msg, + } + _ = meta.SetStatusCondition(conditions, condition) +} diff --git a/pkg/util/kubeobjects/labels/labels.go b/pkg/util/kubeobjects/labels/labels.go index 7788eda228..7a99fad401 100644 --- a/pkg/util/kubeobjects/labels/labels.go +++ b/pkg/util/kubeobjects/labels/labels.go @@ -22,8 +22,7 @@ const ( WebhookComponentLabel = "webhook" EdgeConnectComponentLabel = "edgeconnect" ExtensionComponentLabel = "dynatrace-extensions-controller" - CollectorComponentLabel = "dynatrace-extensions-collector" - OtelCComponentLabel = "dynatrace-otelc-controller" + OtelCComponentLabel = "dynatrace-opentelemetry-collector" ) type AppMatchLabels struct { diff --git a/test/features/extensions/extensions.go b/test/features/extensions/extensions.go index ee00beb1e5..adb14d63af 100644 --- a/test/features/extensions/extensions.go +++ b/test/features/extensions/extensions.go @@ -58,7 +58,7 @@ func Feature(t *testing.T) features.Feature { builder.Assess("extensions execution controller started", statefulset.WaitFor(testDynakube.ExtensionsExecutionControllerStatefulsetName(), testDynakube.Namespace)) - builder.Assess("extension collector started", statefulset.WaitFor(testDynakube.ExtensionsCollectorStatefulsetName(), testDynakube.Namespace)) + builder.Assess("extension collector started", statefulset.WaitFor(testDynakube.OtelCollectorStatefulsetName(), testDynakube.Namespace)) componentDynakube.Delete(builder, helpers.LevelTeardown, testDynakube) diff --git a/test/features/support_archive/support_archive.go b/test/features/support_archive/support_archive.go index 558f85d4d3..4c2ad50a5f 100644 --- a/test/features/support_archive/support_archive.go +++ b/test/features/support_archive/support_archive.go @@ -115,7 +115,7 @@ func Feature(t *testing.T) features.Feature { // check if components are running builder.Assess("active gate pod is running", statefulset.WaitFor(testDynakube.Name+"-"+agconsts.MultiActiveGateName, testDynakube.Namespace)) builder.Assess("extensions execution controller started", statefulset.WaitFor(testDynakube.ExtensionsExecutionControllerStatefulsetName(), testDynakube.Namespace)) - builder.Assess("extension collector started", statefulset.WaitFor(testDynakube.ExtensionsCollectorStatefulsetName(), testDynakube.Namespace)) + builder.Assess("extension collector started", statefulset.WaitFor(testDynakube.OtelCollectorStatefulsetName(), testDynakube.Namespace)) // Register actual test builder.Assess("support archive subcommand can be executed correctly with managed logs", testSupportArchiveCommand(testDynakube, testEdgeConnect, true)) From 250a5f4c05c070af238724f5b3e6d3a7f1e32b25 Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Fri, 7 Mar 2025 17:06:54 +0100 Subject: [PATCH 288/426] [OtelC] Add volume with TLS certificate(s) and customize telemetryService configuration. (#4554) Co-authored-by: Andrii Soldatenko Co-authored-by: Stefan Hauth --- pkg/api/v1beta3/dynakube/otelc_props.go | 24 ++ pkg/api/v1beta3/dynakube/otelc_props_test.go | 96 ++++++ .../otelc/configuration/reconciler.go | 6 + .../dynakube/otelc/consts/consts.go | 10 +- .../dynakube/otelc/statefulset/env.go | 2 +- .../dynakube/otelc/statefulset/volumes.go | 38 ++- .../otelc/statefulset/volumes_test.go | 295 ++++++++++++++++-- pkg/otelcgen/exporters.go | 7 +- 8 files changed, 437 insertions(+), 41 deletions(-) create mode 100644 pkg/api/v1beta3/dynakube/otelc_props_test.go diff --git a/pkg/api/v1beta3/dynakube/otelc_props.go b/pkg/api/v1beta3/dynakube/otelc_props.go index 064ce39176..f493f3612d 100644 --- a/pkg/api/v1beta3/dynakube/otelc_props.go +++ b/pkg/api/v1beta3/dynakube/otelc_props.go @@ -3,3 +3,27 @@ package dynakube func (dk *DynaKube) OtelCollectorStatefulsetName() string { return dk.Name + "-extensions-collector" } + +func (dk *DynaKube) IsAGCertificateNeeded() bool { + if dk.isInClusterActiveGate() && dk.ActiveGate().HasCaCert() { + return true + } + + return false +} + +func (dk *DynaKube) IsCACertificateNeeded() bool { + if !dk.isInClusterActiveGate() && dk.Spec.TrustedCAs != "" { + return true + } + + return false +} + +func (dk *DynaKube) isInClusterActiveGate() bool { + if dk.ActiveGate().IsEnabled() && dk.ActiveGate().IsApiEnabled() { + return true + } + + return false +} diff --git a/pkg/api/v1beta3/dynakube/otelc_props_test.go b/pkg/api/v1beta3/dynakube/otelc_props_test.go new file mode 100644 index 0000000000..8d76e1052b --- /dev/null +++ b/pkg/api/v1beta3/dynakube/otelc_props_test.go @@ -0,0 +1,96 @@ +package dynakube + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/stretchr/testify/assert" +) + +func TestIsAGCertificateNeeded(t *testing.T) { + t.Run("remote AG and no trustedCAs", func(t *testing.T) { + dk := &DynaKube{ + Spec: DynaKubeSpec{}, + } + assert.False(t, dk.IsAGCertificateNeeded()) + }) + t.Run("remote AG and trustedCAs", func(t *testing.T) { + dk := &DynaKube{ + Spec: DynaKubeSpec{ + TrustedCAs: "test", + }, + } + assert.False(t, dk.IsAGCertificateNeeded()) + }) + t.Run("in-cluster AG and no trustedCAs", func(t *testing.T) { + dk := &DynaKube{ + Spec: DynaKubeSpec{ + ActiveGate: activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + }, + }, + } + assert.True(t, dk.IsAGCertificateNeeded()) + }) + t.Run("in-cluster AG and trustedCAs", func(t *testing.T) { + dk := &DynaKube{ + Spec: DynaKubeSpec{ + ActiveGate: activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + }, + TrustedCAs: "test", + }, + } + assert.True(t, dk.IsAGCertificateNeeded()) + }) +} + +func TestIsCACertificateNeeded(t *testing.T) { + t.Run("remote AG and no trustedCAs", func(t *testing.T) { + dk := &DynaKube{ + Spec: DynaKubeSpec{}, + } + assert.False(t, dk.IsCACertificateNeeded()) + }) + t.Run("remote AG and trustedCAs", func(t *testing.T) { + dk := &DynaKube{ + Spec: DynaKubeSpec{ + TrustedCAs: "test", + }, + } + assert.True(t, dk.IsCACertificateNeeded()) + }) + t.Run("in-cluster AG and no trustedCAs", func(t *testing.T) { + dk := &DynaKube{ + Spec: DynaKubeSpec{ + ActiveGate: activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + }, + }, + } + assert.False(t, dk.IsCACertificateNeeded()) + }) + t.Run("in-cluster AG and trustedCAs", func(t *testing.T) { + dk := &DynaKube{ + Spec: DynaKubeSpec{ + ActiveGate: activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + }, + TrustedCAs: "test", + }, + } + assert.False(t, dk.IsCACertificateNeeded()) + }) +} diff --git a/pkg/controllers/dynakube/otelc/configuration/reconciler.go b/pkg/controllers/dynakube/otelc/configuration/reconciler.go index 9c4341c970..46627101df 100644 --- a/pkg/controllers/dynakube/otelc/configuration/reconciler.go +++ b/pkg/controllers/dynakube/otelc/configuration/reconciler.go @@ -106,6 +106,12 @@ func (r *Reconciler) getData() (map[string]string, error) { otelcgen.WithExportersEndpoint("${env:DT_ENDPOINT}"), } + if r.dk.IsAGCertificateNeeded() { + options = append(options, otelcgen.WithCA(otelcconsts.ActiveGateTLSCertVolumePath)) + } else if r.dk.IsCACertificateNeeded() { + options = append(options, otelcgen.WithCA(otelcconsts.TrustedCAVolumePath)) + } + if r.dk.TelemetryIngest().IsEnabled() && r.dk.TelemetryIngest().Spec.TlsRefName != "" { options = append(options, otelcgen.WithTLS(filepath.Join(otelcconsts.CustomTlsCertMountPath, consts.TLSCrtDataName), filepath.Join(otelcconsts.CustomTlsCertMountPath, consts.TLSKeyDataName))) } diff --git a/pkg/controllers/dynakube/otelc/consts/consts.go b/pkg/controllers/dynakube/otelc/consts/consts.go index db287b800d..d84f3373c5 100644 --- a/pkg/controllers/dynakube/otelc/consts/consts.go +++ b/pkg/controllers/dynakube/otelc/consts/consts.go @@ -6,9 +6,15 @@ const ( ConfigFieldName = "telemetry.yaml" TelemetryCollectorConfigmapSuffix = "-telemetry-collector-config" - CustomTlsCertMountPath = "/tls/custom/telemetry" + CustomTlsCertMountPath = "/tls/custom/telemetry" + + TrustedCAsFile = "rootca.pem" TrustedCAVolumeMountPath = "/tls/custom/cacerts" - TrustedCAVolumePath = TrustedCAVolumeMountPath + "/certs" + TrustedCAVolumePath = TrustedCAVolumeMountPath + "/" + TrustedCAsFile + + ActiveGateCertFile = "cert.pem" + ActiveGateTLSCertCAVolumeMountPath = "/tls/custom/activegate" + ActiveGateTLSCertVolumePath = ActiveGateTLSCertCAVolumeMountPath + "/" + ActiveGateCertFile EnvDataIngestToken = "DT_DATA_INGEST_TOKEN" ) diff --git a/pkg/controllers/dynakube/otelc/statefulset/env.go b/pkg/controllers/dynakube/otelc/statefulset/env.go index f05987589a..f6e70413fb 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env.go @@ -101,7 +101,7 @@ func getEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { ) } - if dk.Spec.TrustedCAs != "" { + if dk.IsExtensionsEnabled() && dk.Spec.TrustedCAs != "" { envs = append(envs, corev1.EnvVar{Name: envTrustedCAs, Value: otelcConsts.TrustedCAVolumePath}) } diff --git a/pkg/controllers/dynakube/otelc/statefulset/volumes.go b/pkg/controllers/dynakube/otelc/statefulset/volumes.go index 715b4c9bc4..595fa6ccc9 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/volumes.go +++ b/pkg/controllers/dynakube/otelc/statefulset/volumes.go @@ -13,8 +13,7 @@ import ( const ( // Volume names and paths caCertsVolumeName = "cacerts" - - trustedCAsFile = "rootca.pem" + agCertVolumeName = "agcert" customTlsCertVolumeName = "telemetry-ingest-custom-tls" extensionsControllerTLSVolumeName = "extensions-controller-tls" @@ -60,7 +59,7 @@ func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { ) } - if dk.Spec.TrustedCAs != "" { + if isTrustedCAsVolumeNeeded(dk) { volumes = append(volumes, corev1.Volume{ Name: caCertsVolumeName, VolumeSource: corev1.VolumeSource{ @@ -71,7 +70,7 @@ func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { Items: []corev1.KeyToPath{ { Key: "certs", - Path: trustedCAsFile, + Path: otelcconsts.TrustedCAsFile, }, }, }, @@ -80,6 +79,23 @@ func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { } if dk.TelemetryIngest().IsEnabled() { + if dk.IsAGCertificateNeeded() { + volumes = append(volumes, corev1.Volume{ + Name: agCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ActiveGate().GetTLSSecretName(), + Items: []corev1.KeyToPath{ + { + Key: dynakube.TLSCertKey, + Path: otelcconsts.ActiveGateCertFile, + }, + }, + }, + }, + }) + } + if dk.TelemetryIngest().Spec.TlsRefName != "" { volumes = append(volumes, corev1.Volume{ Name: customTlsCertVolumeName, @@ -135,7 +151,7 @@ func buildContainerVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { ) } - if dk.Spec.TrustedCAs != "" { + if isTrustedCAsVolumeNeeded(dk) { vm = append(vm, corev1.VolumeMount{ Name: caCertsVolumeName, MountPath: otelcconsts.TrustedCAVolumeMountPath, @@ -144,6 +160,14 @@ func buildContainerVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { } if dk.TelemetryIngest().IsEnabled() { + if dk.IsAGCertificateNeeded() { + vm = append(vm, corev1.VolumeMount{ + Name: agCertVolumeName, + MountPath: otelcconsts.ActiveGateTLSCertCAVolumeMountPath, + ReadOnly: true, + }) + } + if dk.TelemetryIngest().Spec.TlsRefName != "" { vm = append(vm, corev1.VolumeMount{ Name: customTlsCertVolumeName, @@ -161,3 +185,7 @@ func buildContainerVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { return vm } + +func isTrustedCAsVolumeNeeded(dk *dynakube.DynaKube) bool { + return dk.IsExtensionsEnabled() && dk.Spec.TrustedCAs != "" || dk.TelemetryIngest().IsEnabled() && dk.IsCACertificateNeeded() +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go b/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go index 15d226dc14..93449c7a19 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go @@ -3,11 +3,14 @@ package statefulset import ( "testing" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/consts" otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" ) @@ -17,24 +20,13 @@ func TestVolumes(t *testing.T) { dk.Spec.TrustedCAs = "test-trusted-cas" statefulSet := getStatefulset(t, dk) - expectedVolumeMount := corev1.VolumeMount{ - Name: caCertsVolumeName, - MountPath: otelcconsts.TrustedCAVolumeMountPath, - ReadOnly: true, - } - assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, trustedCAsVolumeMount()) }) t.Run("volume mounts without trusted CAs", func(t *testing.T) { dk := getTestDynakubeWithExtensions() statefulSet := getStatefulset(t, dk) - expectedVolumeMount := corev1.VolumeMount{ - Name: caCertsVolumeName, - MountPath: otelcconsts.TrustedCAVolumeMountPath, - ReadOnly: true, - } - - assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, trustedCAsVolumeMount()) }) t.Run("volumes and volume mounts with custom EEC TLS certificate", func(t *testing.T) { dk := getTestDynakubeWithExtensions() @@ -87,23 +79,7 @@ func TestVolumes(t *testing.T) { dk.Spec.TrustedCAs = "test-trusted-cas" statefulSet := getStatefulset(t, dk) - expectedVolume := corev1.Volume{ - Name: caCertsVolumeName, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: dk.Spec.TrustedCAs, - }, - Items: []corev1.KeyToPath{ - { - Key: "certs", - Path: trustedCAsFile, - }, - }, - }, - }, - } - assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, trustedCAsVolume(dk)) }) t.Run("volumes with otelc token", func(t *testing.T) { dk := getTestDynakubeWithExtensions() @@ -170,3 +146,262 @@ func TestVolumes(t *testing.T) { assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) }) } + +func TestVolumesWithTelemetryIngestAndRemoteActiveGate(t *testing.T) { + t.Run("volumes without trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithTelemetryIngest() + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, trustedCAsVolume(dk)) + }) + t.Run("volume mounts without trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithTelemetryIngest() + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, trustedCAsVolumeMount()) + }) + + t.Run("volumes with trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithTelemetryIngest() + dk.Spec.TrustedCAs = "test-trusted-cas" + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, trustedCAsVolume(dk)) + }) + t.Run("volume mounts with trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithTelemetryIngest() + dk.Spec.TrustedCAs = "test-trusted-cas" + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, trustedCAsVolumeMount()) + }) +} + +func TestVolumesWithTelemetryIngestAndInClusterActiveGate(t *testing.T) { + t.Run("volumes without trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithTelemetryIngest() + dk.Spec.ActiveGate = activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + } + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, trustedCAsVolume(dk)) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, agCertVolume(dk)) + }) + t.Run("volume mounts without trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithTelemetryIngest() + dk.Spec.ActiveGate = activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + } + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, trustedCAsVolumeMount()) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, agCertVolumeMount()) + }) + + t.Run("volumes with trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithTelemetryIngest() + dk.Spec.ActiveGate = activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + } + dk.Spec.TrustedCAs = "test-trusted-cas" + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, trustedCAsVolume(dk)) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, agCertVolume(dk)) + }) + t.Run("volume mounts with trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithTelemetryIngest() + dk.Spec.ActiveGate = activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + } + dk.Spec.TrustedCAs = "test-trusted-cas" + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, trustedCAsVolumeMount()) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, agCertVolumeMount()) + }) +} + +func TestVolumesWithTelemetryIngestAndExtensionsAndInClusterActiveGate(t *testing.T) { + t.Run("volumes without trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithExtensionsAndTelemetryIngest() + dk.Spec.ActiveGate = activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + } + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, trustedCAsVolume(dk)) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, agCertVolume(dk)) + }) + t.Run("volume mounts without trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithExtensionsAndTelemetryIngest() + dk.Spec.ActiveGate = activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + } + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, trustedCAsVolumeMount()) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, agCertVolumeMount()) + }) + + t.Run("volumes with trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithExtensionsAndTelemetryIngest() + dk.Spec.ActiveGate = activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + } + dk.Spec.TrustedCAs = "test-trusted-cas" + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, trustedCAsVolume(dk)) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, agCertVolume(dk)) + }) + t.Run("volume mounts with trusted CAs", func(t *testing.T) { + dk := getTestDynakubeWithExtensionsAndTelemetryIngest() + dk.Spec.ActiveGate = activegate.Spec{ + TlsSecretName: "test-ag-cert", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + }, + } + dk.Spec.TrustedCAs = "test-trusted-cas" + tokensSecret := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + statefulSet := getStatefulset(t, dk, &tokensSecret, &configMap) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, trustedCAsVolumeMount()) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, agCertVolumeMount()) + }) +} + +func trustedCAsVolume(dk *dynakube.DynaKube) corev1.Volume { + return corev1.Volume{ + Name: caCertsVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: dk.Spec.TrustedCAs, + }, + Items: []corev1.KeyToPath{ + { + Key: "certs", + Path: otelcconsts.TrustedCAsFile, + }, + }, + }, + }, + } +} + +func trustedCAsVolumeMount() corev1.VolumeMount { + return corev1.VolumeMount{ + Name: caCertsVolumeName, + MountPath: otelcconsts.TrustedCAVolumeMountPath, + ReadOnly: true, + } +} + +func agCertVolume(dk *dynakube.DynaKube) corev1.Volume { + return corev1.Volume{ + Name: agCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ActiveGate().GetTLSSecretName(), + Items: []corev1.KeyToPath{ + { + Key: dynakube.TLSCertKey, + Path: otelcconsts.ActiveGateCertFile, + }, + }, + }, + }, + } +} + +func agCertVolumeMount() corev1.VolumeMount { + return corev1.VolumeMount{ + Name: agCertVolumeName, + MountPath: otelcconsts.ActiveGateTLSCertCAVolumeMountPath, + ReadOnly: true, + } +} + +func getTestDynakubeWithTelemetryIngest() *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakubeName, + Namespace: testNamespaceName, + Annotations: map[string]string{}, + }, + Spec: dynakube.DynaKubeSpec{ + TelemetryIngest: &telemetryingest.Spec{}, + Templates: dynakube.TemplatesSpec{OpenTelemetryCollector: dynakube.OpenTelemetryCollectorSpec{}}, + }, + } +} + +func getTestDynakubeWithExtensionsAndTelemetryIngest() *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDynakubeName, + Namespace: testNamespaceName, + Annotations: map[string]string{}, + }, + Spec: dynakube.DynaKubeSpec{ + Extensions: &dynakube.ExtensionsSpec{}, + TelemetryIngest: &telemetryingest.Spec{}, + Templates: dynakube.TemplatesSpec{OpenTelemetryCollector: dynakube.OpenTelemetryCollectorSpec{}}, + }, + } +} diff --git a/pkg/otelcgen/exporters.go b/pkg/otelcgen/exporters.go index 703d02d9fb..13a189fec3 100644 --- a/pkg/otelcgen/exporters.go +++ b/pkg/otelcgen/exporters.go @@ -10,12 +10,13 @@ var ( func (c *Config) buildExporters() map[component.ID]component.Config { serverConfig := &ServerConfig{ - Endpoint: c.buildExportersEndpoint(), - TLSSetting: &TLSSetting{}, + Endpoint: c.buildExportersEndpoint(), } if c.caFile != "" { - serverConfig.TLSSetting.CAFile = c.caFile + serverConfig.TLSSetting = &TLSSetting{ + CAFile: c.caFile, + } } if c.apiToken != "" { From 76b81173f9607831c05dd360fd25261a120115e6 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Fri, 7 Mar 2025 17:48:07 +0100 Subject: [PATCH 289/426] Fix exporter endpoint and add unit tests. (#4562) --- .../dynakube/otelc/secret/reconciler.go | 12 ++--- .../dynakube/otelc/secret/reconciler_test.go | 52 +++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler.go b/pkg/controllers/dynakube/otelc/secret/reconciler.go index 275ece8788..0f5f5fc106 100644 --- a/pkg/controllers/dynakube/otelc/secret/reconciler.go +++ b/pkg/controllers/dynakube/otelc/secret/reconciler.go @@ -83,16 +83,16 @@ func (r *Reconciler) ensureTelemetryIngestApiCredentialsSecret(ctx context.Conte } func (r *Reconciler) getDtEndpoint() ([]byte, error) { - tenantUUID, err := r.dk.TenantUUID() - if err != nil { - return nil, err - } - if r.dk.ActiveGate().IsApiEnabled() { + tenantUUID, err := r.dk.TenantUUID() + if err != nil { + return nil, err + } + return []byte(fmt.Sprintf("https://%s-activegate.dynatrace.svc/e/%s/api/v2/otlp", r.dk.Name, tenantUUID)), nil } - return []byte(fmt.Sprintf("https://%s.%s/api/v2/otlp", tenantUUID, r.dk.ApiUrlHost())), nil + return []byte(fmt.Sprintf("https://%s/api/v2/otlp", r.dk.ApiUrlHost())), nil } func (r *Reconciler) generateTelemetryIngestApiCredentialsSecret(name string) (secret *corev1.Secret, err error) { diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler_test.go b/pkg/controllers/dynakube/otelc/secret/reconciler_test.go index 0b68d12346..505a6f21ec 100644 --- a/pkg/controllers/dynakube/otelc/secret/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/secret/reconciler_test.go @@ -2,6 +2,7 @@ package secret import ( "context" + "fmt" "testing" schemeFake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" @@ -83,6 +84,57 @@ func TestSecretCreation(t *testing.T) { }) } +func TestEndpoint(t *testing.T) { + t.Run("in-cluster ActiveGate", func(t *testing.T) { + dk := createDynaKube(true) + apiUrl := fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", testTenantUUID) + dk.Spec.APIURL = apiUrl + dk.Spec.ActiveGate = activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{"dynatrace-api"}, + } + + objs := []client.Object{ + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: consts.TelemetryApiCredentialsSecretName, + Namespace: dk.Namespace, + }, + }, + } + + clt := schemeFake.NewClient(objs...) + r := NewReconciler(clt, clt, &dk) + + endpoint, err := r.getDtEndpoint() + require.NoError(t, err) + + expected := fmt.Sprintf("https://%s-activegate.dynatrace.svc/e/%s/api/v2/otlp", dk.Name, testTenantUUID) + assert.Equal(t, expected, string(endpoint)) + }) + + t.Run("public ActiveGate", func(t *testing.T) { + dk := createDynaKube(true) + apiUrl := fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", testTenantUUID) + dk.Spec.APIURL = apiUrl + + objs := []client.Object{ + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: consts.TelemetryApiCredentialsSecretName, + Namespace: dk.Namespace, + }, + }, + } + + clt := schemeFake.NewClient(objs...) + r := NewReconciler(clt, clt, &dk) + + endpoint, err := r.getDtEndpoint() + require.NoError(t, err) + assert.Equal(t, apiUrl+"/v2/otlp", string(endpoint)) + }) +} + func createDynaKube(telemetryIngestEnabled bool) dynakube.DynaKube { dk := dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ From af81691f2d8675f147103556da98d646a3759eb6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 19:10:15 +0000 Subject: [PATCH 290/426] chore(deps): update github/codeql-action action to v3.28.11 (main) (#4563) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 4bef96e574..be61997a27 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 + uses: github/codeql-action/init@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 + uses: github/codeql-action/autobuild@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 + uses: github/codeql-action/analyze@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index a6555eb42e..7255650d2a 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 + uses: github/codeql-action/upload-sarif@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 with: sarif_file: results.sarif From 2d4043cba631fb318732e120615e09931d94a73b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 13:41:34 +0000 Subject: [PATCH 291/426] fix(deps): update module sigs.k8s.io/controller-runtime to v0.20.3 (main) (#4564) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 56ee09a46b..3f99c36773 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( k8s.io/client-go v0.32.2 k8s.io/mount-utils v0.32.2 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - sigs.k8s.io/controller-runtime v0.20.2 + sigs.k8s.io/controller-runtime v0.20.3 sigs.k8s.io/e2e-framework v0.3.0 sigs.k8s.io/yaml v1.4.0 ) diff --git a/go.sum b/go.sum index 0794f772b4..95d4f0ad1a 100644 --- a/go.sum +++ b/go.sum @@ -397,8 +397,8 @@ k8s.io/mount-utils v0.32.2 h1:aDwp+ucWiVnDr/LpRg88/dsXf/vm6gI1VZkYH3+3+Vw= k8s.io/mount-utils v0.32.2/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.20.2 h1:/439OZVxoEc02psi1h4QO3bHzTgu49bb347Xp4gW1pc= -sigs.k8s.io/controller-runtime v0.20.2/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= +sigs.k8s.io/controller-runtime v0.20.3 h1:I6Ln8JfQjHH7JbtCD2HCYHoIzajoRxPNuvhvcDbZgkI= +sigs.k8s.io/controller-runtime v0.20.3/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= From 1fc35bdc650995f188495862f2092478d60bca87 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 08:29:34 +0000 Subject: [PATCH 292/426] chore(deps): update module github.com/vektra/mockery to v2.53.1 (main) (#4565) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 7f76564780..4bf81ad046 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.31.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.53.0 +mockery_version=v2.53.1 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest From a8462c502222e1ff625b33537a1c7c16ea2d8234 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Mon, 10 Mar 2025 09:56:57 +0100 Subject: [PATCH 293/426] Handle unexpected error in kspm token generation (#4561) --- .../dynakube/kspm/token/reconciler.go | 4 +++ .../dynakube/kspm/token/reconciler_test.go | 33 +++++++++++++++++++ pkg/util/kubeobjects/internal/query/query.go | 2 +- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/pkg/controllers/dynakube/kspm/token/reconciler.go b/pkg/controllers/dynakube/kspm/token/reconciler.go index 6be82a311b..0aeafc9458 100644 --- a/pkg/controllers/dynakube/kspm/token/reconciler.go +++ b/pkg/controllers/dynakube/kspm/token/reconciler.go @@ -74,6 +74,10 @@ func ensureKSPMSecret(ctx context.Context, client client.Client, apiReader clien dk.KSPM().TokenSecretHash = tokenHash conditions.SetSecretCreated(dk.Conditions(), kspmConditionType, dk.KSPM().GetTokenSecretName()) + } else if err != nil { + conditions.SetKubeApiError(dk.Conditions(), kspmConditionType, err) + + return err } return nil diff --git a/pkg/controllers/dynakube/kspm/token/reconciler_test.go b/pkg/controllers/dynakube/kspm/token/reconciler_test.go index 635da14da5..59010e66d2 100644 --- a/pkg/controllers/dynakube/kspm/token/reconciler_test.go +++ b/pkg/controllers/dynakube/kspm/token/reconciler_test.go @@ -2,6 +2,7 @@ package token import ( "context" + "errors" "testing" dtfake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" @@ -16,6 +17,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/client/interceptor" ) func TestTokenCreation(t *testing.T) { @@ -38,6 +40,16 @@ func TestTokenCreation(t *testing.T) { assert.NotEmpty(t, dk.KSPM().TokenSecretHash) }) + t.Run("unexpected error -> return error", func(t *testing.T) { + clt := createFailK8sClient(t) + + dk := createDynaKube(true) + + err := ensureKSPMSecret(ctx, clt, clt, &dk) + require.Error(t, err) + assert.Equal(t, conditions.KubeApiErrorReason, meta.FindStatusCondition(*dk.Conditions(), kspmConditionType).Reason) + }) + t.Run("removes secret if exists", func(t *testing.T) { dk := createDynaKube(false) dk.KSPM().TokenSecretHash = "something" @@ -71,6 +83,27 @@ func TestTokenCreation(t *testing.T) { }) } +func createFailK8sClient(t *testing.T) client.Client { + t.Helper() + + boomClient := dtfake.NewClientWithInterceptors(interceptor.Funcs{ + Create: func(ctx context.Context, client client.WithWatch, obj client.Object, opts ...client.CreateOption) error { + return errors.New("BOOM") + }, + Delete: func(ctx context.Context, client client.WithWatch, obj client.Object, opts ...client.DeleteOption) error { + return errors.New("BOOM") + }, + Update: func(ctx context.Context, client client.WithWatch, obj client.Object, opts ...client.UpdateOption) error { + return errors.New("BOOM") + }, + Get: func(ctx context.Context, client client.WithWatch, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { + return errors.New("BOOM") + }, + }) + + return boomClient +} + func createDynaKube(kspmEnabled bool) dynakube.DynaKube { dk := dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/util/kubeobjects/internal/query/query.go b/pkg/util/kubeobjects/internal/query/query.go index 10e8ac83d3..c4db09c1b2 100644 --- a/pkg/util/kubeobjects/internal/query/query.go +++ b/pkg/util/kubeobjects/internal/query/query.go @@ -38,7 +38,7 @@ func (c Generic[T, L]) WithOwner(owner client.Object) Generic[T, L] { func (c Generic[T, L]) Get(ctx context.Context, objectKey client.ObjectKey) (T, error) { err := c.KubeReader.Get(ctx, objectKey, c.Target) - return c.Target, err + return c.Target, errors.WithStack(err) } func (c Generic[T, L]) Create(ctx context.Context, object T) error { From 8a8310b37b692ea243b291f9b62222ecac981893 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Mon, 10 Mar 2025 12:31:12 +0100 Subject: [PATCH 294/426] Fix ag capabilities for telemetry ingest (#4566) --- .../dynakube/activegate/capability/capability.go | 4 ++-- .../dynakube/activegate/capability/capability_test.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/controllers/dynakube/activegate/capability/capability.go b/pkg/controllers/dynakube/activegate/capability/capability.go index 2e2a585aae..76b3b92148 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability.go +++ b/pkg/controllers/dynakube/activegate/capability/capability.go @@ -104,8 +104,8 @@ func NewMultiCapability(dk *dynakube.DynaKube) Capability { } if dk.IsOTLPingestEnabled() || dk.TelemetryIngest().IsEnabled() { - capabilityNames = append(capabilityNames, "log_analytics_collector", "generic_ingest_enabled", "otlp_ingest") - capabilityDisplayNames = append(capabilityDisplayNames, "log_analytics_collector", "generic_ingest_enabled", "otlp_ingest") + capabilityNames = append(capabilityNames, "log_analytics_collector_enabled", "generic_ingest_enabled", "otlp_ingest") + capabilityDisplayNames = append(capabilityDisplayNames, "log_analytics_collector_enabled", "generic_ingest_enabled", "otlp_ingest") } mc.argName = strings.Join(capabilityNames, ",") diff --git a/pkg/controllers/dynakube/activegate/capability/capability_test.go b/pkg/controllers/dynakube/activegate/capability/capability_test.go index 4b83dbc5e9..2cc8ca027c 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability_test.go +++ b/pkg/controllers/dynakube/activegate/capability/capability_test.go @@ -21,10 +21,10 @@ const ( expectedArgNameWithDebugging = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,debugging" expectedArgNameWithExtensions = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller" expectedArgNameWithExtensionsOnly = "extension_controller" - expectedArgNameWithOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest_enabled,otlp_ingest" - expectedArgNameWithOTLPingestOnly = "log_analytics_collector,generic_ingest_enabled,otlp_ingest" - expectedArgNameWithExtensionsAndOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller,log_analytics_collector,generic_ingest_enabled,otlp_ingest" - expectedArgNameWithTelemetryIngest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest_enabled,otlp_ingest" + expectedArgNameWithOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector_enabled,generic_ingest_enabled,otlp_ingest" + expectedArgNameWithOTLPingestOnly = "log_analytics_collector_enabled,generic_ingest_enabled,otlp_ingest" + expectedArgNameWithExtensionsAndOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller,log_analytics_collector_enabled,generic_ingest_enabled,otlp_ingest" + expectedArgNameWithTelemetryIngest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector_enabled,generic_ingest_enabled,otlp_ingest" ) var capabilities = []activegate.CapabilityDisplayName{ From f95746e7dceb0eca63ef5f938bc5ae951995cb22 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 13:48:15 +0000 Subject: [PATCH 295/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1741600006 (main) (#4567) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b5b7b8d0d1..f25064f46d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739776878@sha256:d115f8aad9c4ae7ee21ae75bbcb3dc2c5dbf9b57bf6dad6dcb5aac5c02003bde AS base -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1739751568@sha256:d342aa80781bf41c4c73485c41d8f1e2dbc40ee491633d9cafe787c361dd44ff AS dependency +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1741600006@sha256:b88227436597e960f70db8eadcaf18ffa5b6d1a615888f709dcae3fba1540c61 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 0f7922703697f44e9f82305c13208413d3f7cad3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 22:20:56 +0000 Subject: [PATCH 296/426] chore(deps): update module github.com/vektra/mockery to v2.53.2 (main) (#4571) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 4bf81ad046..f48ac66709 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.31.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.53.1 +mockery_version=v2.53.2 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest From f79df31dedb42073609b43ff2b21d1243c75ecf4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 02:00:07 +0000 Subject: [PATCH 297/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1741626669 (main) (#4572) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f25064f46d..6f4dbf0b23 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1739776878@sha256:d115f8aad9c4ae7ee21ae75bbcb3dc2c5dbf9b57bf6dad6dcb5aac5c02003bde AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1741626669@sha256:91828a5ca154132e18072cf885f6bb41bb881e6158f30b793f4b424ec144b87d AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1741600006@sha256:b88227436597e960f70db8eadcaf18ffa5b6d1a615888f709dcae3fba1540c61 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From 4a557a8f62261f199efd191765562e286c1a68c7 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Tue, 11 Mar 2025 09:57:42 +0100 Subject: [PATCH 298/426] Fix Endpoint URL generation to also work with managed API urls. (#4569) --- .../dynakube/otelc/secret/reconciler.go | 2 +- .../dynakube/otelc/secret/reconciler_test.go | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler.go b/pkg/controllers/dynakube/otelc/secret/reconciler.go index 0f5f5fc106..0dba9a61c8 100644 --- a/pkg/controllers/dynakube/otelc/secret/reconciler.go +++ b/pkg/controllers/dynakube/otelc/secret/reconciler.go @@ -92,7 +92,7 @@ func (r *Reconciler) getDtEndpoint() ([]byte, error) { return []byte(fmt.Sprintf("https://%s-activegate.dynatrace.svc/e/%s/api/v2/otlp", r.dk.Name, tenantUUID)), nil } - return []byte(fmt.Sprintf("https://%s/api/v2/otlp", r.dk.ApiUrlHost())), nil + return []byte(r.dk.ApiUrl() + "/v2/otlp"), nil } func (r *Reconciler) generateTelemetryIngestApiCredentialsSecret(name string) (secret *corev1.Secret, err error) { diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler_test.go b/pkg/controllers/dynakube/otelc/secret/reconciler_test.go index 505a6f21ec..2ced4814ee 100644 --- a/pkg/controllers/dynakube/otelc/secret/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/secret/reconciler_test.go @@ -133,6 +133,28 @@ func TestEndpoint(t *testing.T) { require.NoError(t, err) assert.Equal(t, apiUrl+"/v2/otlp", string(endpoint)) }) + + t.Run("managed ActiveGate", func(t *testing.T) { + dk := createDynaKube(true) + apiUrl := "https://dynatrace.foobar.com/e/abcdefgh-1234-5678-9abc-deadbeef/api" + dk.Spec.APIURL = apiUrl + + objs := []client.Object{ + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: consts.TelemetryApiCredentialsSecretName, + Namespace: dk.Namespace, + }, + }, + } + + clt := schemeFake.NewClient(objs...) + r := NewReconciler(clt, clt, &dk) + + endpoint, err := r.getDtEndpoint() + require.NoError(t, err) + assert.Equal(t, apiUrl+"/v2/otlp", string(endpoint)) + }) } func createDynaKube(telemetryIngestEnabled bool) dynakube.DynaKube { From 31974a5c4667ff6e2818988a831001038e2ab9d4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 21:32:19 +0000 Subject: [PATCH 299/426] chore(deps): update dependency python to 3.13 (main) (#4577) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/self-update-on-new-release-version.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/self-update-on-new-release-version.yaml b/.github/workflows/self-update-on-new-release-version.yaml index 8cdae74ed0..359f01e3ca 100644 --- a/.github/workflows/self-update-on-new-release-version.yaml +++ b/.github/workflows/self-update-on-new-release-version.yaml @@ -19,7 +19,7 @@ jobs: - name: Install Python uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 with: - python-version: '3.12' + python-version: '3.13' - name: Install python requirements run: make prerequisites/python - name: Find last 3 release branches From bf9e524291bb538cd72f3be6661465011992d0c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 12:05:38 +0000 Subject: [PATCH 300/426] fix(deps): update kubernetes packages to v0.32.3 (main) (#4579) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 3f99c36773..4bfebc8d50 100644 --- a/go.mod +++ b/go.mod @@ -31,11 +31,11 @@ require ( gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.25.0 istio.io/client-go v1.25.0 - k8s.io/api v0.32.2 - k8s.io/apiextensions-apiserver v0.32.2 - k8s.io/apimachinery v0.32.2 - k8s.io/client-go v0.32.2 - k8s.io/mount-utils v0.32.2 + k8s.io/api v0.32.3 + k8s.io/apiextensions-apiserver v0.32.3 + k8s.io/apimachinery v0.32.3 + k8s.io/client-go v0.32.3 + k8s.io/mount-utils v0.32.3 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.20.3 sigs.k8s.io/e2e-framework v0.3.0 diff --git a/go.sum b/go.sum index 95d4f0ad1a..41809a960b 100644 --- a/go.sum +++ b/go.sum @@ -381,20 +381,20 @@ istio.io/api v1.25.0 h1:UVQNFUAz4R06NagA+QpEzLmi4sw+m+UuMgD6sIyXawA= istio.io/api v1.25.0/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= istio.io/client-go v1.25.0 h1:MMG8r1g+o2yEzVwi0AGSdB6EQyLEhYz8YMYQQIw8IZw= istio.io/client-go v1.25.0/go.mod h1:Y4qIjNIVCkpZMiq/e3C7tMjOm7aYUbxT6ebtmai1TRY= -k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= -k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= -k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4= -k8s.io/apiextensions-apiserver v0.32.2/go.mod h1:GPwf8sph7YlJT3H6aKUWtd0E+oyShk/YHWQHf/OOgCA= -k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= -k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= -k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= +k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= +k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= +k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= +k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= +k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= +k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= +k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/mount-utils v0.32.2 h1:aDwp+ucWiVnDr/LpRg88/dsXf/vm6gI1VZkYH3+3+Vw= -k8s.io/mount-utils v0.32.2/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= +k8s.io/mount-utils v0.32.3 h1:ZPXXHblfBhYP89OnaozpFg9Ojl6HhDfxBLcdWNkaxW8= +k8s.io/mount-utils v0.32.3/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.20.3 h1:I6Ln8JfQjHH7JbtCD2HCYHoIzajoRxPNuvhvcDbZgkI= From 088217ef602a9cfff6ac6e4b8dbf6221ca2dddf0 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Wed, 12 Mar 2025 14:53:12 +0100 Subject: [PATCH 301/426] Introduce new DynaKube API version v1beta4 (#4529) --- .testcoverage.yml | 2 +- .../v1beta4/applicationMonitoring.yaml | 18 + .../dynakube/v1beta4/classicFullStack.yaml | 18 + .../v1beta4/cloudNativeFullStack.yaml | 18 + .../dynakube/v1beta4/hostMonitoring.yaml | 18 + .../v1beta4/kubernetesObservability.yaml | 15 + .../kubernetesSecurityPostureManagement.yaml | 32 + .../dynakube/v1beta4/logMonitoring.yaml | 28 + .../dynakube/v1beta4/multipleDynakubes.yaml | 49 + cmd/support_archive/resource_query.go | 6 +- cmd/support_archive/resources_test.go | 2 +- cmd/support_archive/troubleshoot_test.go | 2 +- cmd/troubleshoot/builder.go | 2 +- cmd/troubleshoot/builder_test.go | 2 +- cmd/troubleshoot/component.go | 2 +- cmd/troubleshoot/dynakube.go | 2 +- cmd/troubleshoot/dynakube_test.go | 6 +- cmd/troubleshoot/image.go | 2 +- cmd/troubleshoot/image_test.go | 6 +- cmd/troubleshoot/proxy.go | 2 +- cmd/troubleshoot/proxy_test.go | 2 +- cmd/webhook/builder.go | 66 +- config/crd/bases/dynatrace.com_dynakubes.yaml | 3225 +++++++++++++++++ .../Common/crd/dynatrace-operator-crd.yaml | 3225 +++++++++++++++++ .../validatingwebhookconfiguration.yaml | 21 + .../validatingwebhookconfiguration_test.yaml | 21 + doc/api/feature-flags.md | 4 +- hack/doc/gen_feature_flags.sh | 2 +- pkg/api/scheme/scheme.go | 3 + pkg/api/v1beta1/dynakube/convert_from.go | 4 +- pkg/api/v1beta1/dynakube/convert_from_test.go | 51 +- pkg/api/v1beta1/dynakube/convert_to.go | 6 +- pkg/api/v1beta1/dynakube/convert_to_test.go | 2 +- pkg/api/v1beta2/dynakube/convert_from.go | 4 +- pkg/api/v1beta2/dynakube/convert_from_test.go | 82 +- pkg/api/v1beta2/dynakube/convert_to.go | 6 +- pkg/api/v1beta2/dynakube/convert_to_test.go | 2 +- pkg/api/v1beta3/dynakube/activegate/props.go | 4 - pkg/api/v1beta3/dynakube/activegate/spec.go | 7 - .../activegate/zz_generated.deepcopy.go | 5 - pkg/api/v1beta3/dynakube/activegate_props.go | 1 - pkg/api/v1beta3/dynakube/convert_from.go | 293 ++ pkg/api/v1beta3/dynakube/convert_from_test.go | 960 +++++ pkg/api/v1beta3/dynakube/convert_to.go | 294 ++ pkg/api/v1beta3/dynakube/convert_to_test.go | 707 ++++ pkg/api/v1beta3/dynakube/dynakube_status.go | 11 - pkg/api/v1beta3/dynakube/dynakube_types.go | 8 - .../v1beta3/dynakube/zz_generated.deepcopy.go | 6 - pkg/api/v1beta4/dynakube/activegate/props.go | 154 + pkg/api/v1beta4/dynakube/activegate/spec.go | 182 + pkg/api/v1beta4/dynakube/activegate/status.go | 28 + .../activegate/zz_generated.deepcopy.go | 141 + pkg/api/v1beta4/dynakube/activegate_props.go | 18 + pkg/api/v1beta4/dynakube/certs.go | 66 + .../dynakube/conversion.go | 0 pkg/api/v1beta4/dynakube/dynakube_props.go | 110 + .../v1beta4/dynakube/dynakube_props_test.go | 118 + pkg/api/v1beta4/dynakube/dynakube_status.go | 123 + pkg/api/v1beta4/dynakube/dynakube_types.go | 182 + pkg/api/v1beta4/dynakube/dynakube_webhook.go | 13 + pkg/api/v1beta4/dynakube/extensions.go | 88 + pkg/api/v1beta4/dynakube/extensions_props.go | 49 + pkg/api/v1beta4/dynakube/feature_flags.go | 304 ++ .../v1beta4/dynakube/feature_flags_test.go | 321 ++ pkg/api/v1beta4/dynakube/kspm/props.go | 17 + pkg/api/v1beta4/dynakube/kspm/spec.go | 80 + .../dynakube/kspm/zz_generated.deepcopy.go | 117 + pkg/api/v1beta4/dynakube/kspm_props.go | 14 + .../logmonitoring/ingestrulematchers.go | 10 + .../v1beta4/dynakube/logmonitoring/props.go | 42 + .../v1beta4/dynakube/logmonitoring/spec.go | 66 + .../logmonitoring/zz_generated.deepcopy.go | 115 + .../v1beta4/dynakube/logmonitoring_props.go | 16 + pkg/api/v1beta4/dynakube/metada_enrichment.go | 13 + .../dynakube/metadata_enrichment_props.go | 13 + pkg/api/v1beta4/dynakube/oneagent/props.go | 327 ++ .../v1beta4/dynakube/oneagent/props_test.go | 386 ++ pkg/api/v1beta4/dynakube/oneagent/spec.go | 165 + pkg/api/v1beta4/dynakube/oneagent/status.go | 58 + .../oneagent/zz_generated.deepcopy.go | 274 ++ pkg/api/v1beta4/dynakube/oneagent_props.go | 18 + .../dynakube/otelc_props.go | 2 - .../dynakube/otelc_props_test.go | 2 +- .../dynakube/otlp_props.go | 0 pkg/api/v1beta4/dynakube/proxy.go | 81 + .../dynakube/telemetryingest/props.go | 0 .../dynakube/telemetryingest/spec.go | 0 .../telemetryingest/zz_generated.deepcopy.go | 0 .../dynakube/telemetryservice_props.go | 2 +- pkg/api/v1beta4/dynakube/test/certs_test.go | 107 + pkg/api/v1beta4/dynakube/test/proxy_test.go | 61 + .../v1beta4/dynakube/zz_generated.deepcopy.go | 376 ++ pkg/api/v1beta4/groupversion_info.go | 34 + pkg/api/validation/dynakube/activegate.go | 4 +- .../validation/dynakube/activegate_test.go | 4 +- pkg/api/validation/dynakube/api_url.go | 2 +- pkg/api/validation/dynakube/api_url_test.go | 2 +- pkg/api/validation/dynakube/csi_daemonset.go | 2 +- .../validation/dynakube/csi_daemonset_test.go | 4 +- pkg/api/validation/dynakube/dynakube_name.go | 2 +- .../validation/dynakube/dynakube_name_test.go | 2 +- pkg/api/validation/dynakube/eec.go | 2 +- pkg/api/validation/dynakube/eec_test.go | 4 +- pkg/api/validation/dynakube/extensions.go | 2 +- .../validation/dynakube/extensions_test.go | 4 +- pkg/api/validation/dynakube/featureflag.go | 2 +- .../validation/dynakube/featureflag_test.go | 2 +- pkg/api/validation/dynakube/image.go | 2 +- pkg/api/validation/dynakube/image_test.go | 6 +- pkg/api/validation/dynakube/istio.go | 2 +- pkg/api/validation/dynakube/istio_test.go | 2 +- pkg/api/validation/dynakube/kspm.go | 2 +- pkg/api/validation/dynakube/kspm_test.go | 6 +- pkg/api/validation/dynakube/logmonitoring.go | 2 +- .../validation/dynakube/logmonitoring_test.go | 8 +- pkg/api/validation/dynakube/module_test.go | 10 +- pkg/api/validation/dynakube/modules.go | 2 +- .../validation/dynakube/namespace_selector.go | 2 +- .../dynakube/namespace_selector_test.go | 4 +- pkg/api/validation/dynakube/oneagent.go | 2 +- pkg/api/validation/dynakube/oneagent_test.go | 4 +- pkg/api/validation/dynakube/preview_test.go | 4 +- pkg/api/validation/dynakube/proxy_url.go | 2 +- pkg/api/validation/dynakube/proxy_url_test.go | 2 +- .../validation/dynakube/telemetryservice.go | 2 +- .../dynakube/telemetryservice_test.go | 4 +- pkg/api/validation/dynakube/validation.go | 8 +- .../validation/dynakube/validation_test.go | 6 +- pkg/clients/dynatrace/client.go | 2 +- pkg/clients/dynatrace/processmoduleconfig.go | 2 +- pkg/clients/dynatrace/settings_enrichment.go | 2 +- .../dynatrace/settings_enrichment_test.go | 2 +- .../dynatrace/settings_logmonitoring.go | 2 +- .../dynatrace/settings_logmonitoring_test.go | 4 +- .../csi/driver/volumes/volume_config.go | 2 +- pkg/controllers/csi/metadata/correctness.go | 2 +- .../csi/provisioner/cleanup/binaries.go | 2 +- .../csi/provisioner/cleanup/binaries_test.go | 4 +- .../csi/provisioner/cleanup/hostmounts.go | 2 +- .../provisioner/cleanup/hostmounts_test.go | 4 +- pkg/controllers/csi/provisioner/controller.go | 2 +- .../csi/provisioner/controller_test.go | 4 +- pkg/controllers/csi/provisioner/install.go | 2 +- pkg/controllers/dynakube/activegate.go | 2 +- .../activegate/capability/capability.go | 4 +- .../activegate/capability/capability_test.go | 6 +- .../internal/authtoken/reconciler.go | 2 +- .../internal/authtoken/reconciler_test.go | 4 +- .../internal/capability/reconciler.go | 2 +- .../internal/capability/reconciler_test.go | 4 +- .../activegate/internal/capability/service.go | 2 +- .../internal/capability/service_test.go | 4 +- .../internal/customproperties/reconciler.go | 2 +- .../customproperties/reconciler_test.go | 2 +- .../builder/modifiers/authtoken.go | 2 +- .../statefulset/builder/modifiers/certs.go | 2 +- .../builder/modifiers/certs_test.go | 2 +- .../statefulset/builder/modifiers/config.go | 2 +- .../builder/modifiers/config_test.go | 4 +- .../builder/modifiers/customprops.go | 2 +- .../builder/modifiers/customprops_test.go | 2 +- .../statefulset/builder/modifiers/eec.go | 2 +- .../statefulset/builder/modifiers/eec_test.go | 2 +- .../statefulset/builder/modifiers/kspm.go | 4 +- .../builder/modifiers/kspm_test.go | 4 +- .../statefulset/builder/modifiers/kubemon.go | 2 +- .../builder/modifiers/kubemon_test.go | 2 +- .../statefulset/builder/modifiers/proxy.go | 2 +- .../builder/modifiers/proxy_test.go | 2 +- .../statefulset/builder/modifiers/rawimage.go | 2 +- .../statefulset/builder/modifiers/readonly.go | 2 +- .../builder/modifiers/serviceport.go | 2 +- .../builder/modifiers/ssl_volume.go | 2 +- .../builder/modifiers/trustedcas_volume.go | 2 +- .../internal/statefulset/reconciler.go | 2 +- .../internal/statefulset/reconciler_test.go | 4 +- .../internal/statefulset/statefulset.go | 2 +- .../internal/statefulset/statefulset_test.go | 6 +- .../activegate/internal/tls/reconciler.go | 2 +- .../internal/tls/reconciler_test.go | 4 +- .../dynakube/activegate/reconciler.go | 2 +- .../dynakube/activegate/reconciler_test.go | 4 +- pkg/controllers/dynakube/activegate_test.go | 4 +- .../dynakube/apimonitoring/reconciler.go | 2 +- .../dynakube/apimonitoring/reconciler_test.go | 4 +- pkg/controllers/dynakube/conditions.go | 2 +- .../activegate/communication_hosts.go | 2 +- .../activegate/communication_hosts_test.go | 4 +- .../connectioninfo/activegate/reconciler.go | 2 +- .../activegate/reconciler_test.go | 4 +- .../oneagent/communication_hosts.go | 2 +- .../oneagent/communication_hosts_test.go | 4 +- .../connectioninfo/oneagent/reconciler.go | 4 +- .../oneagent/reconciler_test.go | 4 +- pkg/controllers/dynakube/controller.go | 2 +- .../dynakube/controller_system_test.go | 8 +- pkg/controllers/dynakube/controller_test.go | 6 +- .../deploymentmetadata/deploymentmetadata.go | 2 +- .../deploymentmetadata_test.go | 4 +- .../dynakube/deploymentmetadata/reconciler.go | 2 +- .../deploymentmetadata/reconciler_test.go | 6 +- pkg/controllers/dynakube/dtpullsecret/find.go | 2 +- .../dynakube/dtpullsecret/find_test.go | 2 +- .../dynakube/dtpullsecret/generate_test.go | 4 +- .../dynakube/dtpullsecret/reconciler.go | 2 +- .../dynakube/dtpullsecret/reconciler_test.go | 4 +- .../dynakube/dynatraceclient/builder.go | 2 +- .../dynakube/dynatraceclient/builder_test.go | 2 +- .../dynakube/dynatraceclient/options.go | 2 +- .../dynakube/dynatraceclient/options_test.go | 2 +- .../dynakube/extension/eec/reconciler.go | 2 +- .../dynakube/extension/eec/reconciler_test.go | 4 +- .../dynakube/extension/eec/statefulset.go | 2 +- .../dynakube/extension/reconciler.go | 2 +- .../dynakube/extension/reconciler_test.go | 4 +- .../dynakube/extension/tls/reconciler.go | 2 +- .../dynakube/extension/tls/reconciler_test.go | 4 +- .../dynakube/injection/reconciler.go | 2 +- .../dynakube/injection/reconciler_test.go | 4 +- pkg/controllers/dynakube/istio/reconciler.go | 2 +- .../dynakube/istio/reconciler_test.go | 6 +- .../dynakube/kspm/daemonset/certs.go | 2 +- .../dynakube/kspm/daemonset/certs_test.go | 4 +- .../dynakube/kspm/daemonset/container.go | 2 +- .../dynakube/kspm/daemonset/container_test.go | 2 +- .../dynakube/kspm/daemonset/env.go | 2 +- .../dynakube/kspm/daemonset/env_test.go | 2 +- .../dynakube/kspm/daemonset/reconciler.go | 2 +- .../kspm/daemonset/reconciler_test.go | 6 +- .../dynakube/kspm/daemonset/volumes.go | 4 +- .../dynakube/kspm/daemonset/volumes_test.go | 2 +- pkg/controllers/dynakube/kspm/reconciler.go | 2 +- .../dynakube/kspm/token/reconciler.go | 4 +- .../dynakube/kspm/token/reconciler_test.go | 4 +- .../logmonitoring/configsecret/reconciler.go | 2 +- .../configsecret/reconciler_test.go | 6 +- .../dynakube/logmonitoring/daemonset/args.go | 2 +- .../logmonitoring/daemonset/args_test.go | 4 +- .../logmonitoring/daemonset/container.go | 2 +- .../logmonitoring/daemonset/container_test.go | 4 +- .../dynakube/logmonitoring/daemonset/env.go | 2 +- .../logmonitoring/daemonset/env_test.go | 2 +- .../logmonitoring/daemonset/reconciler.go | 2 +- .../daemonset/reconciler_test.go | 6 +- .../logmonsettings/reconciler.go | 4 +- .../logmonsettings/reconciler_test.go | 4 +- .../dynakube/logmonitoring/reconciler.go | 2 +- .../dynakube/logmonitoring/reconciler_test.go | 4 +- .../dynakube/metadata/rules/reconciler.go | 2 +- .../metadata/rules/reconciler_test.go | 2 +- .../dynakube/monitoredentities/reconciler.go | 2 +- .../monitoredentities/reconciler_test.go | 2 +- .../oneagent/daemonset/affinity_test.go | 2 +- .../oneagent/daemonset/arguments_test.go | 6 +- .../dynakube/oneagent/daemonset/daemonset.go | 4 +- .../oneagent/daemonset/daemonset_test.go | 4 +- .../dynakube/oneagent/daemonset/env_vars.go | 2 +- .../oneagent/daemonset/env_vars_test.go | 6 +- .../dynakube/oneagent/daemonset/volumes.go | 2 +- .../oneagent/daemonset/volumes_test.go | 6 +- .../dynakube/oneagent/oneagent_reconciler.go | 4 +- .../oneagent/oneagent_reconciler_test.go | 4 +- .../otelc/configuration/reconciler.go | 2 +- .../otelc/configuration/reconciler_test.go | 4 +- pkg/controllers/dynakube/otelc/reconciler.go | 2 +- .../dynakube/otelc/secret/reconciler.go | 2 +- .../dynakube/otelc/secret/reconciler_test.go | 6 +- .../dynakube/otelc/service/reconciler.go | 2 +- .../dynakube/otelc/service/reconciler_test.go | 4 +- .../dynakube/otelc/statefulset/container.go | 2 +- .../otelc/statefulset/container_test.go | 2 +- .../dynakube/otelc/statefulset/env.go | 2 +- .../dynakube/otelc/statefulset/env_test.go | 2 +- .../dynakube/otelc/statefulset/reconciler.go | 2 +- .../otelc/statefulset/reconciler_test.go | 2 +- .../dynakube/otelc/statefulset/volumes.go | 2 +- .../otelc/statefulset/volumes_test.go | 6 +- pkg/controllers/dynakube/phase.go | 2 +- pkg/controllers/dynakube/phase_test.go | 10 +- .../processmoduleconfigsecret/reconciler.go | 2 +- .../reconciler_test.go | 4 +- pkg/controllers/dynakube/proxy/reconciler.go | 2 +- .../dynakube/proxy/reconciler_test.go | 4 +- pkg/controllers/dynakube/token/feature.go | 2 +- .../dynakube/token/feature_test.go | 2 +- pkg/controllers/dynakube/token/reader.go | 2 +- pkg/controllers/dynakube/token/reader_test.go | 2 +- pkg/controllers/dynakube/token/token.go | 2 +- pkg/controllers/dynakube/token/tokens.go | 2 +- pkg/controllers/dynakube/token/tokens_test.go | 4 +- .../dynakube/version/activegate.go | 2 +- .../dynakube/version/activegate_test.go | 4 +- .../dynakube/version/codemodules.go | 4 +- .../dynakube/version/codemodules_test.go | 4 +- pkg/controllers/dynakube/version/oneagent.go | 2 +- .../dynakube/version/oneagent_test.go | 4 +- .../dynakube/version/reconciler.go | 2 +- .../dynakube/version/reconciler_test.go | 6 +- .../dynakube/version/updater_test.go | 2 +- pkg/controllers/nodes/nodes_controller.go | 2 +- .../nodes/nodes_controller_test.go | 4 +- pkg/controllers/nodes/oneagent_dao.go | 2 +- .../codemodule/installer/image/installer.go | 2 +- .../installer/image/installer_test.go | 2 +- .../installer/job/bootstrapper_test.go | 2 +- .../installer/job/installer_test.go | 2 +- .../bootstrapperconfig/bootstrapperconfig.go | 2 +- .../bootstrapperconfig_test.go | 4 +- .../namespace/bootstrapperconfig/endpoints.go | 2 +- .../namespace/bootstrapperconfig/pmc.go | 2 +- .../namespace/ingestendpoint/secret.go | 2 +- .../namespace/ingestendpoint/secret_test.go | 4 +- .../initgeneration/initgeneration.go | 2 +- .../initgeneration/initgeneration_test.go | 6 +- pkg/injection/namespace/mapper/dynakubes.go | 2 +- .../namespace/mapper/dynakubes_test.go | 2 +- pkg/injection/namespace/mapper/mapper.go | 2 +- pkg/injection/namespace/mapper/mapper_test.go | 4 +- pkg/injection/namespace/mapper/namespaces.go | 2 +- .../namespace/mapper/namespaces_test.go | 2 +- pkg/oci/registry/client.go | 2 +- pkg/oci/registry/client_test.go | 4 +- pkg/util/conditions/time.go | 2 +- pkg/util/conditions/time_test.go | 2 +- pkg/util/kubeobjects/activegate/capability.go | 4 +- .../mutation/namespace/webhook_test.go | 4 +- pkg/webhook/mutation/pod/events.go | 2 +- pkg/webhook/mutation/pod/init_container.go | 2 +- .../mutation/pod/init_container_test.go | 4 +- .../mutation/pod/metadata/annotations.go | 2 +- .../mutation/pod/metadata/annotations_test.go | 2 +- .../mutation/pod/metadata/mutator_test.go | 6 +- .../mutation/pod/oneagent/annotations.go | 2 +- .../mutation/pod/oneagent/containers_test.go | 2 +- pkg/webhook/mutation/pod/oneagent/env.go | 2 +- pkg/webhook/mutation/pod/oneagent/env_test.go | 4 +- .../mutation/pod/oneagent/mutator_test.go | 6 +- pkg/webhook/mutation/pod/oneagent/volumes.go | 2 +- .../mutation/pod/oneagent/volumes_test.go | 4 +- pkg/webhook/mutation/pod/request.go | 2 +- pkg/webhook/mutation/pod/request_test.go | 2 +- pkg/webhook/mutation/pod/webhook_test.go | 4 +- pkg/webhook/mutator.go | 2 +- test/features/activegate/activegate.go | 2 +- test/features/activegate/curl.go | 2 +- .../label_version_detection.go | 4 +- .../metadata_enrichment.go | 2 +- .../read_only_csi_volume.go | 4 +- .../applicationmonitoring/without_csi.go | 2 +- test/features/classic/classic.go | 2 +- .../classic/switch_modes/switch_modes.go | 2 +- .../cloudnative/codemodules/codemodules.go | 4 +- test/features/cloudnative/container.go | 2 +- .../disabled_auto_injection.go | 2 +- test/features/cloudnative/init_containers.go | 2 +- .../cloudnative/switch_modes/switch_modes.go | 2 +- test/features/cloudnative/upgrade/upgrade.go | 4 +- test/features/extensions/extensions.go | 2 +- test/features/support_archive/files.go | 2 +- .../support_archive/support_archive.go | 4 +- .../components/activegate/installation.go | 2 +- .../components/codemodules/codemodules.go | 2 +- test/helpers/components/dynakube/dynakube.go | 8 +- test/helpers/components/dynakube/options.go | 6 +- test/helpers/components/oneagent/daemonset.go | 4 +- test/helpers/components/oneagent/uninstall.go | 2 +- test/helpers/curl/curl.go | 2 +- test/helpers/istio/install.go | 2 +- test/helpers/proxy/proxy.go | 2 +- test/helpers/scheme.go | 8 +- test/mocks/pkg/clients/dynatrace/client.go | 2 +- .../dynakube/dynatraceclient/builder.go | 2 +- .../controllers/dynakube/istio/reconciler.go | 2 +- .../dynakube/version/reconciler.go | 2 +- test/scenarios/release/release_test.go | 2 +- 375 files changed, 13840 insertions(+), 553 deletions(-) create mode 100644 assets/samples/dynakube/v1beta4/applicationMonitoring.yaml create mode 100644 assets/samples/dynakube/v1beta4/classicFullStack.yaml create mode 100644 assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml create mode 100644 assets/samples/dynakube/v1beta4/hostMonitoring.yaml create mode 100644 assets/samples/dynakube/v1beta4/kubernetesObservability.yaml create mode 100644 assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml create mode 100644 assets/samples/dynakube/v1beta4/logMonitoring.yaml create mode 100644 assets/samples/dynakube/v1beta4/multipleDynakubes.yaml create mode 100644 pkg/api/v1beta3/dynakube/convert_from.go create mode 100644 pkg/api/v1beta3/dynakube/convert_from_test.go create mode 100644 pkg/api/v1beta3/dynakube/convert_to.go create mode 100644 pkg/api/v1beta3/dynakube/convert_to_test.go create mode 100644 pkg/api/v1beta4/dynakube/activegate/props.go create mode 100644 pkg/api/v1beta4/dynakube/activegate/spec.go create mode 100644 pkg/api/v1beta4/dynakube/activegate/status.go create mode 100644 pkg/api/v1beta4/dynakube/activegate/zz_generated.deepcopy.go create mode 100644 pkg/api/v1beta4/dynakube/activegate_props.go create mode 100644 pkg/api/v1beta4/dynakube/certs.go rename pkg/api/{v1beta3 => v1beta4}/dynakube/conversion.go (100%) create mode 100644 pkg/api/v1beta4/dynakube/dynakube_props.go create mode 100644 pkg/api/v1beta4/dynakube/dynakube_props_test.go create mode 100644 pkg/api/v1beta4/dynakube/dynakube_status.go create mode 100644 pkg/api/v1beta4/dynakube/dynakube_types.go create mode 100644 pkg/api/v1beta4/dynakube/dynakube_webhook.go create mode 100644 pkg/api/v1beta4/dynakube/extensions.go create mode 100644 pkg/api/v1beta4/dynakube/extensions_props.go create mode 100644 pkg/api/v1beta4/dynakube/feature_flags.go create mode 100644 pkg/api/v1beta4/dynakube/feature_flags_test.go create mode 100644 pkg/api/v1beta4/dynakube/kspm/props.go create mode 100644 pkg/api/v1beta4/dynakube/kspm/spec.go create mode 100644 pkg/api/v1beta4/dynakube/kspm/zz_generated.deepcopy.go create mode 100644 pkg/api/v1beta4/dynakube/kspm_props.go create mode 100644 pkg/api/v1beta4/dynakube/logmonitoring/ingestrulematchers.go create mode 100644 pkg/api/v1beta4/dynakube/logmonitoring/props.go create mode 100644 pkg/api/v1beta4/dynakube/logmonitoring/spec.go create mode 100644 pkg/api/v1beta4/dynakube/logmonitoring/zz_generated.deepcopy.go create mode 100644 pkg/api/v1beta4/dynakube/logmonitoring_props.go create mode 100644 pkg/api/v1beta4/dynakube/metada_enrichment.go create mode 100644 pkg/api/v1beta4/dynakube/metadata_enrichment_props.go create mode 100644 pkg/api/v1beta4/dynakube/oneagent/props.go create mode 100644 pkg/api/v1beta4/dynakube/oneagent/props_test.go create mode 100644 pkg/api/v1beta4/dynakube/oneagent/spec.go create mode 100644 pkg/api/v1beta4/dynakube/oneagent/status.go create mode 100644 pkg/api/v1beta4/dynakube/oneagent/zz_generated.deepcopy.go create mode 100644 pkg/api/v1beta4/dynakube/oneagent_props.go rename pkg/api/{v1beta3 => v1beta4}/dynakube/otelc_props.go (99%) rename pkg/api/{v1beta3 => v1beta4}/dynakube/otelc_props_test.go (97%) rename pkg/api/{v1beta3 => v1beta4}/dynakube/otlp_props.go (100%) create mode 100644 pkg/api/v1beta4/dynakube/proxy.go rename pkg/api/{v1beta3 => v1beta4}/dynakube/telemetryingest/props.go (100%) rename pkg/api/{v1beta3 => v1beta4}/dynakube/telemetryingest/spec.go (100%) rename pkg/api/{v1beta3 => v1beta4}/dynakube/telemetryingest/zz_generated.deepcopy.go (100%) rename pkg/api/{v1beta3 => v1beta4}/dynakube/telemetryservice_props.go (78%) create mode 100644 pkg/api/v1beta4/dynakube/test/certs_test.go create mode 100644 pkg/api/v1beta4/dynakube/test/proxy_test.go create mode 100644 pkg/api/v1beta4/dynakube/zz_generated.deepcopy.go create mode 100644 pkg/api/v1beta4/groupversion_info.go diff --git a/.testcoverage.yml b/.testcoverage.yml index ba73e57bb6..7ab3bb7d5a 100644 --- a/.testcoverage.yml +++ b/.testcoverage.yml @@ -24,7 +24,7 @@ threshold: # (optional; default 0) # The minimum total coverage project should have - total: 71 + total: 69 # Holds regexp rules which will override thresholds for matched files or packages # using their paths. diff --git a/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml b/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml new file mode 100644 index 0000000000..b77a74f4a8 --- /dev/null +++ b/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml @@ -0,0 +1,18 @@ +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + applicationMonitoring: {} + + activeGate: + capabilities: + - routing + - kubernetes-monitoring + - dynatrace-api diff --git a/assets/samples/dynakube/v1beta4/classicFullStack.yaml b/assets/samples/dynakube/v1beta4/classicFullStack.yaml new file mode 100644 index 0000000000..d0a9cddde5 --- /dev/null +++ b/assets/samples/dynakube/v1beta4/classicFullStack.yaml @@ -0,0 +1,18 @@ +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + classicFullStack: {} + + activeGate: + capabilities: + - routing + - kubernetes-monitoring + - dynatrace-api diff --git a/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml b/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml new file mode 100644 index 0000000000..e8b2c506fe --- /dev/null +++ b/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml @@ -0,0 +1,18 @@ +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + cloudNativeFullStack: {} + + activeGate: + capabilities: + - routing + - kubernetes-monitoring + - dynatrace-api diff --git a/assets/samples/dynakube/v1beta4/hostMonitoring.yaml b/assets/samples/dynakube/v1beta4/hostMonitoring.yaml new file mode 100644 index 0000000000..6dcbde71c1 --- /dev/null +++ b/assets/samples/dynakube/v1beta4/hostMonitoring.yaml @@ -0,0 +1,18 @@ +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + hostMonitoring: {} + + activeGate: + capabilities: + - routing + - kubernetes-monitoring + - dynatrace-api diff --git a/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml b/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml new file mode 100644 index 0000000000..f9a9783a9a --- /dev/null +++ b/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml @@ -0,0 +1,15 @@ +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace + # annotations: + # feature.dynatrace.com/k8s-app-enabled: "true" +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + activeGate: + capabilities: + - kubernetes-monitoring diff --git a/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml new file mode 100644 index 0000000000..929e8c20e3 --- /dev/null +++ b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml @@ -0,0 +1,32 @@ +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + kspm: {} + + activeGate: + tlsSecretName: + + capabilities: + - kubernetes-monitoring + + customProperties: + value: | + [kubernetes_monitoring] + kubernetes_configuration_dataset_pipeline_enabled = true + kubernetes_configuration_dataset_pipeline_include_node_config = true + + templates: {} + # Required in combination with kspm enabled. + # As there is no image available in public registry yet, this field is required if you want to run kspm. + # + # kspmNodeConfigurationCollector: + # imageRef: + # repository: + # tag: diff --git a/assets/samples/dynakube/v1beta4/logMonitoring.yaml b/assets/samples/dynakube/v1beta4/logMonitoring.yaml new file mode 100644 index 0000000000..c7cde36f5a --- /dev/null +++ b/assets/samples/dynakube/v1beta4/logMonitoring.yaml @@ -0,0 +1,28 @@ +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # The `logMonitoring` section is used to configure log collection via the OneAgent Log module. + # it can be used with any other DynaKube mode, e.g. applicationMonitoring. + # Available with Dynatrace version 1.306+ and OneAgent 1.305+ + + logMonitoring: {} + + activeGate: + capabilities: + - kubernetes-monitoring + + templates: {} + # Required in combination with logMonitoring enabled. + # As there is no image available in public registry yet, this field is required if you want to run logMonitoring. + # + # logMonitoring: + # imageRef: + # repository: + # tag: diff --git a/assets/samples/dynakube/v1beta4/multipleDynakubes.yaml b/assets/samples/dynakube/v1beta4/multipleDynakubes.yaml new file mode 100644 index 0000000000..8faee91306 --- /dev/null +++ b/assets/samples/dynakube/v1beta4/multipleDynakubes.yaml @@ -0,0 +1,49 @@ +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube-application-monitoring + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + applicationMonitoring: + namespaceSelector: + matchLabels: + monitor: applicationMonitoring + + activeGate: + capabilities: + - kubernetes-monitoring +--- + +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube-cloud-native + namespace: dynatrace +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + oneAgent: + cloudNativeFullStack: + namespaceSelector: + matchLabels: + monitor: cloudNativeFullStack + + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + activeGate: + capabilities: + - routing + - dynatrace-api diff --git a/cmd/support_archive/resource_query.go b/cmd/support_archive/resource_query.go index 2ebe502c2e..6413ba4236 100644 --- a/cmd/support_archive/resource_query.go +++ b/cmd/support_archive/resource_query.go @@ -5,8 +5,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" appsv1 "k8s.io/api/apps/v1" @@ -86,7 +86,7 @@ func getComponentsQueryGroup(namespace string, appName string, labelKey string) func getCustomResourcesQueryGroup(namespace string) resourceQueryGroup { return resourceQueryGroup{ resources: []schema.GroupVersionKind{ - toGroupVersionKind(v1beta3.GroupVersion, dynakube.DynaKube{}), + toGroupVersionKind(v1beta4.GroupVersion, dynakube.DynaKube{}), toGroupVersionKind(v1alpha2.GroupVersion, edgeconnect.EdgeConnect{}), }, filters: []client.ListOption{ diff --git a/cmd/support_archive/resources_test.go b/cmd/support_archive/resources_test.go index 7fdbbf9c1b..7846385b46 100644 --- a/cmd/support_archive/resources_test.go +++ b/cmd/support_archive/resources_test.go @@ -11,7 +11,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" diff --git a/cmd/support_archive/troubleshoot_test.go b/cmd/support_archive/troubleshoot_test.go index 5d3eabfc65..4e78966d6f 100644 --- a/cmd/support_archive/troubleshoot_test.go +++ b/cmd/support_archive/troubleshoot_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" diff --git a/cmd/troubleshoot/builder.go b/cmd/troubleshoot/builder.go index 26cc1eefcd..dc8459760d 100644 --- a/cmd/troubleshoot/builder.go +++ b/cmd/troubleshoot/builder.go @@ -7,7 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/cmd/config" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/Dynatrace/dynatrace-operator/pkg/oci/dockerkeychain" "github.com/Dynatrace/dynatrace-operator/pkg/oci/registry" diff --git a/cmd/troubleshoot/builder_test.go b/cmd/troubleshoot/builder_test.go index 19b4f3b9aa..9e0e358afc 100644 --- a/cmd/troubleshoot/builder_test.go +++ b/cmd/troubleshoot/builder_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/cmd/troubleshoot/component.go b/cmd/troubleshoot/component.go index 19cb8cef18..1000cf899b 100644 --- a/cmd/troubleshoot/component.go +++ b/cmd/troubleshoot/component.go @@ -1,7 +1,7 @@ package troubleshoot import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" ) type component string diff --git a/cmd/troubleshoot/dynakube.go b/cmd/troubleshoot/dynakube.go index 1f60f66a21..3322db3155 100644 --- a/cmd/troubleshoot/dynakube.go +++ b/cmd/troubleshoot/dynakube.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dtpullsecret" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dynatraceclient" diff --git a/cmd/troubleshoot/dynakube_test.go b/cmd/troubleshoot/dynakube_test.go index 58181487a4..74cc1210d2 100644 --- a/cmd/troubleshoot/dynakube_test.go +++ b/cmd/troubleshoot/dynakube_test.go @@ -6,9 +6,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/pkg/errors" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" diff --git a/cmd/troubleshoot/image.go b/cmd/troubleshoot/image.go index 802526a919..0f0082964f 100644 --- a/cmd/troubleshoot/image.go +++ b/cmd/troubleshoot/image.go @@ -4,7 +4,7 @@ import ( "context" "net/http" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/arch" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/google/go-containerregistry/pkg/authn" diff --git a/cmd/troubleshoot/image_test.go b/cmd/troubleshoot/image_test.go index 28ceb6d567..005831b509 100644 --- a/cmd/troubleshoot/image_test.go +++ b/cmd/troubleshoot/image_test.go @@ -10,9 +10,9 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dtpullsecret" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/Dynatrace/dynatrace-operator/pkg/oci/dockerkeychain" diff --git a/cmd/troubleshoot/proxy.go b/cmd/troubleshoot/proxy.go index eb0e1e8a70..94f3da3c75 100644 --- a/cmd/troubleshoot/proxy.go +++ b/cmd/troubleshoot/proxy.go @@ -3,7 +3,7 @@ package troubleshoot import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "golang.org/x/net/http/httpproxy" "sigs.k8s.io/controller-runtime/pkg/client" diff --git a/cmd/troubleshoot/proxy_test.go b/cmd/troubleshoot/proxy_test.go index 5b18f027ea..fae53a0da5 100644 --- a/cmd/troubleshoot/proxy_test.go +++ b/cmd/troubleshoot/proxy_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/cmd/webhook/builder.go b/cmd/webhook/builder.go index 39a0e74d54..0491cad561 100644 --- a/cmd/webhook/builder.go +++ b/cmd/webhook/builder.go @@ -11,6 +11,7 @@ import ( dynakubev1beta1 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta1/dynakube" //nolint:staticcheck dynakubev1beta2 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta2/dynakube" //nolint:staticcheck dynakubev1beta3 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + dynakubev1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dynakubevalidation "github.com/Dynatrace/dynatrace-operator/pkg/api/validation/dynakube" edgeconnectvalidation "github.com/Dynatrace/dynatrace-operator/pkg/api/validation/edgeconnect" "github.com/Dynatrace/dynatrace-operator/pkg/logd" @@ -120,6 +121,48 @@ func startCertificateWatcher(webhookManager manager.Manager, namespace string, p return nil } +func setupDynakubeValidation(webhookManager manager.Manager) error { + dkValidator := dynakubevalidation.New(webhookManager.GetAPIReader(), webhookManager.GetConfig()) + + err := dynakubev1beta1.SetupWebhookWithManager(webhookManager, dkValidator) + if err != nil { + return err + } + + err = dynakubev1beta2.SetupWebhookWithManager(webhookManager, dkValidator) + if err != nil { + return err + } + + err = dynakubev1beta3.SetupWebhookWithManager(webhookManager, dkValidator) + if err != nil { + return err + } + + err = dynakubev1beta4.SetupWebhookWithManager(webhookManager, dkValidator) + if err != nil { + return err + } + + return nil +} + +func setupEdgeconnectValidation(webhookManager manager.Manager) error { + ecValidator := edgeconnectvalidation.New(webhookManager.GetAPIReader(), webhookManager.GetConfig()) + + err := edgeconnectv1alpha1.SetupWebhookWithManager(webhookManager, ecValidator) + if err != nil { + return err + } + + err = edgeconnectv1alpha2.SetupWebhookWithManager(webhookManager, ecValidator) + if err != nil { + return err + } + + return nil +} + func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { installconfig.ReadModules() @@ -153,31 +196,12 @@ func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { return err } - dkValidator := dynakubevalidation.New(webhookManager.GetAPIReader(), webhookManager.GetConfig()) - - err = dynakubev1beta1.SetupWebhookWithManager(webhookManager, dkValidator) - if err != nil { - return err - } - - err = dynakubev1beta2.SetupWebhookWithManager(webhookManager, dkValidator) - if err != nil { - return err - } - - err = dynakubev1beta3.SetupWebhookWithManager(webhookManager, dkValidator) - if err != nil { - return err - } - - ecValidator := edgeconnectvalidation.New(webhookManager.GetAPIReader(), webhookManager.GetConfig()) - - err = edgeconnectv1alpha1.SetupWebhookWithManager(webhookManager, ecValidator) + err = setupDynakubeValidation(webhookManager) if err != nil { return err } - err = edgeconnectv1alpha2.SetupWebhookWithManager(webhookManager, ecValidator) + err = setupEdgeconnectValidation(webhookManager) if err != nil { return err } diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index 53a8dc927f..a3262ed292 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -4614,6 +4614,3231 @@ spec: type: string description: Node selector to control the selection of nodes type: object + priorityClassName: + description: |- + If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that + name. If not specified the setting will be removed from the StatefulSet. + type: string + replicas: + description: Amount of replicas for your ActiveGates + format: int32 + type: integer + resources: + description: Define resources requests and limits for single ActiveGate + pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tlsSecretName: + description: |- + The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. + server.p12: certificate+key pair in pkcs12 format + password: passphrase to read server.p12 + type: string + tolerations: + description: Set tolerations for the ActiveGate pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + apiUrl: + description: |- + Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. + For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. + maxLength: 128 + type: string + customPullSecret: + description: |- + Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. + To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret + (https://www.dynatrace. + type: string + dynatraceApiRequestThreshold: + description: Configuration for thresholding Dynatrace API requests. + type: integer + enableIstio: + description: |- + When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding + VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. + Disabled by default. + type: boolean + extensions: + description: |- + When an (empty) ExtensionsSpec is provided, the extensions related components (extensions controller and extensions collector) + are deployed by the operator. + type: object + kspm: + description: General configuration about the KSPM feature. + type: object + logMonitoring: + description: General configuration about the LogMonitoring feature. + properties: + ingestRuleMatchers: + items: + properties: + attribute: + type: string + values: + items: + type: string + type: array + type: object + type: array + type: object + metadataEnrichment: + description: Configuration for Metadata Enrichment. + properties: + enabled: + description: Enables MetadataEnrichment, `false` by default. + type: boolean + namespaceSelector: + description: The namespaces where you want Dynatrace Operator + to inject enrichment. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object + networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. + type: string + oneAgent: + description: |- + General configuration about OneAgent instances. + You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). + properties: + applicationMonitoring: + description: |- + dynatrace-webhook injects into application pods based on labeled namespaces. + Has an optional CSI driver per node via DaemonSet to provide binaries to pods. + nullable: true + properties: + codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. + type: string + initResources: + description: |- + Define resources requests and limits for the initContainer. For details, see Managing resources for containers + (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + namespaceSelector: + description: |- + Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. + For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + version: + description: Use a specific OneAgent CodeModule version. Defaults + to the latest version from the Dynatrace cluster. + type: string + type: object + classicFullStack: + description: |- + Has a single OneAgent per node via DaemonSet. + Injection is performed via the same OneAgent DaemonSet. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. + type: string + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. + type: string + type: object + cloudNativeFullStack: + description: |- + Has a single OneAgent per node via DaemonSet. + dynatrace-webhook injects into application pods based on labeled namespaces. + Has a CSI driver per node via DaemonSet to provide binaries to pods. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. + type: string + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. + type: string + initResources: + description: |- + Define resources requests and limits for the initContainer. For details, see Managing resources for containers + (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + namespaceSelector: + description: |- + Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. + For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. + type: string + type: object + hostGroup: + description: Sets a host group for OneAgent. + type: string + hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. + type: string + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. + type: string + type: object + type: object + proxy: + description: |- + Set custom proxy settings either directly or from a secret with the field proxy. + Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. + properties: + value: + description: Raw value for given property. + nullable: true + type: string + valueFrom: + description: Name of the secret to get the property from. + nullable: true + type: string + type: object + skipCertCheck: + description: |- + Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + Set to true if you want to skip certification validation checks. + type: boolean + templates: + properties: + extensionExecutionController: + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the ExtensionExecutionController + pods + type: object + customConfig: + description: Defines name of ConfigMap containing custom configuration + file + type: string + customExtensionCertificates: + description: Defines name of Secret containing certificates + for custom extensions signature validation + type: string + imageRef: + description: Overrides the default image + properties: + repository: + description: Custom image repository + example: docker.io/dynatrace/image-name + type: string + tag: + description: Indicates a tag of the image to use + type: string + type: object + labels: + additionalProperties: + type: string + description: Adds additional labels for the ExtensionExecutionController + pods + type: object + persistentVolumeClaim: + description: Defines storage device + properties: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified data source. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + More info: https://kubernetes. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. + type: string + volumeMode: + description: |- + volumeMode defines what type of volume is required by the claim. + Value of Filesystem is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + resources: + description: Define resources' requests and limits for single + ExtensionExecutionController pod + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tlsRefName: + type: string + tolerations: + description: Set tolerations for the ExtensionExecutionController + pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ExtensionExecutionController + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + useEphemeralVolume: + description: Selects EmptyDir volume to be storage device + type: boolean + type: object + kspmNodeConfigurationCollector: + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations for the NodeConfigurationCollector + pods + type: object + args: + description: Set additional arguments to the NodeConfigurationCollector + pods + items: + type: string + type: array + env: + description: Set additional environment variables for the + NodeConfigurationCollector pods + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + imageRef: + description: Overrides the default image + properties: + repository: + description: Custom image repository + example: docker.io/dynatrace/image-name + type: string + tag: + description: Indicates a tag of the image to use + type: string + type: object + labels: + additionalProperties: + type: string + description: Adds additional labels for the NodeConfigurationCollector + pods + type: object + nodeAffinity: + description: Define the nodeAffinity for the DaemonSet of + the NodeConfigurationCollector + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes NodeConfigurationCollector pods will be deployed. + type: object + priorityClassName: + description: |- + If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that + name. If not specified the setting will be removed from the DaemonSet. + type: string + resources: + description: Define resources' requests and limits for single + NodeConfigurationCollector pod + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tolerations: + description: Set tolerations for the NodeConfigurationCollector + pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + updateStrategy: + description: Define the NodeConfigurationCollector daemonSet + updateStrategy + properties: + rollingUpdate: + description: Rolling update config params. Present only + if type = "RollingUpdate". + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: |- + The maximum number of nodes with an existing available DaemonSet pod that + can have an updated DaemonSet pod during during an update. + Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). + This can not be 0 if MaxUnavailable is 0. + Absolute number is calculated from percentage by rounding up to a minimum of 1. + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: |- + The maximum number of DaemonSet pods that can be unavailable during the + update. Value can be an absolute number (ex: 5) or a percentage of total + number of DaemonSet pods at the start of the update (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This cannot be 0 if MaxSurge is 0 + Default value is 1. + x-kubernetes-int-or-string: true + type: object + type: + description: Type of daemon set update. Can be "RollingUpdate" + or "OnDelete". Default is RollingUpdate. + type: string + type: object + type: object + logMonitoring: + description: Low-level configuration options for the LogMonitoring + feature. + properties: + annotations: + additionalProperties: + type: string + description: Add custom annotations to the LogMonitoring pods + type: object + args: + description: Set additional arguments to the LogMonitoring + main container + items: + type: string + type: array + dnsPolicy: + description: Sets DNS Policy for the LogMonitoring pods + type: string + imageRef: + description: Overrides the default image for the LogMonitoring + pods + properties: + repository: + description: Custom image repository + example: docker.io/dynatrace/image-name + type: string + tag: + description: Indicates a tag of the image to use + type: string + type: object + labels: + additionalProperties: + type: string + description: Add custom labels to the LogMonitoring pods + type: object + nodeSelector: + additionalProperties: + type: string + description: Node selector to control the selection of nodes + for the LogMonitoring pods + type: object + priorityClassName: + description: Assign a priority class to the LogMonitoring + pods. By default, no class is set + type: string + resources: + description: Define resources' requests and limits for all + the LogMonitoring pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode for the LogMonitoring + pods + type: string + tolerations: + description: Set tolerations for the LogMonitoring pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + openTelemetryCollector: + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the OtelCollector + pods + type: object + imageRef: + description: Overrides the default image + properties: + repository: + description: Custom image repository + example: docker.io/dynatrace/image-name + type: string + tag: + description: Indicates a tag of the image to use + type: string + type: object + labels: + additionalProperties: + type: string + description: Adds additional labels for the OtelCollector + pods + type: object + replicas: + description: Number of replicas for your OtelCollector + format: int32 + type: integer + resources: + description: Define resources' requests and limits for single + OtelCollector pod + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tlsRefName: + type: string + tolerations: + description: Set tolerations for the OtelCollector pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the OtelCollector + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + type: object + tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. + type: string + trustedCAs: + description: |- + Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. + Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. + type: string + required: + - apiUrl + type: object + status: + description: DynaKubeStatus defines the observed state of DynaKube + properties: + activeGate: + description: Observed state of ActiveGate + properties: + connectionInfoStatus: + description: Information about Active Gate's connections + properties: + endpoints: + description: Available connection endpoints + type: string + lastRequest: + description: Time of the last connection request + format: date-time + type: string + tenantTokenHash: + description: Hash of the tenant token + type: string + tenantUUID: + description: UUID of the tenant, received from the tenant + type: string + type: object + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator + items: + type: string + type: array + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + codeModules: + description: Observed state of Code Modules + properties: + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + conditions: + description: Conditions includes status about the current state of + the instance + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + dynatraceApi: + description: Observed state of Dynatrace API + properties: + lastTokenScopeRequest: + description: Time of the last token request + format: date-time + type: string + type: object + kspm: + description: Observed state of Kspm + properties: + tokenSecretHash: + description: |- + TokenSecretHash contains the hash of the token that is passed to both the ActiveGate and Node-Configuration-Collector. + Meant to keep the two in sync. + type: string + type: object + kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster + type: string + kubernetesClusterMEID: + description: KubernetesClusterMEID contains the ID of the monitored + entity that points to the Kubernetes cluster + type: string + kubernetesClusterName: + description: KubernetesClusterName contains the display name (also + know as label) of the monitored entity that points to the Kubernetes + cluster + type: string + metadataEnrichment: + description: Observed state of Metadata-Enrichment + properties: + rules: + items: + properties: + enabled: + type: boolean + source: + type: string + target: + type: string + type: + type: string + type: object + type: array + type: object + oneAgent: + description: Observed state of OneAgent + properties: + connectionInfoStatus: + description: Information about OneAgent's connections + properties: + communicationHosts: + description: List of communication hosts + items: + properties: + host: + description: Host domain + type: string + port: + description: Connection port + format: int32 + type: integer + protocol: + description: Connection protocol + type: string + type: object + type: array + endpoints: + description: Available connection endpoints + type: string + lastRequest: + description: Time of the last connection request + format: date-time + type: string + tenantTokenHash: + description: Hash of the tenant token + type: string + tenantUUID: + description: UUID of the tenant, received from the tenant + type: string + type: object + healthcheck: + description: Commands used for OneAgent's readiness probe + type: object + x-kubernetes-preserve-unknown-fields: true + imageID: + description: Image ID + type: string + instances: + additionalProperties: + properties: + ipAddress: + description: IP address of the pod + type: string + podName: + description: Name of the OneAgent pod + type: string + type: object + description: List of deployed OneAgent instances + type: object + lastInstanceStatusUpdate: + description: Time of the last instance status update + format: date-time + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + phase: + description: Defines the current state (Running, Updating, Error, + ...) + type: string + updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.apiUrl + name: ApiUrl + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta4 + schema: + openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: DynaKubeSpec defines the desired state of DynaKube + properties: + activeGate: + description: General configuration about ActiveGate instances. + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the ActiveGate pods + type: object + capabilities: + description: Activegate capabilities enabled (routing, kubernetes-monitoring, + metrics-ingest, dynatrace-api) + items: + type: string + type: array + customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced from a secret, make sure the key is called 'customProperties' + properties: + value: + description: Raw value for given property. + nullable: true + type: string + valueFrom: + description: Name of the secret to get the property from. + nullable: true + type: string + type: object + dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods + type: string + env: + description: List of environment variables to set for the ActiveGate + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + group: + description: Set activation group for ActiveGate + type: string + image: + description: The ActiveGate container image. Defaults to the latest + ActiveGate image provided by the registry on the tenant + type: string + labels: + additionalProperties: + type: string + description: Adds additional labels for the ActiveGate pods + type: object + nodeSelector: + additionalProperties: + type: string + description: Node selector to control the selection of nodes + type: object persistentVolumeClaim: description: Defines storage device properties: diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 2e2c26da21..07704cdb89 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -4626,6 +4626,3231 @@ spec: type: string description: Node selector to control the selection of nodes type: object + priorityClassName: + description: |- + If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that + name. If not specified the setting will be removed from the StatefulSet. + type: string + replicas: + description: Amount of replicas for your ActiveGates + format: int32 + type: integer + resources: + description: Define resources requests and limits for single ActiveGate + pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tlsSecretName: + description: |- + The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. + server.p12: certificate+key pair in pkcs12 format + password: passphrase to read server.p12 + type: string + tolerations: + description: Set tolerations for the ActiveGate pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + apiUrl: + description: |- + Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. + For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. + maxLength: 128 + type: string + customPullSecret: + description: |- + Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. + To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret + (https://www.dynatrace. + type: string + dynatraceApiRequestThreshold: + description: Configuration for thresholding Dynatrace API requests. + type: integer + enableIstio: + description: |- + When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding + VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. + Disabled by default. + type: boolean + extensions: + description: |- + When an (empty) ExtensionsSpec is provided, the extensions related components (extensions controller and extensions collector) + are deployed by the operator. + type: object + kspm: + description: General configuration about the KSPM feature. + type: object + logMonitoring: + description: General configuration about the LogMonitoring feature. + properties: + ingestRuleMatchers: + items: + properties: + attribute: + type: string + values: + items: + type: string + type: array + type: object + type: array + type: object + metadataEnrichment: + description: Configuration for Metadata Enrichment. + properties: + enabled: + description: Enables MetadataEnrichment, `false` by default. + type: boolean + namespaceSelector: + description: The namespaces where you want Dynatrace Operator + to inject enrichment. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object + networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. + type: string + oneAgent: + description: |- + General configuration about OneAgent instances. + You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). + properties: + applicationMonitoring: + description: |- + dynatrace-webhook injects into application pods based on labeled namespaces. + Has an optional CSI driver per node via DaemonSet to provide binaries to pods. + nullable: true + properties: + codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. + type: string + initResources: + description: |- + Define resources requests and limits for the initContainer. For details, see Managing resources for containers + (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + namespaceSelector: + description: |- + Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. + For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + version: + description: Use a specific OneAgent CodeModule version. Defaults + to the latest version from the Dynatrace cluster. + type: string + type: object + classicFullStack: + description: |- + Has a single OneAgent per node via DaemonSet. + Injection is performed via the same OneAgent DaemonSet. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. + type: string + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. + type: string + type: object + cloudNativeFullStack: + description: |- + Has a single OneAgent per node via DaemonSet. + dynatrace-webhook injects into application pods based on labeled namespaces. + Has a CSI driver per node via DaemonSet to provide binaries to pods. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. + type: string + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. + type: string + initResources: + description: |- + Define resources requests and limits for the initContainer. For details, see Managing resources for containers + (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + namespaceSelector: + description: |- + Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. + For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. + type: string + type: object + hostGroup: + description: Sets a host group for OneAgent. + type: string + hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace. + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. + type: string + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. + type: string + type: object + type: object + proxy: + description: |- + Set custom proxy settings either directly or from a secret with the field proxy. + Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. + properties: + value: + description: Raw value for given property. + nullable: true + type: string + valueFrom: + description: Name of the secret to get the property from. + nullable: true + type: string + type: object + skipCertCheck: + description: |- + Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + Set to true if you want to skip certification validation checks. + type: boolean + templates: + properties: + extensionExecutionController: + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the ExtensionExecutionController + pods + type: object + customConfig: + description: Defines name of ConfigMap containing custom configuration + file + type: string + customExtensionCertificates: + description: Defines name of Secret containing certificates + for custom extensions signature validation + type: string + imageRef: + description: Overrides the default image + properties: + repository: + description: Custom image repository + example: docker.io/dynatrace/image-name + type: string + tag: + description: Indicates a tag of the image to use + type: string + type: object + labels: + additionalProperties: + type: string + description: Adds additional labels for the ExtensionExecutionController + pods + type: object + persistentVolumeClaim: + description: Defines storage device + properties: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified data source. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + More info: https://kubernetes. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. + type: string + volumeMode: + description: |- + volumeMode defines what type of volume is required by the claim. + Value of Filesystem is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + resources: + description: Define resources' requests and limits for single + ExtensionExecutionController pod + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tlsRefName: + type: string + tolerations: + description: Set tolerations for the ExtensionExecutionController + pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ExtensionExecutionController + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + useEphemeralVolume: + description: Selects EmptyDir volume to be storage device + type: boolean + type: object + kspmNodeConfigurationCollector: + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations for the NodeConfigurationCollector + pods + type: object + args: + description: Set additional arguments to the NodeConfigurationCollector + pods + items: + type: string + type: array + env: + description: Set additional environment variables for the + NodeConfigurationCollector pods + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + imageRef: + description: Overrides the default image + properties: + repository: + description: Custom image repository + example: docker.io/dynatrace/image-name + type: string + tag: + description: Indicates a tag of the image to use + type: string + type: object + labels: + additionalProperties: + type: string + description: Adds additional labels for the NodeConfigurationCollector + pods + type: object + nodeAffinity: + description: Define the nodeAffinity for the DaemonSet of + the NodeConfigurationCollector + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes NodeConfigurationCollector pods will be deployed. + type: object + priorityClassName: + description: |- + If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that + name. If not specified the setting will be removed from the DaemonSet. + type: string + resources: + description: Define resources' requests and limits for single + NodeConfigurationCollector pod + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tolerations: + description: Set tolerations for the NodeConfigurationCollector + pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + updateStrategy: + description: Define the NodeConfigurationCollector daemonSet + updateStrategy + properties: + rollingUpdate: + description: Rolling update config params. Present only + if type = "RollingUpdate". + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: |- + The maximum number of nodes with an existing available DaemonSet pod that + can have an updated DaemonSet pod during during an update. + Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). + This can not be 0 if MaxUnavailable is 0. + Absolute number is calculated from percentage by rounding up to a minimum of 1. + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: |- + The maximum number of DaemonSet pods that can be unavailable during the + update. Value can be an absolute number (ex: 5) or a percentage of total + number of DaemonSet pods at the start of the update (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This cannot be 0 if MaxSurge is 0 + Default value is 1. + x-kubernetes-int-or-string: true + type: object + type: + description: Type of daemon set update. Can be "RollingUpdate" + or "OnDelete". Default is RollingUpdate. + type: string + type: object + type: object + logMonitoring: + description: Low-level configuration options for the LogMonitoring + feature. + properties: + annotations: + additionalProperties: + type: string + description: Add custom annotations to the LogMonitoring pods + type: object + args: + description: Set additional arguments to the LogMonitoring + main container + items: + type: string + type: array + dnsPolicy: + description: Sets DNS Policy for the LogMonitoring pods + type: string + imageRef: + description: Overrides the default image for the LogMonitoring + pods + properties: + repository: + description: Custom image repository + example: docker.io/dynatrace/image-name + type: string + tag: + description: Indicates a tag of the image to use + type: string + type: object + labels: + additionalProperties: + type: string + description: Add custom labels to the LogMonitoring pods + type: object + nodeSelector: + additionalProperties: + type: string + description: Node selector to control the selection of nodes + for the LogMonitoring pods + type: object + priorityClassName: + description: Assign a priority class to the LogMonitoring + pods. By default, no class is set + type: string + resources: + description: Define resources' requests and limits for all + the LogMonitoring pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode for the LogMonitoring + pods + type: string + tolerations: + description: Set tolerations for the LogMonitoring pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + openTelemetryCollector: + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the OtelCollector + pods + type: object + imageRef: + description: Overrides the default image + properties: + repository: + description: Custom image repository + example: docker.io/dynatrace/image-name + type: string + tag: + description: Indicates a tag of the image to use + type: string + type: object + labels: + additionalProperties: + type: string + description: Adds additional labels for the OtelCollector + pods + type: object + replicas: + description: Number of replicas for your OtelCollector + format: int32 + type: integer + resources: + description: Define resources' requests and limits for single + OtelCollector pod + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tlsRefName: + type: string + tolerations: + description: Set tolerations for the OtelCollector pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the OtelCollector + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + type: object + tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. + type: string + trustedCAs: + description: |- + Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. + Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. + type: string + required: + - apiUrl + type: object + status: + description: DynaKubeStatus defines the observed state of DynaKube + properties: + activeGate: + description: Observed state of ActiveGate + properties: + connectionInfoStatus: + description: Information about Active Gate's connections + properties: + endpoints: + description: Available connection endpoints + type: string + lastRequest: + description: Time of the last connection request + format: date-time + type: string + tenantTokenHash: + description: Hash of the tenant token + type: string + tenantUUID: + description: UUID of the tenant, received from the tenant + type: string + type: object + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator + items: + type: string + type: array + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + codeModules: + description: Observed state of Code Modules + properties: + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + conditions: + description: Conditions includes status about the current state of + the instance + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + dynatraceApi: + description: Observed state of Dynatrace API + properties: + lastTokenScopeRequest: + description: Time of the last token request + format: date-time + type: string + type: object + kspm: + description: Observed state of Kspm + properties: + tokenSecretHash: + description: |- + TokenSecretHash contains the hash of the token that is passed to both the ActiveGate and Node-Configuration-Collector. + Meant to keep the two in sync. + type: string + type: object + kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster + type: string + kubernetesClusterMEID: + description: KubernetesClusterMEID contains the ID of the monitored + entity that points to the Kubernetes cluster + type: string + kubernetesClusterName: + description: KubernetesClusterName contains the display name (also + know as label) of the monitored entity that points to the Kubernetes + cluster + type: string + metadataEnrichment: + description: Observed state of Metadata-Enrichment + properties: + rules: + items: + properties: + enabled: + type: boolean + source: + type: string + target: + type: string + type: + type: string + type: object + type: array + type: object + oneAgent: + description: Observed state of OneAgent + properties: + connectionInfoStatus: + description: Information about OneAgent's connections + properties: + communicationHosts: + description: List of communication hosts + items: + properties: + host: + description: Host domain + type: string + port: + description: Connection port + format: int32 + type: integer + protocol: + description: Connection protocol + type: string + type: object + type: array + endpoints: + description: Available connection endpoints + type: string + lastRequest: + description: Time of the last connection request + format: date-time + type: string + tenantTokenHash: + description: Hash of the tenant token + type: string + tenantUUID: + description: UUID of the tenant, received from the tenant + type: string + type: object + healthcheck: + description: Commands used for OneAgent's readiness probe + type: object + x-kubernetes-preserve-unknown-fields: true + imageID: + description: Image ID + type: string + instances: + additionalProperties: + properties: + ipAddress: + description: IP address of the pod + type: string + podName: + description: Name of the OneAgent pod + type: string + type: object + description: List of deployed OneAgent instances + type: object + lastInstanceStatusUpdate: + description: Time of the last instance status update + format: date-time + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + phase: + description: Defines the current state (Running, Updating, Error, + ...) + type: string + updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.apiUrl + name: ApiUrl + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta4 + schema: + openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: DynaKubeSpec defines the desired state of DynaKube + properties: + activeGate: + description: General configuration about ActiveGate instances. + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the ActiveGate pods + type: object + capabilities: + description: Activegate capabilities enabled (routing, kubernetes-monitoring, + metrics-ingest, dynatrace-api) + items: + type: string + type: array + customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced from a secret, make sure the key is called 'customProperties' + properties: + value: + description: Raw value for given property. + nullable: true + type: string + valueFrom: + description: Name of the secret to get the property from. + nullable: true + type: string + type: object + dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods + type: string + env: + description: List of environment variables to set for the ActiveGate + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + group: + description: Set activation group for ActiveGate + type: string + image: + description: The ActiveGate container image. Defaults to the latest + ActiveGate image provided by the registry on the tenant + type: string + labels: + additionalProperties: + type: string + description: Adds additional labels for the ActiveGate pods + type: object + nodeSelector: + additionalProperties: + type: string + description: Node selector to control the selection of nodes + type: object persistentVolumeClaim: description: Defines storage device properties: diff --git a/config/helm/chart/default/templates/Common/webhook/validatingwebhookconfiguration.yaml b/config/helm/chart/default/templates/Common/webhook/validatingwebhookconfiguration.yaml index 6ecfd954c6..d0a66228fd 100644 --- a/config/helm/chart/default/templates/Common/webhook/validatingwebhookconfiguration.yaml +++ b/config/helm/chart/default/templates/Common/webhook/validatingwebhookconfiguration.yaml @@ -81,6 +81,27 @@ webhooks: timeoutSeconds: {{.Values.webhook.validatingWebhook.timeoutSeconds}} sideEffects: None matchPolicy: Exact + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + path: /validate-dynatrace-com-v1beta4-dynakube + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - dynatrace.com + apiVersions: + - v1beta4 + resources: + - dynakubes + name: v1beta4.dynakube.webhook.dynatrace.com + timeoutSeconds: {{.Values.webhook.validatingWebhook.timeoutSeconds}} + sideEffects: None + matchPolicy: Exact - admissionReviewVersions: - v1 clientConfig: diff --git a/config/helm/chart/default/tests/Common/webhook/validatingwebhookconfiguration_test.yaml b/config/helm/chart/default/tests/Common/webhook/validatingwebhookconfiguration_test.yaml index e52f61671f..70232be82e 100644 --- a/config/helm/chart/default/tests/Common/webhook/validatingwebhookconfiguration_test.yaml +++ b/config/helm/chart/default/tests/Common/webhook/validatingwebhookconfiguration_test.yaml @@ -79,6 +79,27 @@ tests: timeoutSeconds: 10 sideEffects: None matchPolicy: Exact + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: dynatrace-webhook + namespace: NAMESPACE + path: /validate-dynatrace-com-v1beta4-dynakube + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - dynatrace.com + apiVersions: + - v1beta4 + resources: + - dynakubes + name: v1beta4.dynakube.webhook.dynatrace.com + timeoutSeconds: 10 + sideEffects: None + matchPolicy: Exact - admissionReviewVersions: - v1 clientConfig: diff --git a/doc/api/feature-flags.md b/doc/api/feature-flags.md index b3a5ace476..3e0bf01dc3 100644 --- a/doc/api/feature-flags.md +++ b/doc/api/feature-flags.md @@ -3,7 +3,7 @@ # dynakube ```go -import "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/tmp" +import "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/tmp" ``` ## Index @@ -76,7 +76,7 @@ const ( -## func [MountAttemptsToTimeout]() +## func [MountAttemptsToTimeout]() ```go func MountAttemptsToTimeout(maxAttempts int) string diff --git a/hack/doc/gen_feature_flags.sh b/hack/doc/gen_feature_flags.sh index b3021758cf..4b75645265 100755 --- a/hack/doc/gen_feature_flags.sh +++ b/hack/doc/gen_feature_flags.sh @@ -1,7 +1,7 @@ #!/bin/sh gomarkdoc_header="" script_header="" -doc_dir="./pkg/api/v1beta3/dynakube" +doc_dir="./pkg/api/v1beta4/dynakube" output_dir="./doc/api" output_file="feature-flags.md" output="" diff --git a/pkg/api/scheme/scheme.go b/pkg/api/scheme/scheme.go index 0a9b70dc25..e00efc99de 100644 --- a/pkg/api/scheme/scheme.go +++ b/pkg/api/scheme/scheme.go @@ -27,6 +27,8 @@ import ( _ "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta2/dynakube" //nolint:staticcheck "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3" _ "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4" + _ "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" istiov1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" corev1 "k8s.io/api/core/v1" apiv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -45,6 +47,7 @@ func init() { utilruntime.Must(v1beta1.AddToScheme(Scheme)) utilruntime.Must(v1beta2.AddToScheme(Scheme)) utilruntime.Must(v1beta3.AddToScheme(Scheme)) + utilruntime.Must(v1beta4.AddToScheme(Scheme)) utilruntime.Must(istiov1beta1.AddToScheme(Scheme)) utilruntime.Must(corev1.AddToScheme(Scheme)) utilruntime.Must(apiv1.AddToScheme(Scheme)) diff --git a/pkg/api/v1beta1/dynakube/convert_from.go b/pkg/api/v1beta1/dynakube/convert_from.go index 529d2eeef4..117c119bcc 100644 --- a/pkg/api/v1beta1/dynakube/convert_from.go +++ b/pkg/api/v1beta1/dynakube/convert_from.go @@ -3,8 +3,8 @@ package dynakube import ( "strconv" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/conversion" diff --git a/pkg/api/v1beta1/dynakube/convert_from_test.go b/pkg/api/v1beta1/dynakube/convert_from_test.go index 3d17116192..7379c2d4ec 100644 --- a/pkg/api/v1beta1/dynakube/convert_from_test.go +++ b/pkg/api/v1beta1/dynakube/convert_from_test.go @@ -6,9 +6,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" @@ -24,7 +24,8 @@ func TestConvertFrom(t *testing.T) { from := getNewDynakubeBase() to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) compareBase(t, to, from) }) @@ -33,9 +34,15 @@ func TestConvertFrom(t *testing.T) { from := getNewDynakubeBase() hostSpec := getNewHostInjectSpec() from.Spec.OneAgent.HostMonitoring = &hostSpec + to := DynaKube{} + err := to.ConvertFrom(&from) + require.NoError(t, err) - to.ConvertFrom(&from) + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Equal(t, from.Spec.OneAgent.HostGroup, to.Spec.OneAgent.HostGroup) compareHostInjectSpec(t, *to.Spec.OneAgent.HostMonitoring, *from.Spec.OneAgent.HostMonitoring) compareMovedFields(t, to, from) @@ -47,7 +54,13 @@ func TestConvertFrom(t *testing.T) { from.Spec.OneAgent.ClassicFullStack = &hostSpec to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + assert.Equal(t, from.Spec.OneAgent.HostGroup, to.Spec.OneAgent.HostGroup) compareHostInjectSpec(t, *to.Spec.OneAgent.ClassicFullStack, *from.Spec.OneAgent.ClassicFullStack) compareMovedFields(t, to, from) @@ -59,7 +72,13 @@ func TestConvertFrom(t *testing.T) { from.Spec.OneAgent.CloudNativeFullStack = &spec to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + assert.Equal(t, from.Spec.OneAgent.HostGroup, to.Spec.OneAgent.HostGroup) compareCloudNativeSpec(t, *to.Spec.OneAgent.CloudNativeFullStack, *from.Spec.OneAgent.CloudNativeFullStack) compareMovedFields(t, to, from) @@ -71,7 +90,13 @@ func TestConvertFrom(t *testing.T) { from.Spec.OneAgent.ApplicationMonitoring = &appSpec to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + assert.Equal(t, from.Spec.OneAgent.HostGroup, to.Spec.OneAgent.HostGroup) compareApplicationMonitoringSpec(t, *to.Spec.OneAgent.ApplicationMonitoring, *from.Spec.OneAgent.ApplicationMonitoring) }) @@ -82,7 +107,8 @@ func TestConvertFrom(t *testing.T) { from.Spec.ActiveGate = agSpec to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) compareActiveGateSpec(t, to.Spec.ActiveGate, from.Spec.ActiveGate) }) @@ -92,7 +118,8 @@ func TestConvertFrom(t *testing.T) { from.Status = getNewStatus() to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) compareStatus(t, to.Status, from.Status) }) @@ -126,6 +153,7 @@ func compareBase(t *testing.T, oldDk DynaKube, newDk dynakube.DynaKube) { assert.Equal(t, oldDk.Spec.EnableIstio, newDk.Spec.EnableIstio) assert.Equal(t, oldDk.Spec.SkipCertCheck, newDk.Spec.SkipCertCheck) assert.Equal(t, oldDk.Spec.TrustedCAs, newDk.Spec.TrustedCAs) + assert.Equal(t, oldDk.Spec.NetworkZone, newDk.Spec.NetworkZone) if oldDk.Spec.Proxy != nil || newDk.Spec.Proxy != nil { // necessary so we don't explode with nil pointer when not set require.NotNil(t, oldDk.Spec.Proxy) @@ -277,6 +305,9 @@ func getNewDynakubeBase() dynakube.DynaKube { Enabled: ptr.To(true), NamespaceSelector: getTestNamespaceSelector(), }, + OneAgent: oneagent.Spec{ + HostGroup: "host-group", + }, }, } } diff --git a/pkg/api/v1beta1/dynakube/convert_to.go b/pkg/api/v1beta1/dynakube/convert_to.go index 4a8edc283a..e9c0a3438b 100644 --- a/pkg/api/v1beta1/dynakube/convert_to.go +++ b/pkg/api/v1beta1/dynakube/convert_to.go @@ -6,9 +6,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/conversion" ) diff --git a/pkg/api/v1beta1/dynakube/convert_to_test.go b/pkg/api/v1beta1/dynakube/convert_to_test.go index f7d397a8f7..14ee1a3248 100644 --- a/pkg/api/v1beta1/dynakube/convert_to_test.go +++ b/pkg/api/v1beta1/dynakube/convert_to_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" diff --git a/pkg/api/v1beta2/dynakube/convert_from.go b/pkg/api/v1beta2/dynakube/convert_from.go index 56839738c6..f46c3dbc3d 100644 --- a/pkg/api/v1beta2/dynakube/convert_from.go +++ b/pkg/api/v1beta2/dynakube/convert_from.go @@ -1,8 +1,8 @@ package dynakube import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "sigs.k8s.io/controller-runtime/pkg/conversion" ) diff --git a/pkg/api/v1beta2/dynakube/convert_from_test.go b/pkg/api/v1beta2/dynakube/convert_from_test.go index 11a63a961e..591823c837 100644 --- a/pkg/api/v1beta2/dynakube/convert_from_test.go +++ b/pkg/api/v1beta2/dynakube/convert_from_test.go @@ -6,9 +6,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" @@ -20,79 +20,106 @@ import ( ) func TestConvertFrom(t *testing.T) { - t.Run("migrate base from v1beta3 to v1beta2", func(t *testing.T) { + t.Run("migrate base from v1beta4 to v1beta2", func(t *testing.T) { from := getNewDynakubeBase() to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) compareBase(t, to, from) }) - t.Run("migrate host-monitoring from v1beta3 to v1beta2", func(t *testing.T) { + t.Run("migrate host-monitoring from v1beta4 to v1beta2", func(t *testing.T) { from := getNewDynakubeBase() hostSpec := getNewHostInjectSpec() from.Spec.OneAgent.HostMonitoring = &hostSpec to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Equal(t, from.Spec.OneAgent.HostGroup, to.Spec.OneAgent.HostGroup) compareHostInjectSpec(t, *to.Spec.OneAgent.HostMonitoring, *from.Spec.OneAgent.HostMonitoring) compareBase(t, to, from) }) - t.Run("migrate classic-fullstack from v1beta3 to v1beta2", func(t *testing.T) { + t.Run("migrate classic-fullstack from v1beta4 to v1beta2", func(t *testing.T) { from := getNewDynakubeBase() hostSpec := getNewHostInjectSpec() from.Spec.OneAgent.ClassicFullStack = &hostSpec to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + assert.Equal(t, from.Spec.OneAgent.HostGroup, to.Spec.OneAgent.HostGroup) compareHostInjectSpec(t, *to.Spec.OneAgent.ClassicFullStack, *from.Spec.OneAgent.ClassicFullStack) compareBase(t, to, from) }) - t.Run("migrate cloud-native from v1beta3 to v1beta2", func(t *testing.T) { + t.Run("migrate cloud-native from v1beta4 to v1beta2", func(t *testing.T) { from := getNewDynakubeBase() spec := getNewCloudNativeSpec() from.Spec.OneAgent.CloudNativeFullStack = &spec to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + assert.Equal(t, from.Spec.OneAgent.HostGroup, to.Spec.OneAgent.HostGroup) compareCloudNativeSpec(t, *to.Spec.OneAgent.CloudNativeFullStack, *from.Spec.OneAgent.CloudNativeFullStack) compareBase(t, to, from) }) - t.Run("migrate application-monitoring from v1beta3 to v1beta2", func(t *testing.T) { + t.Run("migrate application-monitoring from v1beta4 to v1beta2", func(t *testing.T) { from := getNewDynakubeBase() appSpec := getNewApplicationMonitoringSpec() from.Spec.OneAgent.ApplicationMonitoring = &appSpec to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + assert.Equal(t, from.Spec.OneAgent.HostGroup, to.Spec.OneAgent.HostGroup) compareApplicationMonitoringSpec(t, *to.Spec.OneAgent.ApplicationMonitoring, *from.Spec.OneAgent.ApplicationMonitoring) }) - t.Run("migrate activegate from v1beta3 to v1beta2", func(t *testing.T) { + t.Run("migrate activegate from v1beta4 to v1beta2", func(t *testing.T) { from := getNewDynakubeBase() agSpec := getNewActiveGateSpec() from.Spec.ActiveGate = agSpec to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) compareActiveGateSpec(t, to.Spec.ActiveGate, from.Spec.ActiveGate) }) - t.Run("migrate status from v1beta3 to v1beta2", func(t *testing.T) { + t.Run("migrate status from v1beta4 to v1beta2", func(t *testing.T) { from := getNewDynakubeBase() from.Status = getNewStatus() to := DynaKube{} - to.ConvertFrom(&from) + err := to.ConvertFrom(&from) + require.NoError(t, err) compareStatus(t, to.Status, from.Status) }) @@ -120,6 +147,7 @@ func compareBase(t *testing.T, oldDk DynaKube, newDk dynakube.DynaKube) { assert.Equal(t, oldDk.Spec.SkipCertCheck, newDk.Spec.SkipCertCheck) assert.Equal(t, oldDk.Spec.TrustedCAs, newDk.Spec.TrustedCAs) assert.Equal(t, uint16(oldDk.Spec.DynatraceApiRequestThreshold), *newDk.Spec.DynatraceApiRequestThreshold) //nolint:gosec + assert.Equal(t, oldDk.Spec.NetworkZone, newDk.Spec.NetworkZone) if newDk.OneAgent().IsAppInjectionNeeded() { assert.Equal(t, oldDk.OneAgentNamespaceSelector(), newDk.OneAgent().GetNamespaceSelector()) @@ -142,23 +170,24 @@ func compareBase(t *testing.T, oldDk DynaKube, newDk dynakube.DynaKube) { func compareHostInjectSpec(t *testing.T, oldSpec HostInjectSpec, newSpec oneagent.HostInjectSpec) { assert.Equal(t, oldSpec.Annotations, newSpec.Annotations) - assert.Equal(t, oldSpec.Args, newSpec.Args) - assert.Equal(t, oldSpec.AutoUpdate, *newSpec.AutoUpdate) - assert.Equal(t, oldSpec.DNSPolicy, newSpec.DNSPolicy) - assert.Equal(t, oldSpec.Env, newSpec.Env) - assert.Equal(t, oldSpec.Image, newSpec.Image) assert.Equal(t, oldSpec.Labels, newSpec.Labels) assert.Equal(t, oldSpec.NodeSelector, newSpec.NodeSelector) - assert.Equal(t, oldSpec.OneAgentResources, newSpec.OneAgentResources) - assert.Equal(t, oldSpec.PriorityClassName, newSpec.PriorityClassName) - assert.Equal(t, oldSpec.Tolerations, newSpec.Tolerations) + assert.Equal(t, oldSpec.AutoUpdate, *newSpec.AutoUpdate) assert.Equal(t, oldSpec.Version, newSpec.Version) + assert.Equal(t, oldSpec.Image, newSpec.Image) + assert.Equal(t, oldSpec.DNSPolicy, newSpec.DNSPolicy) + assert.Equal(t, oldSpec.PriorityClassName, newSpec.PriorityClassName) assert.Equal(t, oldSpec.SecCompProfile, newSpec.SecCompProfile) + assert.Equal(t, oldSpec.OneAgentResources, newSpec.OneAgentResources) + assert.Equal(t, oldSpec.Tolerations, newSpec.Tolerations) + assert.Equal(t, oldSpec.Env, newSpec.Env) + assert.Equal(t, oldSpec.Args, newSpec.Args) } func compareAppInjectionSpec(t *testing.T, oldSpec AppInjectionSpec, newSpec oneagent.AppInjectionSpec) { assert.Equal(t, oldSpec.CodeModulesImage, newSpec.CodeModulesImage) assert.Equal(t, oldSpec.InitResources, newSpec.InitResources) + assert.Equal(t, oldSpec.NamespaceSelector, newSpec.NamespaceSelector) } func compareCloudNativeSpec(t *testing.T, oldSpec CloudNativeFullStackSpec, newSpec oneagent.CloudNativeFullStackSpec) { @@ -268,6 +297,9 @@ func getNewDynakubeBase() dynakube.DynaKube { Enabled: ptr.To(true), NamespaceSelector: getTestNamespaceSelector(), }, + OneAgent: oneagent.Spec{ + HostGroup: "host-group", + }, }, } } diff --git a/pkg/api/v1beta2/dynakube/convert_to.go b/pkg/api/v1beta2/dynakube/convert_to.go index 9000c7b053..2c36eafcf2 100644 --- a/pkg/api/v1beta2/dynakube/convert_to.go +++ b/pkg/api/v1beta2/dynakube/convert_to.go @@ -5,9 +5,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/conversion" ) diff --git a/pkg/api/v1beta2/dynakube/convert_to_test.go b/pkg/api/v1beta2/dynakube/convert_to_test.go index cdcb9ef996..4231ca39d0 100644 --- a/pkg/api/v1beta2/dynakube/convert_to_test.go +++ b/pkg/api/v1beta2/dynakube/convert_to_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" registryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" diff --git a/pkg/api/v1beta3/dynakube/activegate/props.go b/pkg/api/v1beta3/dynakube/activegate/props.go index 639cf51d9f..ff51796e0b 100644 --- a/pkg/api/v1beta3/dynakube/activegate/props.go +++ b/pkg/api/v1beta3/dynakube/activegate/props.go @@ -32,10 +32,6 @@ func (ag *Spec) SetExtensionsDependency(isEnabled bool) { ag.enabledDependencies.extensions = isEnabled } -func (ag *Spec) SetOTLPingestDependency(isEnabled bool) { - ag.enabledDependencies.otlpIngest = isEnabled -} - func (ag *Spec) apiUrlHost() string { parsedUrl, err := url.Parse(ag.apiUrl) if err != nil { diff --git a/pkg/api/v1beta3/dynakube/activegate/spec.go b/pkg/api/v1beta3/dynakube/activegate/spec.go index f4323e6624..d3954050aa 100644 --- a/pkg/api/v1beta3/dynakube/activegate/spec.go +++ b/pkg/api/v1beta3/dynakube/activegate/spec.go @@ -82,10 +82,6 @@ type Spec struct { // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Annotations",order=27,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} Annotations map[string]string `json:"annotations,omitempty"` - // Defines storage device - // +kubebuilder:validation:Optional - PersistentVolumeClaim *corev1.PersistentVolumeClaimSpec `json:"persistentVolumeClaim,omitempty"` - name string apiUrl string @@ -115,9 +111,6 @@ type Spec struct { enabledDependencies dependencies automaticTLSCertificateEnabled bool - - // UseEphemeralVolume - UseEphemeralVolume bool `json:"useEphemeralVolume,omitempty"` } // +kubebuilder:object:generate=true diff --git a/pkg/api/v1beta3/dynakube/activegate/zz_generated.deepcopy.go b/pkg/api/v1beta3/dynakube/activegate/zz_generated.deepcopy.go index 910cebcf43..441afb5208 100644 --- a/pkg/api/v1beta3/dynakube/activegate/zz_generated.deepcopy.go +++ b/pkg/api/v1beta3/dynakube/activegate/zz_generated.deepcopy.go @@ -94,11 +94,6 @@ func (in *Spec) DeepCopyInto(out *Spec) { (*out)[key] = val } } - if in.PersistentVolumeClaim != nil { - in, out := &in.PersistentVolumeClaim, &out.PersistentVolumeClaim - *out = new(v1.PersistentVolumeClaimSpec) - (*in).DeepCopyInto(*out) - } in.CapabilityProperties.DeepCopyInto(&out.CapabilityProperties) if in.Capabilities != nil { in, out := &in.Capabilities, &out.Capabilities diff --git a/pkg/api/v1beta3/dynakube/activegate_props.go b/pkg/api/v1beta3/dynakube/activegate_props.go index 4e4febc371..30f9862abe 100644 --- a/pkg/api/v1beta3/dynakube/activegate_props.go +++ b/pkg/api/v1beta3/dynakube/activegate_props.go @@ -9,7 +9,6 @@ func (dk *DynaKube) ActiveGate() *activegate.ActiveGate { dk.Spec.ActiveGate.SetName(dk.Name) dk.Spec.ActiveGate.SetAutomaticTLSCertificate(dk.FeatureActiveGateAutomaticTLSCertificate()) dk.Spec.ActiveGate.SetExtensionsDependency(dk.IsExtensionsEnabled()) - dk.Spec.ActiveGate.SetOTLPingestDependency(dk.IsOTLPingestEnabled()) return &activegate.ActiveGate{ Spec: &dk.Spec.ActiveGate, diff --git a/pkg/api/v1beta3/dynakube/convert_from.go b/pkg/api/v1beta3/dynakube/convert_from.go new file mode 100644 index 0000000000..1322b23fcb --- /dev/null +++ b/pkg/api/v1beta3/dynakube/convert_from.go @@ -0,0 +1,293 @@ +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + dynakubev1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + kspmv1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" + logmonitoringv1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + oneagentv1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +// ConvertFrom converts from the Hub version (v1beta4) to this version (v1beta3). +func (dst *DynaKube) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*dynakubev1beta4.DynaKube) + + dst.fromStatus(src) + + dst.fromBase(src) + dst.fromMetadataEnrichment(src) + dst.fromLogMonitoringSpec(src) + dst.fromKspmSpec(src) + dst.fromExtensionsSpec(src) + dst.fromOneAgentSpec(src) + dst.fromActiveGateSpec(src) + dst.fromTemplatesSpec(src) + + return nil +} + +func (dst *DynaKube) fromBase(src *dynakubev1beta4.DynaKube) { + if src.Annotations == nil { + src.Annotations = map[string]string{} + } + + dst.ObjectMeta = *src.ObjectMeta.DeepCopy() // DeepCopy mainly relevant for testing + + dst.Spec.Proxy = src.Spec.Proxy + dst.Spec.DynatraceApiRequestThreshold = src.Spec.DynatraceApiRequestThreshold + dst.Spec.APIURL = src.Spec.APIURL + dst.Spec.Tokens = src.Spec.Tokens + dst.Spec.TrustedCAs = src.Spec.TrustedCAs + dst.Spec.NetworkZone = src.Spec.NetworkZone + dst.Spec.CustomPullSecret = src.Spec.CustomPullSecret + dst.Spec.SkipCertCheck = src.Spec.SkipCertCheck + dst.Spec.EnableIstio = src.Spec.EnableIstio +} + +func (dst *DynaKube) fromLogMonitoringSpec(src *dynakubev1beta4.DynaKube) { + if src.Spec.LogMonitoring != nil { + dst.Spec.LogMonitoring = &logmonitoring.Spec{} + dst.Spec.LogMonitoring.IngestRuleMatchers = make([]logmonitoring.IngestRuleMatchers, 0) + + for _, rule := range src.Spec.LogMonitoring.IngestRuleMatchers { + dst.Spec.LogMonitoring.IngestRuleMatchers = append(dst.Spec.LogMonitoring.IngestRuleMatchers, logmonitoring.IngestRuleMatchers{ + Attribute: rule.Attribute, + Values: rule.Values, + }) + } + } +} + +func (dst *DynaKube) fromKspmSpec(src *dynakubev1beta4.DynaKube) { + if src.Spec.Kspm != nil { + dst.Spec.Kspm = &kspm.Spec{} + } +} + +func (dst *DynaKube) fromExtensionsSpec(src *dynakubev1beta4.DynaKube) { + if src.Spec.Extensions != nil { + dst.Spec.Extensions = &ExtensionsSpec{} + } +} + +func (dst *DynaKube) fromOneAgentSpec(src *dynakubev1beta4.DynaKube) { //nolint:dupl + switch { + case src.OneAgent().IsClassicFullStackMode(): + dst.Spec.OneAgent.ClassicFullStack = fromHostInjectSpec(*src.Spec.OneAgent.ClassicFullStack) + case src.OneAgent().IsCloudNativeFullstackMode(): + dst.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} + dst.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec = *fromHostInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec) + dst.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec = *fromAppInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec) + case src.OneAgent().IsApplicationMonitoringMode(): + dst.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} + dst.Spec.OneAgent.ApplicationMonitoring.Version = src.Spec.OneAgent.ApplicationMonitoring.Version + dst.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec = *fromAppInjectSpec(src.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec) + case src.OneAgent().IsHostMonitoringMode(): + dst.Spec.OneAgent.HostMonitoring = fromHostInjectSpec(*src.Spec.OneAgent.HostMonitoring) + } + + dst.Spec.OneAgent.HostGroup = src.Spec.OneAgent.HostGroup +} + +func (dst *DynaKube) fromTemplatesSpec(src *dynakubev1beta4.DynaKube) { + dst.Spec.Templates.LogMonitoring = fromLogMonitoringTemplate(src.Spec.Templates.LogMonitoring) + dst.Spec.Templates.KspmNodeConfigurationCollector = fromKspmNodeConfigurationCollectorTemplate(src.Spec.Templates.KspmNodeConfigurationCollector) + dst.Spec.Templates.OpenTelemetryCollector = fromOpenTelemetryCollectorTemplate(src.Spec.Templates.OpenTelemetryCollector) + dst.Spec.Templates.ExtensionExecutionController = fromExtensionControllerTemplate(src.Spec.Templates.ExtensionExecutionController) +} + +func fromLogMonitoringTemplate(src *logmonitoringv1beta4.TemplateSpec) *logmonitoring.TemplateSpec { + if src == nil { + return nil + } + + dst := &logmonitoring.TemplateSpec{} + + dst.Annotations = src.Annotations + dst.Labels = src.Labels + dst.NodeSelector = src.NodeSelector + dst.ImageRef = src.ImageRef + dst.DNSPolicy = src.DNSPolicy + dst.PriorityClassName = src.PriorityClassName + dst.SecCompProfile = src.SecCompProfile + dst.Resources = src.Resources + dst.Tolerations = src.Tolerations + dst.Args = src.Args + + return dst +} + +func fromKspmNodeConfigurationCollectorTemplate(src kspmv1beta4.NodeConfigurationCollectorSpec) kspm.NodeConfigurationCollectorSpec { + dst := kspm.NodeConfigurationCollectorSpec{} + + dst.UpdateStrategy = src.UpdateStrategy + dst.Labels = src.Labels + dst.Annotations = src.Annotations + dst.NodeSelector = src.NodeSelector + dst.ImageRef = src.ImageRef + dst.PriorityClassName = src.PriorityClassName + dst.Resources = src.Resources + dst.NodeAffinity = src.NodeAffinity + dst.Tolerations = src.Tolerations + dst.Args = src.Args + dst.Env = src.Env + + return dst +} + +func fromOpenTelemetryCollectorTemplate(src dynakubev1beta4.OpenTelemetryCollectorSpec) OpenTelemetryCollectorSpec { + dst := OpenTelemetryCollectorSpec{} + + dst.Labels = src.Labels + dst.Annotations = src.Annotations + dst.Replicas = src.Replicas + dst.ImageRef = src.ImageRef + dst.TlsRefName = src.TlsRefName + dst.Resources = src.Resources + dst.Tolerations = src.Tolerations + dst.TopologySpreadConstraints = src.TopologySpreadConstraints + + return dst +} + +func fromExtensionControllerTemplate(src dynakubev1beta4.ExtensionExecutionControllerSpec) ExtensionExecutionControllerSpec { + dst := ExtensionExecutionControllerSpec{} + + dst.PersistentVolumeClaim = src.PersistentVolumeClaim + dst.Labels = src.Labels + dst.Annotations = src.Annotations + dst.ImageRef = src.ImageRef + dst.TlsRefName = src.TlsRefName + dst.CustomConfig = src.CustomConfig + dst.CustomExtensionCertificates = src.CustomExtensionCertificates + dst.Resources = src.Resources + dst.Tolerations = src.Tolerations + dst.TopologySpreadConstraints = src.TopologySpreadConstraints + dst.UseEphemeralVolume = src.UseEphemeralVolume + + return dst +} + +func (dst *DynaKube) fromActiveGateSpec(src *dynakubev1beta4.DynaKube) { //nolint:dupl + dst.Spec.ActiveGate.Annotations = src.Spec.ActiveGate.Annotations + dst.Spec.ActiveGate.TlsSecretName = src.Spec.ActiveGate.TlsSecretName + dst.Spec.ActiveGate.DNSPolicy = src.Spec.ActiveGate.DNSPolicy + dst.Spec.ActiveGate.PriorityClassName = src.Spec.ActiveGate.PriorityClassName + + dst.Spec.ActiveGate.CapabilityProperties.CustomProperties = src.Spec.ActiveGate.CapabilityProperties.CustomProperties + dst.Spec.ActiveGate.CapabilityProperties.NodeSelector = src.Spec.ActiveGate.CapabilityProperties.NodeSelector + dst.Spec.ActiveGate.CapabilityProperties.Labels = src.Spec.ActiveGate.CapabilityProperties.Labels + dst.Spec.ActiveGate.CapabilityProperties.Replicas = src.Spec.ActiveGate.CapabilityProperties.Replicas + dst.Spec.ActiveGate.CapabilityProperties.Image = src.Spec.ActiveGate.CapabilityProperties.Image + dst.Spec.ActiveGate.CapabilityProperties.Group = src.Spec.ActiveGate.CapabilityProperties.Group + dst.Spec.ActiveGate.CapabilityProperties.Resources = src.Spec.ActiveGate.CapabilityProperties.Resources + dst.Spec.ActiveGate.CapabilityProperties.Tolerations = src.Spec.ActiveGate.CapabilityProperties.Tolerations + dst.Spec.ActiveGate.CapabilityProperties.Env = src.Spec.ActiveGate.CapabilityProperties.Env + dst.Spec.ActiveGate.CapabilityProperties.TopologySpreadConstraints = src.Spec.ActiveGate.CapabilityProperties.TopologySpreadConstraints + + dst.Spec.ActiveGate.Capabilities = make([]activegate.CapabilityDisplayName, 0) + for _, capability := range src.Spec.ActiveGate.Capabilities { + dst.Spec.ActiveGate.Capabilities = append(dst.Spec.ActiveGate.Capabilities, activegate.CapabilityDisplayName(capability)) + } +} + +func (dst *DynaKube) fromStatus(src *dynakubev1beta4.DynaKube) { + dst.fromOneAgentStatus(*src) + dst.fromActiveGateStatus(*src) + dst.Status.CodeModules = oneagent.CodeModulesStatus{ + VersionStatus: src.Status.CodeModules.VersionStatus, + } + + dst.Status.MetadataEnrichment.Rules = make([]EnrichmentRule, 0) + for _, rule := range src.Status.MetadataEnrichment.Rules { + dst.Status.MetadataEnrichment.Rules = append(dst.Status.MetadataEnrichment.Rules, + EnrichmentRule{ + Type: EnrichmentRuleType(rule.Type), + Source: rule.Source, + Target: rule.Target, + Enabled: rule.Enabled, + }) + } + + dst.Status.Kspm.TokenSecretHash = src.Status.Kspm.TokenSecretHash + dst.Status.UpdatedTimestamp = src.Status.UpdatedTimestamp + dst.Status.DynatraceApi = DynatraceApiStatus{ + LastTokenScopeRequest: src.Status.DynatraceApi.LastTokenScopeRequest, + } + dst.Status.Phase = src.Status.Phase + dst.Status.KubeSystemUUID = src.Status.KubeSystemUUID + dst.Status.KubernetesClusterMEID = src.Status.KubernetesClusterMEID + dst.Status.KubernetesClusterName = src.Status.KubernetesClusterName + dst.Status.Conditions = src.Status.Conditions +} + +func (dst *DynaKube) fromOneAgentStatus(src dynakubev1beta4.DynaKube) { //nolint:dupl + dst.Status.OneAgent.VersionStatus = src.Status.OneAgent.VersionStatus + + dst.Status.OneAgent.Instances = map[string]oneagent.Instance{} + for key, instance := range src.Status.OneAgent.Instances { + dst.Status.OneAgent.Instances[key] = oneagent.Instance{ + PodName: instance.PodName, + IPAddress: instance.IPAddress, + } + } + + dst.Status.OneAgent.LastInstanceStatusUpdate = src.Status.OneAgent.LastInstanceStatusUpdate + dst.Status.OneAgent.Healthcheck = src.Status.OneAgent.Healthcheck + dst.Status.OneAgent.ConnectionInfoStatus.ConnectionInfo = src.Status.OneAgent.ConnectionInfoStatus.ConnectionInfo + dst.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = make([]oneagent.CommunicationHostStatus, 0) + + for _, host := range src.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts { + dst.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = + append(dst.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts, oneagent.CommunicationHostStatus{ + Protocol: host.Protocol, + Host: host.Host, + Port: host.Port, + }) + } +} + +func (dst *DynaKube) fromActiveGateStatus(src dynakubev1beta4.DynaKube) { + dst.Status.ActiveGate.VersionStatus = src.Status.ActiveGate.VersionStatus + dst.Status.ActiveGate.ConnectionInfo = src.Status.ActiveGate.ConnectionInfo + dst.Status.ActiveGate.ServiceIPs = src.Status.ActiveGate.ServiceIPs +} + +func fromHostInjectSpec(src oneagentv1beta4.HostInjectSpec) *oneagent.HostInjectSpec { + dst := &oneagent.HostInjectSpec{} + + dst.Annotations = src.Annotations + dst.Labels = src.Labels + dst.NodeSelector = src.NodeSelector + dst.AutoUpdate = src.AutoUpdate + dst.Version = src.Version + dst.Image = src.Image + dst.DNSPolicy = src.DNSPolicy + dst.PriorityClassName = src.PriorityClassName + dst.SecCompProfile = src.SecCompProfile + dst.OneAgentResources = src.OneAgentResources + dst.Tolerations = src.Tolerations + dst.Env = src.Env + dst.Args = src.Args + + return dst +} + +func fromAppInjectSpec(src oneagentv1beta4.AppInjectionSpec) *oneagent.AppInjectionSpec { + dst := &oneagent.AppInjectionSpec{} + + dst.InitResources = src.InitResources + dst.CodeModulesImage = src.CodeModulesImage + dst.NamespaceSelector = src.NamespaceSelector + + return dst +} + +func (dst *DynaKube) fromMetadataEnrichment(src *dynakubev1beta4.DynaKube) { + dst.Spec.MetadataEnrichment.Enabled = src.Spec.MetadataEnrichment.Enabled + dst.Spec.MetadataEnrichment.NamespaceSelector = src.Spec.MetadataEnrichment.NamespaceSelector +} diff --git a/pkg/api/v1beta3/dynakube/convert_from_test.go b/pkg/api/v1beta3/dynakube/convert_from_test.go new file mode 100644 index 0000000000..3f87a99eb8 --- /dev/null +++ b/pkg/api/v1beta3/dynakube/convert_from_test.go @@ -0,0 +1,960 @@ +package dynakube + +import ( + "slices" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + dynakubev1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + activegatev1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + kspmv1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" + logmonitoringv1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + oneagentv1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + registryv1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" +) + +func TestConvertFrom(t *testing.T) { + t.Run("migrate base from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + compareBase(t, to, from) + }) + + t.Run("migrate metadata-enrichment from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.True(t, to.MetadataEnrichmentEnabled()) + compareBase(t, to, from) + }) + + t.Run("migrate host-monitoring from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + hostSpec := getNewHostInjectSpec() + from.Spec.OneAgent.HostMonitoring = &hostSpec + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + compareHostInjectSpec(t, *to.Spec.OneAgent.HostMonitoring, *from.Spec.OneAgent.HostMonitoring) + compareBase(t, to, from) + }) + + t.Run("migrate classic-fullstack from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + hostSpec := getNewHostInjectSpec() + from.Spec.OneAgent.ClassicFullStack = &hostSpec + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + + compareHostInjectSpec(t, *to.Spec.OneAgent.ClassicFullStack, *from.Spec.OneAgent.ClassicFullStack) + compareBase(t, to, from) + }) + + t.Run("migrate cloud-native from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + spec := getNewCloudNativeSpec() + from.Spec.OneAgent.CloudNativeFullStack = &spec + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + + compareCloudNativeSpec(t, *to.Spec.OneAgent.CloudNativeFullStack, *from.Spec.OneAgent.CloudNativeFullStack) + compareBase(t, to, from) + }) + + t.Run("migrate application-monitoring from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + appSpec := getNewApplicationMonitoringSpec() + from.Spec.OneAgent.ApplicationMonitoring = &appSpec + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + + compareApplicationMonitoringSpec(t, *to.Spec.OneAgent.ApplicationMonitoring, *from.Spec.OneAgent.ApplicationMonitoring) + compareBase(t, to, from) + }) + + t.Run("migrate activegate from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + agSpec := getNewActiveGateSpec() + from.Spec.ActiveGate = agSpec + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + compareActiveGateSpec(t, to.Spec.ActiveGate, from.Spec.ActiveGate) + compareBase(t, to, from) + }) + + t.Run("migrate extensions from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + from.Spec.Extensions = &dynakubev1beta4.ExtensionsSpec{} + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.NotNil(t, to.Spec.Extensions) + compareBase(t, to, from) + }) + + t.Run("migrate log-monitoring from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + from.Spec.LogMonitoring = getNewLogMonitoringSpec() + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + compareLogMonitoringSpec(t, to.Spec.LogMonitoring, from.Spec.LogMonitoring) + compareBase(t, to, from) + }) + + t.Run("migrate kspm from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + from.Spec.Kspm = &kspmv1beta4.Spec{} + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.NotNil(t, to.Spec.Kspm) + compareBase(t, to, from) + }) + + t.Run("migrate extensions templates from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + from.Spec.Templates.OpenTelemetryCollector = getNewOpenTelemetryTemplateSpec() + from.Spec.Templates.ExtensionExecutionController = getNewExtensionExecutionControllerSpec() + + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + compareOpenTelemetryTemplateSpec(t, to.Spec.Templates.OpenTelemetryCollector, from.Spec.Templates.OpenTelemetryCollector) + compareExtensionsExecutionControllerTemplateSpec(t, to.Spec.Templates.ExtensionExecutionController, from.Spec.Templates.ExtensionExecutionController) + + compareBase(t, to, from) + }) + + t.Run("migrate log-monitoring templates from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + from.Spec.Templates.LogMonitoring = getNewLogMonitoringTemplateSpec() + + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + compareLogMonitoringTemplateSpec(t, to.Spec.Templates.LogMonitoring, from.Spec.Templates.LogMonitoring) + compareBase(t, to, from) + }) + + t.Run("migrate kspm templates from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + from.Spec.Templates.KspmNodeConfigurationCollector = getNewNodeConfigurationCollectorTemplateSpec() + + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + compareNodeConfigurationCollectorTemplateSpec(t, to.Spec.Templates.KspmNodeConfigurationCollector, from.Spec.Templates.KspmNodeConfigurationCollector) + compareBase(t, to, from) + }) + + t.Run("migrate status from v1beta4 to v1beta3", func(t *testing.T) { + from := getNewDynakubeBase() + from.Status = getNewStatus() + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + compareStatus(t, to.Status, from.Status) + }) + t.Run("migrate hostGroup", func(t *testing.T) { + from := getNewDynakubeBase() + from.Status = getNewStatus() + to := DynaKube{} + + err := to.ConvertFrom(&from) + require.NoError(t, err) + + assert.Equal(t, to.Spec.OneAgent.HostGroup, from.Spec.OneAgent.HostGroup) + }) +} + +func compareBase(t *testing.T, oldDk DynaKube, newDk dynakubev1beta4.DynaKube) { + require.NotEmpty(t, oldDk) + require.NotEmpty(t, newDk) + + // Some feature-flags are moved, so ObjectMeta will differ in that 1 field + oldAnnotations := oldDk.Annotations + newAnnotations := newDk.Annotations + oldDk.Annotations = nil + newDk.Annotations = nil + + assert.Equal(t, oldDk.ObjectMeta, newDk.ObjectMeta) + + oldDk.Annotations = oldAnnotations + newDk.Annotations = newAnnotations + + if oldDk.Spec.Proxy != nil || newDk.Spec.Proxy != nil { // necessary so we don't explode with nil pointer when not set + require.NotNil(t, oldDk.Spec.Proxy) + require.NotNil(t, newDk.Spec.Proxy) + assert.Equal(t, oldDk.Spec.Proxy.Value, newDk.Spec.Proxy.Value) + assert.Equal(t, oldDk.Spec.Proxy.ValueFrom, newDk.Spec.Proxy.ValueFrom) + } + + assert.Equal(t, oldDk.Spec.DynatraceApiRequestThreshold, newDk.Spec.DynatraceApiRequestThreshold) + assert.Equal(t, oldDk.Spec.APIURL, newDk.Spec.APIURL) + assert.Equal(t, oldDk.Spec.Tokens, newDk.Spec.Tokens) + assert.Equal(t, oldDk.Spec.TrustedCAs, newDk.Spec.TrustedCAs) + assert.Equal(t, oldDk.Spec.NetworkZone, newDk.Spec.NetworkZone) + assert.Equal(t, oldDk.Spec.CustomPullSecret, newDk.Spec.CustomPullSecret) + assert.Equal(t, oldDk.Spec.SkipCertCheck, newDk.Spec.SkipCertCheck) + assert.Equal(t, oldDk.Spec.EnableIstio, newDk.Spec.EnableIstio) + + if newDk.OneAgent().IsAppInjectionNeeded() { + assert.Equal(t, oldDk.OneAgent().GetNamespaceSelector(), newDk.OneAgent().GetNamespaceSelector()) + } + + assert.Equal(t, oldDk.MetadataEnrichmentEnabled(), newDk.MetadataEnrichmentEnabled()) + assert.Equal(t, oldDk.Spec.MetadataEnrichment.NamespaceSelector, newDk.Spec.MetadataEnrichment.NamespaceSelector) + + if oldDk.FeatureMaxFailedCsiMountAttempts() != DefaultMaxFailedCsiMountAttempts { + assert.Equal(t, dynakubev1beta4.MountAttemptsToTimeout(oldDk.FeatureMaxFailedCsiMountAttempts()), newDk.FeatureMaxCSIRetryTimeout().String()) + } +} + +func compareHostInjectSpec(t *testing.T, oldSpec oneagent.HostInjectSpec, newSpec oneagentv1beta4.HostInjectSpec) { + assert.Equal(t, oldSpec.Annotations, newSpec.Annotations) + assert.Equal(t, oldSpec.Args, newSpec.Args) + assert.Equal(t, *oldSpec.AutoUpdate, *newSpec.AutoUpdate) + assert.Equal(t, oldSpec.DNSPolicy, newSpec.DNSPolicy) + assert.Equal(t, oldSpec.Env, newSpec.Env) + assert.Equal(t, oldSpec.Image, newSpec.Image) + assert.Equal(t, oldSpec.Labels, newSpec.Labels) + assert.Equal(t, oldSpec.NodeSelector, newSpec.NodeSelector) + assert.Equal(t, oldSpec.OneAgentResources, newSpec.OneAgentResources) + assert.Equal(t, oldSpec.PriorityClassName, newSpec.PriorityClassName) + assert.Equal(t, oldSpec.Tolerations, newSpec.Tolerations) + assert.Equal(t, oldSpec.Version, newSpec.Version) + assert.Equal(t, oldSpec.SecCompProfile, newSpec.SecCompProfile) +} + +func compareAppInjectionSpec(t *testing.T, oldSpec oneagent.AppInjectionSpec, newSpec oneagentv1beta4.AppInjectionSpec) { + assert.Equal(t, oldSpec.InitResources, newSpec.InitResources) + assert.Equal(t, oldSpec.CodeModulesImage, newSpec.CodeModulesImage) + assert.Equal(t, oldSpec.NamespaceSelector, newSpec.NamespaceSelector) +} + +func compareCloudNativeSpec(t *testing.T, oldSpec oneagent.CloudNativeFullStackSpec, newSpec oneagentv1beta4.CloudNativeFullStackSpec) { + compareHostInjectSpec(t, oldSpec.HostInjectSpec, newSpec.HostInjectSpec) + compareAppInjectionSpec(t, oldSpec.AppInjectionSpec, newSpec.AppInjectionSpec) +} + +func compareApplicationMonitoringSpec(t *testing.T, oldSpec oneagent.ApplicationMonitoringSpec, newSpec oneagentv1beta4.ApplicationMonitoringSpec) { + assert.Equal(t, oldSpec.Version, newSpec.Version) + compareAppInjectionSpec(t, oldSpec.AppInjectionSpec, newSpec.AppInjectionSpec) +} + +func compareActiveGateSpec(t *testing.T, oldSpec activegate.Spec, newSpec activegatev1beta4.Spec) { + assert.Equal(t, oldSpec.Annotations, newSpec.Annotations) + assert.Equal(t, oldSpec.TlsSecretName, newSpec.TlsSecretName) + assert.Equal(t, oldSpec.DNSPolicy, newSpec.DNSPolicy) + assert.Equal(t, oldSpec.PriorityClassName, newSpec.PriorityClassName) + + if oldSpec.CapabilityProperties.CustomProperties != nil || newSpec.CapabilityProperties.CustomProperties != nil { // necessary so we don't explode with nil pointer when not set + require.NotNil(t, oldSpec.CapabilityProperties.CustomProperties) + require.NotNil(t, newSpec.CapabilityProperties.CustomProperties) + assert.Equal(t, oldSpec.CapabilityProperties.CustomProperties.Value, newSpec.CapabilityProperties.CustomProperties.Value) + assert.Equal(t, oldSpec.CapabilityProperties.CustomProperties.ValueFrom, newSpec.CapabilityProperties.CustomProperties.ValueFrom) + } + + assert.Equal(t, oldSpec.CapabilityProperties.NodeSelector, newSpec.CapabilityProperties.NodeSelector) + assert.Equal(t, oldSpec.CapabilityProperties.Labels, newSpec.CapabilityProperties.Labels) + assert.Equal(t, *oldSpec.CapabilityProperties.Replicas, *newSpec.CapabilityProperties.Replicas) + assert.Equal(t, oldSpec.CapabilityProperties.Image, newSpec.CapabilityProperties.Image) + assert.Equal(t, oldSpec.CapabilityProperties.Group, newSpec.CapabilityProperties.Group) + assert.Equal(t, oldSpec.CapabilityProperties.Resources, newSpec.CapabilityProperties.Resources) + assert.Equal(t, oldSpec.CapabilityProperties.Tolerations, newSpec.CapabilityProperties.Tolerations) + assert.Equal(t, oldSpec.CapabilityProperties.Env, newSpec.CapabilityProperties.Env) + assert.Equal(t, oldSpec.CapabilityProperties.TopologySpreadConstraints, newSpec.CapabilityProperties.TopologySpreadConstraints) + + assert.Len(t, newSpec.Capabilities, len(oldSpec.Capabilities)) + + for _, oldCapability := range oldSpec.Capabilities { + assert.Contains(t, newSpec.Capabilities, activegatev1beta4.CapabilityDisplayName(oldCapability)) + } +} + +func compareStatus(t *testing.T, oldStatus DynaKubeStatus, newStatus dynakubev1beta4.DynaKubeStatus) { + // Base + assert.Equal(t, oldStatus.Conditions, newStatus.Conditions) + assert.Equal(t, oldStatus.DynatraceApi.LastTokenScopeRequest, newStatus.DynatraceApi.LastTokenScopeRequest) + assert.Equal(t, oldStatus.KubeSystemUUID, newStatus.KubeSystemUUID) + assert.Equal(t, oldStatus.Phase, newStatus.Phase) + assert.Equal(t, oldStatus.UpdatedTimestamp, newStatus.UpdatedTimestamp) + + // CodeModule + assert.Equal(t, oldStatus.CodeModules.VersionStatus, newStatus.CodeModules.VersionStatus) + + // ActiveGate + assert.Equal(t, oldStatus.ActiveGate.VersionStatus, newStatus.ActiveGate.VersionStatus) + assert.Equal(t, oldStatus.ActiveGate.ConnectionInfo.Endpoints, newStatus.ActiveGate.ConnectionInfo.Endpoints) + assert.Equal(t, oldStatus.ActiveGate.ConnectionInfo.LastRequest, newStatus.ActiveGate.ConnectionInfo.LastRequest) + assert.Equal(t, oldStatus.ActiveGate.ConnectionInfo.TenantUUID, newStatus.ActiveGate.ConnectionInfo.TenantUUID) + + // OneAgent + assert.Equal(t, oldStatus.OneAgent.VersionStatus, newStatus.OneAgent.VersionStatus) + assert.Equal(t, oldStatus.OneAgent.ConnectionInfoStatus.Endpoints, newStatus.OneAgent.ConnectionInfoStatus.Endpoints) + assert.Equal(t, oldStatus.OneAgent.ConnectionInfoStatus.LastRequest, newStatus.OneAgent.ConnectionInfoStatus.LastRequest) + assert.Equal(t, oldStatus.OneAgent.ConnectionInfoStatus.TenantUUID, newStatus.OneAgent.ConnectionInfoStatus.TenantUUID) + assert.Equal(t, oldStatus.OneAgent.Healthcheck, newStatus.OneAgent.Healthcheck) + assert.Equal(t, oldStatus.OneAgent.LastInstanceStatusUpdate, newStatus.OneAgent.LastInstanceStatusUpdate) + + require.Equal(t, len(oldStatus.OneAgent.Instances), len(newStatus.OneAgent.Instances)) + + for key, value := range oldStatus.OneAgent.Instances { + assert.Equal(t, value.IPAddress, newStatus.OneAgent.Instances[key].IPAddress) + assert.Equal(t, value.PodName, newStatus.OneAgent.Instances[key].PodName) + } + + require.Equal(t, len(oldStatus.OneAgent.ConnectionInfoStatus.CommunicationHosts), len(newStatus.OneAgent.ConnectionInfoStatus.CommunicationHosts)) + + for i, oldHost := range oldStatus.OneAgent.ConnectionInfoStatus.CommunicationHosts { + newHost := newStatus.OneAgent.ConnectionInfoStatus.CommunicationHosts[i] + assert.Equal(t, oldHost.Host, newHost.Host) + assert.Equal(t, oldHost.Port, newHost.Port) + assert.Equal(t, oldHost.Protocol, newHost.Protocol) + } +} + +func compareLogMonitoringSpec(t *testing.T, oldSpec *logmonitoring.Spec, newSpec *logmonitoringv1beta4.Spec) { + if oldSpec == nil { + assert.Nil(t, newSpec) + + return + } else { + require.NotNil(t, newSpec) + } + + assert.Len(t, newSpec.IngestRuleMatchers, len(oldSpec.IngestRuleMatchers)) + + for _, oldMatchers := range oldSpec.IngestRuleMatchers { + assert.True(t, slices.ContainsFunc(newSpec.IngestRuleMatchers, func(newMatchers logmonitoringv1beta4.IngestRuleMatchers) bool { + return slices.Equal(newMatchers.Values, oldMatchers.Values) && newMatchers.Attribute == oldMatchers.Attribute + })) + } +} + +func compareOpenTelemetryTemplateSpec(t *testing.T, oldSpec OpenTelemetryCollectorSpec, newSpec dynakubev1beta4.OpenTelemetryCollectorSpec) { + assert.Equal(t, oldSpec.Labels, newSpec.Labels) + assert.Equal(t, oldSpec.Annotations, newSpec.Annotations) + assert.Equal(t, *oldSpec.Replicas, *newSpec.Replicas) + assert.Equal(t, oldSpec.ImageRef, newSpec.ImageRef) + assert.Equal(t, oldSpec.TlsRefName, newSpec.TlsRefName) + assert.Equal(t, oldSpec.Resources, newSpec.Resources) + assert.Equal(t, oldSpec.Tolerations, newSpec.Tolerations) + assert.Equal(t, oldSpec.TopologySpreadConstraints, newSpec.TopologySpreadConstraints) +} + +func compareExtensionsExecutionControllerTemplateSpec(t *testing.T, oldSpec ExtensionExecutionControllerSpec, newSpec dynakubev1beta4.ExtensionExecutionControllerSpec) { + assert.Equal(t, *oldSpec.PersistentVolumeClaim, *newSpec.PersistentVolumeClaim) + assert.Equal(t, oldSpec.Labels, newSpec.Labels) + assert.Equal(t, oldSpec.Annotations, newSpec.Annotations) + assert.Equal(t, oldSpec.ImageRef, newSpec.ImageRef) + assert.Equal(t, oldSpec.TlsRefName, newSpec.TlsRefName) + assert.Equal(t, oldSpec.CustomConfig, newSpec.CustomConfig) + assert.Equal(t, oldSpec.CustomExtensionCertificates, newSpec.CustomExtensionCertificates) + assert.Equal(t, oldSpec.Resources, newSpec.Resources) + assert.Equal(t, oldSpec.Tolerations, newSpec.Tolerations) + assert.Equal(t, oldSpec.TopologySpreadConstraints, newSpec.TopologySpreadConstraints) + assert.Equal(t, oldSpec.UseEphemeralVolume, newSpec.UseEphemeralVolume) +} + +func compareLogMonitoringTemplateSpec(t *testing.T, oldSpec *logmonitoring.TemplateSpec, newSpec *logmonitoringv1beta4.TemplateSpec) { + if oldSpec == nil { + assert.Nil(t, newSpec) + + return + } else { + require.NotNil(t, newSpec) + } + + assert.Equal(t, oldSpec.Annotations, newSpec.Annotations) + assert.Equal(t, oldSpec.Labels, newSpec.Labels) + assert.Equal(t, oldSpec.NodeSelector, newSpec.NodeSelector) + assert.Equal(t, oldSpec.ImageRef, newSpec.ImageRef) + assert.Equal(t, oldSpec.DNSPolicy, newSpec.DNSPolicy) + assert.Equal(t, oldSpec.PriorityClassName, newSpec.PriorityClassName) + assert.Equal(t, oldSpec.SecCompProfile, newSpec.SecCompProfile) + assert.Equal(t, oldSpec.Resources, newSpec.Resources) + assert.Equal(t, oldSpec.Tolerations, newSpec.Tolerations) + assert.Equal(t, oldSpec.Args, newSpec.Args) +} + +func compareNodeConfigurationCollectorTemplateSpec(t *testing.T, oldSpec kspm.NodeConfigurationCollectorSpec, newSpec kspmv1beta4.NodeConfigurationCollectorSpec) { + assert.Equal(t, oldSpec.UpdateStrategy, newSpec.UpdateStrategy) + assert.Equal(t, oldSpec.Labels, newSpec.Labels) + assert.Equal(t, oldSpec.Annotations, newSpec.Annotations) + assert.Equal(t, oldSpec.NodeSelector, newSpec.NodeSelector) + assert.Equal(t, oldSpec.ImageRef, newSpec.ImageRef) + assert.Equal(t, oldSpec.PriorityClassName, newSpec.PriorityClassName) + assert.Equal(t, oldSpec.Resources, newSpec.Resources) + assert.Equal(t, oldSpec.NodeAffinity, newSpec.NodeAffinity) + assert.Equal(t, oldSpec.Tolerations, newSpec.Tolerations) + assert.Equal(t, oldSpec.Args, newSpec.Args) + assert.Equal(t, oldSpec.Env, newSpec.Env) +} + +func getNewDynakubeBase() dynakubev1beta4.DynaKube { + return dynakubev1beta4.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "name", + GenerateName: "generateName", + Namespace: "namespace", + Generation: 0xDEADBEEF, + Annotations: map[string]string{ + dynakubev1beta4.AnnotationFeatureActiveGateIgnoreProxy: "true", //nolint:staticcheck + dynakubev1beta4.AnnotationFeatureAutomaticK8sApiMonitoring: "true", + }, + Labels: map[string]string{ + "label": "label-value", + }, + Finalizers: []string{"finalizer1", "finalizer2"}, + }, + Spec: dynakubev1beta4.DynaKubeSpec{ + Proxy: &value.Source{ + Value: "proxy-value", + ValueFrom: "proxy-from", + }, + DynatraceApiRequestThreshold: ptr.To(uint16(42)), + APIURL: "api-url", + Tokens: "token", + TrustedCAs: "trusted-ca", + NetworkZone: "network-zone", + CustomPullSecret: "pull-secret", + SkipCertCheck: true, + EnableIstio: true, + MetadataEnrichment: dynakubev1beta4.MetadataEnrichment{ + Enabled: ptr.To(true), + NamespaceSelector: getTestNamespaceSelector(), + }, + }, + } +} + +func getNewHostInjectSpec() oneagentv1beta4.HostInjectSpec { + return oneagentv1beta4.HostInjectSpec{ + Version: "host-inject-version", + Image: "host-inject-image", + Tolerations: []corev1.Toleration{ + {Key: "host-inject-toleration-key", Operator: "In", Value: "host-inject-toleration-value"}, + }, + AutoUpdate: ptr.To(false), + DNSPolicy: corev1.DNSClusterFirstWithHostNet, + Annotations: map[string]string{ + "host-inject-annotation-key": "host-inject-annotation-value", + }, + Labels: map[string]string{ + "host-inject-label-key": "host-inject-label-value", + }, + Env: []corev1.EnvVar{ + {Name: "host-inject-env-1", Value: "host-inject-env-value-1", ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: "host-inject-env-from-1", + }, + }}, + {Name: "host-inject-env-2", Value: "host-inject-env-value-2", ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: "host-inject-env-from-2", + }, + }}, + }, + NodeSelector: map[string]string{ + "host-inject-node-selector-key": "host-inject-node-selector-value", + }, + PriorityClassName: "host-inject-priority-class", + Args: []string{ + "host-inject-arg-1", + "host-inject-arg-2", + }, + OneAgentResources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(1, 1)}, + }, + SecCompProfile: "seccomp", + } +} + +func getNewAppInjectionSpec() oneagentv1beta4.AppInjectionSpec { + return oneagentv1beta4.AppInjectionSpec{ + InitResources: &corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(2, 1)}, + }, + CodeModulesImage: "app-injection-image", + NamespaceSelector: getTestNamespaceSelector(), + } +} + +func getNewCloudNativeSpec() oneagentv1beta4.CloudNativeFullStackSpec { + return oneagentv1beta4.CloudNativeFullStackSpec{ + AppInjectionSpec: getNewAppInjectionSpec(), + HostInjectSpec: getNewHostInjectSpec(), + } +} + +func getNewApplicationMonitoringSpec() oneagentv1beta4.ApplicationMonitoringSpec { + return oneagentv1beta4.ApplicationMonitoringSpec{ + AppInjectionSpec: getNewAppInjectionSpec(), + Version: "app-monitoring-version", + } +} + +func getNewActiveGateSpec() activegatev1beta4.Spec { + return activegatev1beta4.Spec{ + DNSPolicy: corev1.DNSClusterFirstWithHostNet, + Annotations: map[string]string{ + "activegate-annotation-key": "activegate-annotation-value", + }, + TlsSecretName: "activegate-tls-secret-name", + PriorityClassName: "activegate-priority-class-name", + Capabilities: []activegatev1beta4.CapabilityDisplayName{ + activegatev1beta4.DynatraceApiCapability.DisplayName, + activegatev1beta4.KubeMonCapability.DisplayName, + activegatev1beta4.MetricsIngestCapability.DisplayName, + }, + CapabilityProperties: activegatev1beta4.CapabilityProperties{ + Labels: map[string]string{ + "activegate-label-key": "activegate-label-value", + }, + Env: []corev1.EnvVar{ + {Name: "host-inject-env-1", Value: "activegate-env-value-1", ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: "activegate-env-from-1", + }, + }}, + {Name: "activegate-env-2", Value: "activegate-env-value-2", ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: "activegate-env-from-2", + }, + }}, + }, + NodeSelector: map[string]string{ + "activegate-node-selector-key": "activegate-node-selector-value", + }, + Image: "activegate-image", + Replicas: ptr.To(int32(42)), + Group: "activegate-group", + CustomProperties: &value.Source{ + Value: "activegate-cp-value", + ValueFrom: "activegate-cp-value-from", + }, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1)}, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Claims: []corev1.ResourceClaim{{ + Name: "claim-name", + Request: "claim-request", + }}, + }, + Tolerations: []corev1.Toleration{ + {Key: "activegate-toleration-key", Operator: "In", Value: "activegate-toleration-value"}, + }, + TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ + {MaxSkew: 1}, + }, + }, + } +} + +func getNewLogMonitoringSpec() *logmonitoringv1beta4.Spec { + newSpec := logmonitoringv1beta4.Spec{ + IngestRuleMatchers: make([]logmonitoringv1beta4.IngestRuleMatchers, 0), + } + + newSpec.IngestRuleMatchers = append(newSpec.IngestRuleMatchers, logmonitoringv1beta4.IngestRuleMatchers{ + Attribute: "attribute1", + Values: []string{"matcher1", "matcher2", "matcher3"}, + }) + + newSpec.IngestRuleMatchers = append(newSpec.IngestRuleMatchers, logmonitoringv1beta4.IngestRuleMatchers{ + Attribute: "attribute2", + Values: []string{"matcher1", "matcher2", "matcher3"}, + }) + + newSpec.IngestRuleMatchers = append(newSpec.IngestRuleMatchers, logmonitoringv1beta4.IngestRuleMatchers{ + Attribute: "attribute3", + Values: []string{"matcher1", "matcher2", "matcher3"}, + }) + + return &newSpec +} + +func getNewOpenTelemetryTemplateSpec() dynakubev1beta4.OpenTelemetryCollectorSpec { + return dynakubev1beta4.OpenTelemetryCollectorSpec{ + Labels: map[string]string{ + "otelc-label-key1": "otelc-label-value1", + "otelc-label-key2": "otelc-label-value2", + }, + Annotations: map[string]string{ + "otelc-annotation-key1": "otelc-annotation-value1", + "otelc-annotation-key2": "otelc-annotation-value2", + }, + Replicas: ptr.To(int32(42)), + ImageRef: image.Ref{ + Repository: "image-repo.repohost.test/repo", + Tag: "image-tag", + }, + TlsRefName: "tls-ref-name", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Claims: []corev1.ResourceClaim{{ + Name: "claim-name", + Request: "claim-request", + }}, + }, + Tolerations: []corev1.Toleration{ + {Key: "otelc-toleration-key", Operator: "In", Value: "otelc-toleration-value"}, + }, + TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ + {MaxSkew: 1}, + }, + } +} + +func getNewExtensionExecutionControllerSpec() dynakubev1beta4.ExtensionExecutionControllerSpec { + return dynakubev1beta4.ExtensionExecutionControllerSpec{ + PersistentVolumeClaim: getPersistentVolumeClaimSpec(), + Labels: map[string]string{ + "eec-label-key1": "eec-label-value1", + "eec-label-key2": "eec-label-value2", + }, + Annotations: map[string]string{ + "eec-annotation-key1": "eec-annotation-value1", + "eec-annotation-key2": "eec-annotation-value2", + }, + ImageRef: image.Ref{ + Repository: "image-repo.repohost.test/repo", + Tag: "image-tag", + }, + TlsRefName: "tls-ref-name", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Claims: []corev1.ResourceClaim{{ + Name: "claim-name", + Request: "claim-request", + }}, + }, + Tolerations: []corev1.Toleration{ + {Key: "otelc-toleration-key", Operator: "In", Value: "otelc-toleration-value"}, + }, + TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ + {MaxSkew: 1}, + }, + CustomConfig: "custom-eec-config", + CustomExtensionCertificates: "custom-eec-certificates", + UseEphemeralVolume: true, + } +} + +func getPersistentVolumeClaimSpec() *corev1.PersistentVolumeClaimSpec { + return &corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "pvc-label-key1": "pvc-label-value1", + "pvc-label-key2": "pvc-label-value2", + }, + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "label-selector-key", + Operator: "label-selector-value", + Values: []string{"pvc-value-1", "pvc-value-key2"}, + }, + }, + }, + Resources: corev1.VolumeResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceStorage: *resource.NewScaledQuantity(3, 1), + }, + Requests: corev1.ResourceList{ + corev1.ResourceStorage: *resource.NewScaledQuantity(3, 1), + }, + }, + VolumeName: "volume-name", + StorageClassName: ptr.To("localstorage"), + VolumeMode: ptr.To(corev1.PersistentVolumeFilesystem), + VolumeAttributesClassName: ptr.To("volume-attributes-class-name"), + } +} + +func getNewLogMonitoringTemplateSpec() *logmonitoringv1beta4.TemplateSpec { + return &logmonitoringv1beta4.TemplateSpec{ + Labels: map[string]string{ + "logagent-label-key1": "logagent-label-value1", + "logagent-label-key2": "logagent-label-value2", + }, + Annotations: map[string]string{ + "logagent-annotation-key1": "logagent-annotation-value1", + "logagent-annotation-key2": "logagent-annotation-value2", + }, + NodeSelector: map[string]string{ + "selector1": "node1", + "selector2": "node2", + }, + ImageRef: image.Ref{ + Repository: "image-repo.repohost.test/repo", + Tag: "image-tag", + }, + DNSPolicy: "dns-policy", + PriorityClassName: "priority-class-name", + SecCompProfile: "sec-comp-profile", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Claims: []corev1.ResourceClaim{{ + Name: "claim-name", + Request: "claim-request", + }}, + }, + Tolerations: []corev1.Toleration{ + {Key: "otelc-toleration-key", Operator: "In", Value: "otelc-toleration-value"}, + }, + Args: []string{"--log-level", "debug", "--log-format", "json"}, + } +} + +func getNewNodeConfigurationCollectorTemplateSpec() kspmv1beta4.NodeConfigurationCollectorSpec { + return kspmv1beta4.NodeConfigurationCollectorSpec{ + UpdateStrategy: &v1.DaemonSetUpdateStrategy{ + Type: "daemonset-update-strategy-type", + RollingUpdate: &v1.RollingUpdateDaemonSet{ + MaxUnavailable: &intstr.IntOrString{ + Type: 0, + IntVal: 42, + }, + MaxSurge: &intstr.IntOrString{ + Type: 1, + StrVal: "42", + }, + }, + }, + Labels: map[string]string{ + "ncc-label-key1": "ncc-label-value1", + "ncc-label-key2": "ncc-label-value2", + }, + Annotations: map[string]string{ + "ncc-annotation-key1": "ncc-annotation-value1", + "ncc-annotation-key2": "ncc-annotation-value2", + }, + NodeSelector: map[string]string{ + "selector1": "node1", + "selector2": "node2", + }, + ImageRef: image.Ref{ + Repository: "image-repo.repohost.test/repo", + Tag: "image-tag", + }, + PriorityClassName: "priority-class-name", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Claims: []corev1.ResourceClaim{{ + Name: "claim-name", + Request: "claim-request", + }}, + }, + NodeAffinity: corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{{ + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "node-selector-match-key", + Operator: "node-selector-match-operator", + Values: []string{"node-match-value-1", "node-match-value2"}, + }, + }, + MatchFields: []corev1.NodeSelectorRequirement{ + { + Key: "node-selector-field-key", + Operator: "node-selector-field-operator", + Values: []string{"node-field-value-1", "node-field-value2"}, + }, + }, + }}, + }, + PreferredDuringSchedulingIgnoredDuringExecution: nil, + }, + Tolerations: []corev1.Toleration{ + {Key: "otelc-toleration-key", Operator: "In", Value: "otelc-toleration-value"}, + }, + Args: []string{"--log-level", "debug", "--log-format", "json"}, + Env: []corev1.EnvVar{ + { + Name: "ENV1", + Value: "VAL1", + }, + { + Name: "ENV2", + Value: "VAL2", + }, + { + Name: "ENV2", + Value: "VAL2", + }, + }, + } +} + +func getNewStatus() dynakubev1beta4.DynaKubeStatus { + return dynakubev1beta4.DynaKubeStatus{ + OneAgent: oneagentv1beta4.Status{ + VersionStatus: status.VersionStatus{ + ImageID: "oa-image-id", + Version: "oa-version", + Type: "oa-image-type", + Source: status.CustomImageVersionSource, + LastProbeTimestamp: &testTime, + }, + Instances: map[string]oneagentv1beta4.Instance{ + "oa-instance-key-1": { + PodName: "oa-instance-pod-1", + IPAddress: "oa-instance-ip-1", + }, + "oa-instance-key-2": { + PodName: "oa-instance-pod-2", + IPAddress: "oa-instance-ip-2", + }, + }, + LastInstanceStatusUpdate: &testTime, + Healthcheck: ®istryv1.HealthConfig{ + Test: []string{"oa-health-check-test"}, + }, + ConnectionInfoStatus: oneagentv1beta4.ConnectionInfoStatus{ + ConnectionInfo: communication.ConnectionInfo{ + LastRequest: testTime, + TenantUUID: "oa-tenant-uuid", + Endpoints: "oa-endpoints", + }, + CommunicationHosts: []oneagentv1beta4.CommunicationHostStatus{ + { + Protocol: "oa-protocol-1", + Host: "oa-host-1", + Port: 1, + }, + { + Protocol: "oa-protocol-2", + Host: "oa-host-2", + Port: 2, + }, + }, + }, + }, + ActiveGate: activegatev1beta4.Status{ + VersionStatus: status.VersionStatus{ + ImageID: "ag-image-id", + Version: "ag-version", + Type: "ag-image-type", + Source: status.CustomVersionVersionSource, + LastProbeTimestamp: &testTime, + }, + }, + CodeModules: oneagentv1beta4.CodeModulesStatus{ + VersionStatus: status.VersionStatus{ + ImageID: "cm-image-id", + Version: "cm-version", + Type: "cm-image-type", + Source: status.TenantRegistryVersionSource, + LastProbeTimestamp: &testTime, + }, + }, + DynatraceApi: dynakubev1beta4.DynatraceApiStatus{ + LastTokenScopeRequest: testTime, + }, + Conditions: []metav1.Condition{ + { + Type: "condition-type-1", + Status: "condition-status-1", + Reason: "condition-reason-1", + LastTransitionTime: testTime, + }, + { + Type: "condition-type-2", + Status: "condition-status-2", + Reason: "condition-reason-2", + LastTransitionTime: testTime, + }, + }, + KubeSystemUUID: "kube-system-uuid", + Phase: status.Deploying, + UpdatedTimestamp: testTime, + } +} diff --git a/pkg/api/v1beta3/dynakube/convert_to.go b/pkg/api/v1beta3/dynakube/convert_to.go new file mode 100644 index 0000000000..481fde97fe --- /dev/null +++ b/pkg/api/v1beta3/dynakube/convert_to.go @@ -0,0 +1,294 @@ +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + dynakubev1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + activegatev1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + kspmv1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" + logmonitoringv1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + oneagentv1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +// Convertto converts this version (src=v1beta3) to the Hub version. +func (src *DynaKube) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*dynakubev1beta4.DynaKube) + + src.toStatus(dst) + + src.toBase(dst) + src.toMetadataEnrichment(dst) + src.toLogMonitoringSpec(dst) + src.toKspmSpec(dst) + src.toExtensionsSpec(dst) + src.toOneAgentSpec(dst) + src.toActiveGateSpec(dst) + src.toTemplatesSpec(dst) + + return nil +} + +func (src *DynaKube) toBase(dst *dynakubev1beta4.DynaKube) { + if src.Annotations == nil { + dst.Annotations = map[string]string{} + } + + dst.ObjectMeta = *src.ObjectMeta.DeepCopy() // DeepCopy mainly relevant for testing + + dst.Spec.Proxy = src.Spec.Proxy + dst.Spec.DynatraceApiRequestThreshold = src.Spec.DynatraceApiRequestThreshold + dst.Spec.APIURL = src.Spec.APIURL + dst.Spec.Tokens = src.Spec.Tokens + dst.Spec.TrustedCAs = src.Spec.TrustedCAs + dst.Spec.NetworkZone = src.Spec.NetworkZone + dst.Spec.CustomPullSecret = src.Spec.CustomPullSecret + dst.Spec.SkipCertCheck = src.Spec.SkipCertCheck + dst.Spec.EnableIstio = src.Spec.EnableIstio +} + +func (src *DynaKube) toLogMonitoringSpec(dst *dynakubev1beta4.DynaKube) { + if src.Spec.LogMonitoring != nil { + dst.Spec.LogMonitoring = &logmonitoringv1beta4.Spec{} + dst.Spec.LogMonitoring.IngestRuleMatchers = make([]logmonitoringv1beta4.IngestRuleMatchers, 0) + + for _, rule := range src.Spec.LogMonitoring.IngestRuleMatchers { + dst.Spec.LogMonitoring.IngestRuleMatchers = append(dst.Spec.LogMonitoring.IngestRuleMatchers, logmonitoringv1beta4.IngestRuleMatchers{ + Attribute: rule.Attribute, + Values: rule.Values, + }) + } + } +} + +func (src *DynaKube) toKspmSpec(dst *dynakubev1beta4.DynaKube) { + if src.Spec.Kspm != nil { + dst.Spec.Kspm = &kspmv1beta4.Spec{} + } +} + +func (src *DynaKube) toExtensionsSpec(dst *dynakubev1beta4.DynaKube) { + if src.Spec.Extensions != nil { + dst.Spec.Extensions = &dynakubev1beta4.ExtensionsSpec{} + } +} + +func (src *DynaKube) toOneAgentSpec(dst *dynakubev1beta4.DynaKube) { //nolint:dupl + switch { + case src.OneAgent().IsClassicFullStackMode(): + dst.Spec.OneAgent.ClassicFullStack = toHostInjectSpec(*src.Spec.OneAgent.ClassicFullStack) + case src.OneAgent().IsCloudNativeFullstackMode(): + dst.Spec.OneAgent.CloudNativeFullStack = &oneagentv1beta4.CloudNativeFullStackSpec{} + dst.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec = *toHostInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.HostInjectSpec) + dst.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec = *toAppInjectSpec(src.Spec.OneAgent.CloudNativeFullStack.AppInjectionSpec) + case src.OneAgent().IsApplicationMonitoringMode(): + dst.Spec.OneAgent.ApplicationMonitoring = &oneagentv1beta4.ApplicationMonitoringSpec{} + dst.Spec.OneAgent.ApplicationMonitoring.Version = src.Spec.OneAgent.ApplicationMonitoring.Version + dst.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec = *toAppInjectSpec(src.Spec.OneAgent.ApplicationMonitoring.AppInjectionSpec) + case src.OneAgent().IsHostMonitoringMode(): + dst.Spec.OneAgent.HostMonitoring = toHostInjectSpec(*src.Spec.OneAgent.HostMonitoring) + } + + dst.Spec.OneAgent.HostGroup = src.Spec.OneAgent.HostGroup +} + +func (src *DynaKube) toTemplatesSpec(dst *dynakubev1beta4.DynaKube) { + dst.Spec.Templates.LogMonitoring = toLogMonitoringTemplate(src.Spec.Templates.LogMonitoring) + dst.Spec.Templates.KspmNodeConfigurationCollector = toKspmNodeConfigurationCollectorTemplate(src.Spec.Templates.KspmNodeConfigurationCollector) + dst.Spec.Templates.OpenTelemetryCollector = toOpenTelemetryCollectorTemplate(src.Spec.Templates.OpenTelemetryCollector) + dst.Spec.Templates.ExtensionExecutionController = toExtensionControllerTemplate(src.Spec.Templates.ExtensionExecutionController) +} + +func toLogMonitoringTemplate(src *logmonitoring.TemplateSpec) *logmonitoringv1beta4.TemplateSpec { + if src == nil { + return nil + } + + dst := &logmonitoringv1beta4.TemplateSpec{} + + dst.Annotations = src.Annotations + dst.Labels = src.Labels + dst.NodeSelector = src.NodeSelector + dst.ImageRef = src.ImageRef + dst.DNSPolicy = src.DNSPolicy + dst.PriorityClassName = src.PriorityClassName + dst.SecCompProfile = src.SecCompProfile + dst.Resources = src.Resources + dst.Tolerations = src.Tolerations + dst.Args = src.Args + + return dst +} + +func toKspmNodeConfigurationCollectorTemplate(src kspm.NodeConfigurationCollectorSpec) kspmv1beta4.NodeConfigurationCollectorSpec { + dst := kspmv1beta4.NodeConfigurationCollectorSpec{} + + dst.UpdateStrategy = src.UpdateStrategy + dst.Labels = src.Labels + dst.Annotations = src.Annotations + dst.NodeSelector = src.NodeSelector + dst.ImageRef = src.ImageRef + dst.PriorityClassName = src.PriorityClassName + dst.Resources = src.Resources + dst.NodeAffinity = src.NodeAffinity + dst.Tolerations = src.Tolerations + dst.Args = src.Args + dst.Env = src.Env + + return dst +} + +func toOpenTelemetryCollectorTemplate(src OpenTelemetryCollectorSpec) dynakubev1beta4.OpenTelemetryCollectorSpec { + dst := dynakubev1beta4.OpenTelemetryCollectorSpec{} + + dst.Labels = src.Labels + dst.Annotations = src.Annotations + dst.Replicas = src.Replicas + dst.ImageRef = src.ImageRef + dst.TlsRefName = src.TlsRefName + dst.Resources = src.Resources + dst.Tolerations = src.Tolerations + dst.TopologySpreadConstraints = src.TopologySpreadConstraints + + return dst +} + +func toExtensionControllerTemplate(src ExtensionExecutionControllerSpec) dynakubev1beta4.ExtensionExecutionControllerSpec { + dst := dynakubev1beta4.ExtensionExecutionControllerSpec{} + + dst.PersistentVolumeClaim = src.PersistentVolumeClaim + dst.Labels = src.Labels + dst.Annotations = src.Annotations + dst.ImageRef = src.ImageRef + dst.TlsRefName = src.TlsRefName + dst.CustomConfig = src.CustomConfig + dst.CustomExtensionCertificates = src.CustomExtensionCertificates + dst.Resources = src.Resources + dst.Tolerations = src.Tolerations + dst.TopologySpreadConstraints = src.TopologySpreadConstraints + dst.UseEphemeralVolume = src.UseEphemeralVolume + + return dst +} + +func (src *DynaKube) toActiveGateSpec(dst *dynakubev1beta4.DynaKube) { //nolint:dupl + dst.Spec.ActiveGate.Annotations = src.Spec.ActiveGate.Annotations + dst.Spec.ActiveGate.TlsSecretName = src.Spec.ActiveGate.TlsSecretName + dst.Spec.ActiveGate.DNSPolicy = src.Spec.ActiveGate.DNSPolicy + dst.Spec.ActiveGate.PriorityClassName = src.Spec.ActiveGate.PriorityClassName + + dst.Spec.ActiveGate.CapabilityProperties.CustomProperties = src.Spec.ActiveGate.CapabilityProperties.CustomProperties + dst.Spec.ActiveGate.CapabilityProperties.NodeSelector = src.Spec.ActiveGate.CapabilityProperties.NodeSelector + dst.Spec.ActiveGate.CapabilityProperties.Labels = src.Spec.ActiveGate.CapabilityProperties.Labels + dst.Spec.ActiveGate.CapabilityProperties.Replicas = src.Spec.ActiveGate.CapabilityProperties.Replicas + dst.Spec.ActiveGate.CapabilityProperties.Image = src.Spec.ActiveGate.CapabilityProperties.Image + dst.Spec.ActiveGate.CapabilityProperties.Group = src.Spec.ActiveGate.CapabilityProperties.Group + dst.Spec.ActiveGate.CapabilityProperties.Resources = src.Spec.ActiveGate.CapabilityProperties.Resources + dst.Spec.ActiveGate.CapabilityProperties.Tolerations = src.Spec.ActiveGate.CapabilityProperties.Tolerations + dst.Spec.ActiveGate.CapabilityProperties.Env = src.Spec.ActiveGate.CapabilityProperties.Env + dst.Spec.ActiveGate.CapabilityProperties.TopologySpreadConstraints = src.Spec.ActiveGate.CapabilityProperties.TopologySpreadConstraints + + dst.Spec.ActiveGate.Capabilities = make([]activegatev1beta4.CapabilityDisplayName, 0) + for _, capability := range src.Spec.ActiveGate.Capabilities { + dst.Spec.ActiveGate.Capabilities = append(dst.Spec.ActiveGate.Capabilities, activegatev1beta4.CapabilityDisplayName(capability)) + } +} + +func (src *DynaKube) toStatus(dst *dynakubev1beta4.DynaKube) { + src.toOneAgentStatus(dst) + src.toActiveGateStatus(dst) + dst.Status.CodeModules = oneagentv1beta4.CodeModulesStatus{ + VersionStatus: src.Status.CodeModules.VersionStatus, + } + + dst.Status.MetadataEnrichment.Rules = make([]dynakubev1beta4.EnrichmentRule, 0) + for _, rule := range src.Status.MetadataEnrichment.Rules { + dst.Status.MetadataEnrichment.Rules = append(dst.Status.MetadataEnrichment.Rules, + dynakubev1beta4.EnrichmentRule{ + Type: dynakubev1beta4.EnrichmentRuleType(rule.Type), + Source: rule.Source, + Target: rule.Target, + Enabled: rule.Enabled, + }) + } + + dst.Status.Kspm.TokenSecretHash = src.Status.Kspm.TokenSecretHash + dst.Status.UpdatedTimestamp = src.Status.UpdatedTimestamp + dst.Status.DynatraceApi = dynakubev1beta4.DynatraceApiStatus{ + LastTokenScopeRequest: src.Status.DynatraceApi.LastTokenScopeRequest, + } + dst.Status.Phase = src.Status.Phase + dst.Status.KubeSystemUUID = src.Status.KubeSystemUUID + dst.Status.KubernetesClusterMEID = src.Status.KubernetesClusterMEID + dst.Status.KubernetesClusterName = src.Status.KubernetesClusterName + dst.Status.Conditions = src.Status.Conditions +} + +func (src *DynaKube) toOneAgentStatus(dst *dynakubev1beta4.DynaKube) { //nolint:dupl + dst.Status.OneAgent.VersionStatus = src.Status.OneAgent.VersionStatus + + dst.Status.OneAgent.Instances = map[string]oneagentv1beta4.Instance{} + for key, instance := range src.Status.OneAgent.Instances { + dst.Status.OneAgent.Instances[key] = oneagentv1beta4.Instance{ + PodName: instance.PodName, + IPAddress: instance.IPAddress, + } + } + + dst.Status.OneAgent.LastInstanceStatusUpdate = src.Status.OneAgent.LastInstanceStatusUpdate + dst.Status.OneAgent.Healthcheck = src.Status.OneAgent.Healthcheck + + dst.Status.OneAgent.ConnectionInfoStatus.ConnectionInfo = src.Status.OneAgent.ConnectionInfoStatus.ConnectionInfo + dst.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = make([]oneagentv1beta4.CommunicationHostStatus, 0) + + for _, host := range src.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts { + dst.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = + append(dst.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts, oneagentv1beta4.CommunicationHostStatus{ + Protocol: host.Protocol, + Host: host.Host, + Port: host.Port, + }) + } +} + +func (src *DynaKube) toActiveGateStatus(dst *dynakubev1beta4.DynaKube) { + dst.Status.ActiveGate.VersionStatus = src.Status.ActiveGate.VersionStatus + dst.Status.ActiveGate.ConnectionInfo = src.Status.ActiveGate.ConnectionInfo + dst.Status.ActiveGate.ServiceIPs = src.Status.ActiveGate.ServiceIPs +} + +func toHostInjectSpec(src oneagent.HostInjectSpec) *oneagentv1beta4.HostInjectSpec { + dst := &oneagentv1beta4.HostInjectSpec{} + + dst.Annotations = src.Annotations + dst.Labels = src.Labels + dst.NodeSelector = src.NodeSelector + dst.AutoUpdate = src.AutoUpdate + dst.Version = src.Version + dst.Image = src.Image + dst.DNSPolicy = src.DNSPolicy + dst.PriorityClassName = src.PriorityClassName + dst.SecCompProfile = src.SecCompProfile + dst.OneAgentResources = src.OneAgentResources + dst.Tolerations = src.Tolerations + dst.Env = src.Env + dst.Args = src.Args + + return dst +} + +func toAppInjectSpec(src oneagent.AppInjectionSpec) *oneagentv1beta4.AppInjectionSpec { + dst := &oneagentv1beta4.AppInjectionSpec{} + + dst.InitResources = src.InitResources + dst.CodeModulesImage = src.CodeModulesImage + dst.NamespaceSelector = src.NamespaceSelector + + return dst +} + +func (src *DynaKube) toMetadataEnrichment(dst *dynakubev1beta4.DynaKube) { + dst.Spec.MetadataEnrichment.Enabled = src.Spec.MetadataEnrichment.Enabled + dst.Spec.MetadataEnrichment.NamespaceSelector = src.Spec.MetadataEnrichment.NamespaceSelector +} diff --git a/pkg/api/v1beta3/dynakube/convert_to_test.go b/pkg/api/v1beta3/dynakube/convert_to_test.go new file mode 100644 index 0000000000..d6024ae2b2 --- /dev/null +++ b/pkg/api/v1beta3/dynakube/convert_to_test.go @@ -0,0 +1,707 @@ +package dynakube + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + dynakubev1beta4 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + registryv1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" +) + +var testTime = metav1.Now() + +func TestConvertTo(t *testing.T) { + t.Run("migrate from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + compareBase(t, from, to) + }) + + t.Run("migrate metadata-enrichment from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + assert.False(t, to.MetadataEnrichmentEnabled()) + compareBase(t, from, to) + }) + + t.Run("migrate host-monitoring from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + hostSpec := getOldHostInjectSpec() + from.Spec.OneAgent.HostMonitoring = &hostSpec + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + compareHostInjectSpec(t, *from.Spec.OneAgent.HostMonitoring, *to.Spec.OneAgent.HostMonitoring) + compareBase(t, from, to) + assert.False(t, to.MetadataEnrichmentEnabled()) + }) + + t.Run("migrate classic-fullstack from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + hostSpec := getOldHostInjectSpec() + from.Spec.OneAgent.ClassicFullStack = &hostSpec + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + compareHostInjectSpec(t, *from.Spec.OneAgent.ClassicFullStack, *to.Spec.OneAgent.ClassicFullStack) + compareBase(t, from, to) + assert.False(t, to.MetadataEnrichmentEnabled()) + }) + + t.Run("migrate cloud-native from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + spec := getOldCloudNativeSpec() + from.Spec.OneAgent.CloudNativeFullStack = &spec + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.ApplicationMonitoring) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + compareCloudNativeSpec(t, *from.Spec.OneAgent.CloudNativeFullStack, *to.Spec.OneAgent.CloudNativeFullStack) + compareBase(t, from, to) + }) + + t.Run("migrate application-monitoring from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + appSpec := getOldApplicationMonitoringSpec() + from.Spec.OneAgent.ApplicationMonitoring = &appSpec + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + assert.Nil(t, to.Spec.OneAgent.ClassicFullStack) + assert.Nil(t, to.Spec.OneAgent.CloudNativeFullStack) + assert.Nil(t, to.Spec.OneAgent.HostMonitoring) + compareApplicationMonitoringSpec(t, *from.Spec.OneAgent.ApplicationMonitoring, *to.Spec.OneAgent.ApplicationMonitoring) + compareBase(t, from, to) + }) + + t.Run("migrate activegate from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + agSpec := getOldActiveGateSpec() + from.Spec.ActiveGate = agSpec + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + compareActiveGateSpec(t, from.Spec.ActiveGate, to.Spec.ActiveGate) + compareBase(t, from, to) + assert.False(t, to.MetadataEnrichmentEnabled()) + }) + + t.Run("migrate extensions from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + from.Spec.Extensions = &ExtensionsSpec{} + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + assert.NotNil(t, to.Spec.Extensions) + compareBase(t, from, to) + }) + + t.Run("migrate log-monitoring from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + from.Spec.LogMonitoring = getOldLogMonitoringSpec() + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + compareLogMonitoringSpec(t, from.Spec.LogMonitoring, to.Spec.LogMonitoring) + compareBase(t, from, to) + }) + + t.Run("migrate kspm from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + from.Spec.Kspm = &kspm.Spec{} + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + assert.NotNil(t, to.Spec.Kspm) + compareBase(t, from, to) + }) + + t.Run("migrate extensions templates from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + from.Spec.Templates.OpenTelemetryCollector = getOldOpenTelemetryTemplateSpec() + from.Spec.Templates.ExtensionExecutionController = getOldExtensionExecutionControllerSpec() + + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + compareOpenTelemetryTemplateSpec(t, from.Spec.Templates.OpenTelemetryCollector, to.Spec.Templates.OpenTelemetryCollector) + compareExtensionsExecutionControllerTemplateSpec(t, from.Spec.Templates.ExtensionExecutionController, to.Spec.Templates.ExtensionExecutionController) + + compareBase(t, from, to) + }) + + t.Run("migrate log-monitoring templates from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + from.Spec.Templates.LogMonitoring = getOldLogMonitoringTemplateSpec() + + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + compareLogMonitoringTemplateSpec(t, from.Spec.Templates.LogMonitoring, to.Spec.Templates.LogMonitoring) + compareBase(t, from, to) + }) + + t.Run("migrate kspm templates from v1beta4 to v1beta3", func(t *testing.T) { + from := getOldDynakubeBase() + from.Spec.Templates.KspmNodeConfigurationCollector = getOldNodeConfigurationCollectorTemplateSpec() + + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + compareNodeConfigurationCollectorTemplateSpec(t, from.Spec.Templates.KspmNodeConfigurationCollector, to.Spec.Templates.KspmNodeConfigurationCollector) + compareBase(t, from, to) + }) + + t.Run("migrate status from v1beta3 to v1beta4", func(t *testing.T) { + from := getOldDynakubeBase() + from.Status = getOldStatus() + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + compareStatus(t, from.Status, to.Status) + }) + + t.Run("migrate hostGroup", func(t *testing.T) { + from := getOldDynakubeBase() + from.Status = getOldStatus() + to := dynakubev1beta4.DynaKube{} + + err := from.ConvertTo(&to) + require.NoError(t, err) + + assert.Equal(t, from.Spec.OneAgent.HostGroup, to.Spec.OneAgent.HostGroup) + }) +} + +func getTestNamespaceSelector() metav1.LabelSelector { + return metav1.LabelSelector{ + MatchLabels: map[string]string{ + "match-label-key": "match-label-value", + }, + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "match-expression-key", + Operator: "In", + Values: []string{"match-expression-value-test-1", "match-expression-value-test-2"}, + }, + }, + } +} + +func getOldDynakubeBase() DynaKube { + return DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "name", + Namespace: "namespace", + Annotations: map[string]string{ + dynakubev1beta4.AnnotationFeatureActiveGateIgnoreProxy: "true", //nolint:staticcheck + dynakubev1beta4.AnnotationFeatureAutomaticK8sApiMonitoring: "true", + }, + Labels: map[string]string{ + "label": "label-value", + }, + }, + Spec: DynaKubeSpec{ + OneAgent: oneagent.Spec{HostGroup: "hostgroup-value"}, + APIURL: "api-url", + Tokens: "token", + CustomPullSecret: "pull-secret", + EnableIstio: true, + SkipCertCheck: true, + Proxy: &value.Source{ + Value: "proxy-value", + ValueFrom: "proxy-from", + }, + TrustedCAs: "trusted-ca", + NetworkZone: "network-zone", + DynatraceApiRequestThreshold: ptr.To(uint16(42)), + MetadataEnrichment: MetadataEnrichment{ + Enabled: ptr.To(false), + }, + }, + } +} + +func getOldHostInjectSpec() oneagent.HostInjectSpec { + return oneagent.HostInjectSpec{ + Version: "host-inject-version", + Image: "host-inject-image", + Tolerations: []corev1.Toleration{ + {Key: "host-inject-toleration-key", Operator: "In", Value: "host-inject-toleration-value"}, + }, + AutoUpdate: ptr.To(false), + DNSPolicy: corev1.DNSClusterFirstWithHostNet, + Annotations: map[string]string{ + "host-inject-annotation-key": "host-inject-annotation-value", + }, + Labels: map[string]string{ + "host-inject-label-key": "host-inject-label-value", + }, + Env: []corev1.EnvVar{ + {Name: "host-inject-env-1", Value: "host-inject-env-value-1", ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: "host-inject-env-from-1", + }, + }}, + {Name: "host-inject-env-2", Value: "host-inject-env-value-2", ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: "host-inject-env-from-2", + }, + }}, + }, + NodeSelector: map[string]string{ + "host-inject-node-selector-key": "host-inject-node-selector-value", + }, + PriorityClassName: "host-inject-priority-class", + Args: []string{ + "host-inject-arg-1", + "host-inject-arg-2", + }, + OneAgentResources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(1, 1)}, + }, + SecCompProfile: "seccomp", + } +} + +func getOldAppInjectionSpec() oneagent.AppInjectionSpec { + return oneagent.AppInjectionSpec{ + InitResources: &corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(2, 1)}, + }, + CodeModulesImage: "app-injection-image", + NamespaceSelector: getTestNamespaceSelector(), + } +} + +func getOldCloudNativeSpec() oneagent.CloudNativeFullStackSpec { + return oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: getOldAppInjectionSpec(), + HostInjectSpec: getOldHostInjectSpec(), + } +} + +func getOldApplicationMonitoringSpec() oneagent.ApplicationMonitoringSpec { + return oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: getOldAppInjectionSpec(), + Version: "app-monitoring-version", + } +} + +func getOldActiveGateSpec() activegate.Spec { + return activegate.Spec{ + DNSPolicy: corev1.DNSClusterFirstWithHostNet, + Annotations: map[string]string{ + "activegate-annotation-key": "activegate-annotation-value", + }, + TlsSecretName: "activegate-tls-secret-name", + PriorityClassName: "activegate-priority-class-name", + Capabilities: []activegate.CapabilityDisplayName{ + activegate.DynatraceApiCapability.DisplayName, + activegate.KubeMonCapability.DisplayName, + activegate.MetricsIngestCapability.DisplayName, + }, + CapabilityProperties: activegate.CapabilityProperties{ + Labels: map[string]string{ + "activegate-label-key": "activegate-label-value", + }, + Env: []corev1.EnvVar{ + {Name: "host-inject-env-1", Value: "activegate-env-value-1", ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: "activegate-env-from-1", + }, + }}, + {Name: "activegate-env-2", Value: "activegate-env-value-2", ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: "activegate-env-from-2", + }, + }}, + }, + NodeSelector: map[string]string{ + "activegate-node-selector-key": "activegate-node-selector-value", + }, + Image: "activegate-image", + Replicas: ptr.To(int32(42)), + Group: "activegate-group", + CustomProperties: &value.Source{ + Value: "activegate-cp-value", + ValueFrom: "activegate-cp-value-from", + }, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1)}, + }, + Tolerations: []corev1.Toleration{ + {Key: "activegate-toleration-key", Operator: "In", Value: "activegate-toleration-value"}, + }, + TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ + {MaxSkew: 1}, + }, + }, + } +} + +func getOldLogMonitoringSpec() *logmonitoring.Spec { + oldSpec := logmonitoring.Spec{ + IngestRuleMatchers: make([]logmonitoring.IngestRuleMatchers, 0), + } + + oldSpec.IngestRuleMatchers = append(oldSpec.IngestRuleMatchers, logmonitoring.IngestRuleMatchers{ + Attribute: "attribute1", + Values: []string{"matcher1", "matcher2", "matcher3"}, + }) + + oldSpec.IngestRuleMatchers = append(oldSpec.IngestRuleMatchers, logmonitoring.IngestRuleMatchers{ + Attribute: "attribute2", + Values: []string{"matcher1", "matcher2", "matcher3"}, + }) + + oldSpec.IngestRuleMatchers = append(oldSpec.IngestRuleMatchers, logmonitoring.IngestRuleMatchers{ + Attribute: "attribute3", + Values: []string{"matcher1", "matcher2", "matcher3"}, + }) + + return &oldSpec +} + +func getOldOpenTelemetryTemplateSpec() OpenTelemetryCollectorSpec { + return OpenTelemetryCollectorSpec{ + Labels: map[string]string{ + "otelc-label-key1": "otelc-label-value1", + "otelc-label-key2": "otelc-label-value2", + }, + Annotations: map[string]string{ + "otelc-annotation-key1": "otelc-annotation-value1", + "otelc-annotation-key2": "otelc-annotation-value2", + }, + Replicas: ptr.To(int32(42)), + ImageRef: image.Ref{ + Repository: "image-repo.repohost.test/repo", + Tag: "image-tag", + }, + TlsRefName: "tls-ref-name", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Claims: []corev1.ResourceClaim{{ + Name: "claim-name", + Request: "claim-request", + }}, + }, + Tolerations: []corev1.Toleration{ + {Key: "otelc-toleration-key", Operator: "In", Value: "otelc-toleration-value"}, + }, + TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ + {MaxSkew: 1}, + }, + } +} + +func getOldExtensionExecutionControllerSpec() ExtensionExecutionControllerSpec { + return ExtensionExecutionControllerSpec{ + PersistentVolumeClaim: getPersistentVolumeClaimSpec(), + Labels: map[string]string{ + "eec-label-key1": "eec-label-value1", + "eec-label-key2": "eec-label-value2", + }, + Annotations: map[string]string{ + "eec-annotation-key1": "eec-annotation-value1", + "eec-annotation-key2": "eec-annotation-value2", + }, + ImageRef: image.Ref{ + Repository: "image-repo.repohost.test/repo", + Tag: "image-tag", + }, + TlsRefName: "tls-ref-name", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Claims: []corev1.ResourceClaim{{ + Name: "claim-name", + Request: "claim-request", + }}, + }, + Tolerations: []corev1.Toleration{ + {Key: "otelc-toleration-key", Operator: "In", Value: "otelc-toleration-value"}, + }, + TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ + {MaxSkew: 1}, + }, + CustomConfig: "custom-eec-config", + CustomExtensionCertificates: "custom-eec-certificates", + UseEphemeralVolume: true, + } +} + +func getOldLogMonitoringTemplateSpec() *logmonitoring.TemplateSpec { + return &logmonitoring.TemplateSpec{ + Labels: map[string]string{ + "logagent-label-key1": "logagent-label-value1", + "logagent-label-key2": "logagent-label-value2", + }, + Annotations: map[string]string{ + "logagent-annotation-key1": "logagent-annotation-value1", + "logagent-annotation-key2": "logagent-annotation-value2", + }, + NodeSelector: map[string]string{ + "selector1": "node1", + "selector2": "node2", + }, + ImageRef: image.Ref{ + Repository: "image-repo.repohost.test/repo", + Tag: "image-tag", + }, + DNSPolicy: "dns-policy", + PriorityClassName: "priority-class-name", + SecCompProfile: "sec-comp-profile", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Claims: []corev1.ResourceClaim{{ + Name: "claim-name", + Request: "claim-request", + }}, + }, + Tolerations: []corev1.Toleration{ + {Key: "otelc-toleration-key", Operator: "In", Value: "otelc-toleration-value"}, + }, + Args: []string{"--log-level", "debug", "--log-format", "json"}, + } +} + +func getOldNodeConfigurationCollectorTemplateSpec() kspm.NodeConfigurationCollectorSpec { + return kspm.NodeConfigurationCollectorSpec{ + UpdateStrategy: &v1.DaemonSetUpdateStrategy{ + Type: "daemonset-update-strategy-type", + RollingUpdate: &v1.RollingUpdateDaemonSet{ + MaxUnavailable: &intstr.IntOrString{ + Type: 0, + IntVal: 42, + }, + MaxSurge: &intstr.IntOrString{ + Type: 1, + StrVal: "42", + }, + }, + }, + Labels: map[string]string{ + "ncc-label-key1": "ncc-label-value1", + "ncc-label-key2": "ncc-label-value2", + }, + Annotations: map[string]string{ + "ncc-annotation-key1": "ncc-annotation-value1", + "ncc-annotation-key2": "ncc-annotation-value2", + }, + NodeSelector: map[string]string{ + "selector1": "node1", + "selector2": "node2", + }, + ImageRef: image.Ref{ + Repository: "image-repo.repohost.test/repo", + Tag: "image-tag", + }, + PriorityClassName: "priority-class-name", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewScaledQuantity(3, 1), + }, + Claims: []corev1.ResourceClaim{{ + Name: "claim-name", + Request: "claim-request", + }}, + }, + NodeAffinity: corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{{ + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "node-selector-match-key", + Operator: "node-selector-match-operator", + Values: []string{"node-match-value-1", "node-match-value2"}, + }, + }, + MatchFields: []corev1.NodeSelectorRequirement{ + { + Key: "node-selector-field-key", + Operator: "node-selector-field-operator", + Values: []string{"node-field-value-1", "node-field-value2"}, + }, + }, + }}, + }, + PreferredDuringSchedulingIgnoredDuringExecution: nil, + }, + Tolerations: []corev1.Toleration{ + {Key: "otelc-toleration-key", Operator: "In", Value: "otelc-toleration-value"}, + }, + Args: []string{"--log-level", "debug", "--log-format", "json"}, + Env: []corev1.EnvVar{ + { + Name: "ENV1", + Value: "VAL1", + }, + { + Name: "ENV2", + Value: "VAL2", + }, + { + Name: "ENV2", + Value: "VAL2", + }, + }, + } +} + +func getOldStatus() DynaKubeStatus { + return DynaKubeStatus{ + OneAgent: oneagent.Status{ + VersionStatus: status.VersionStatus{ + ImageID: "oa-image-id", + Version: "oa-version", + Type: "oa-image-type", + Source: status.CustomImageVersionSource, + LastProbeTimestamp: &testTime, + }, + Instances: map[string]oneagent.Instance{ + "oa-instance-key-1": { + PodName: "oa-instance-pod-1", + IPAddress: "oa-instance-ip-1", + }, + "oa-instance-key-2": { + PodName: "oa-instance-pod-2", + IPAddress: "oa-instance-ip-2", + }, + }, + LastInstanceStatusUpdate: &testTime, + Healthcheck: ®istryv1.HealthConfig{ + Test: []string{"oa-health-check-test"}, + }, + ConnectionInfoStatus: oneagent.ConnectionInfoStatus{ + ConnectionInfo: communication.ConnectionInfo{ + LastRequest: testTime, + TenantUUID: "oa-tenant-uuid", + Endpoints: "oa-endpoints", + }, + CommunicationHosts: []oneagent.CommunicationHostStatus{ + { + Protocol: "oa-protocol-1", + Host: "oa-host-1", + Port: 1, + }, + { + Protocol: "oa-protocol-2", + Host: "oa-host-2", + Port: 2, + }, + }, + }, + }, + ActiveGate: activegate.Status{ + VersionStatus: status.VersionStatus{ + ImageID: "ag-image-id", + Version: "ag-version", + Type: "ag-image-type", + Source: status.CustomVersionVersionSource, + LastProbeTimestamp: &testTime, + }, + }, + CodeModules: oneagent.CodeModulesStatus{ + VersionStatus: status.VersionStatus{ + ImageID: "cm-image-id", + Version: "cm-version", + Type: "cm-image-type", + Source: status.TenantRegistryVersionSource, + LastProbeTimestamp: &testTime, + }, + }, + DynatraceApi: DynatraceApiStatus{ + LastTokenScopeRequest: testTime, + }, + Conditions: []metav1.Condition{ + { + Type: "condition-type-1", + Status: "condition-status-1", + Reason: "condition-reason-1", + LastTransitionTime: testTime, + }, + { + Type: "condition-type-2", + Status: "condition-status-2", + Reason: "condition-reason-2", + LastTransitionTime: testTime, + }, + }, + KubeSystemUUID: "kube-system-uuid", + Phase: status.Deploying, + UpdatedTimestamp: testTime, + } +} diff --git a/pkg/api/v1beta3/dynakube/dynakube_status.go b/pkg/api/v1beta3/dynakube/dynakube_status.go index 2cb1259c5f..15dc8a585a 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_status.go +++ b/pkg/api/v1beta3/dynakube/dynakube_status.go @@ -2,8 +2,6 @@ package dynakube import ( "context" - "fmt" - "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" @@ -64,15 +62,6 @@ type DynatraceApiStatus struct { LastTokenScopeRequest metav1.Time `json:"lastTokenScopeRequest,omitempty"` } -func GetCacheValidMessage(functionName string, lastRequestTimestamp metav1.Time, timeout time.Duration) string { - remaining := timeout - time.Since(lastRequestTimestamp.Time) - - return fmt.Sprintf("skipping %s, last request was made less than %d minutes ago, %d minutes remaining until next request", - functionName, - int(timeout.Minutes()), - int(remaining.Minutes())) -} - type EnrichmentRuleType string const ( diff --git a/pkg/api/v1beta3/dynakube/dynakube_types.go b/pkg/api/v1beta3/dynakube/dynakube_types.go index 8907a2d74d..362656a3ba 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_types.go +++ b/pkg/api/v1beta3/dynakube/dynakube_types.go @@ -10,7 +10,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -42,7 +41,6 @@ const ( // DynaKube is the Schema for the DynaKube API // +k8s:openapi-gen=true -// +kubebuilder:storageversion // +kubebuilder:object:root=true // +kubebuilder:subresource:status // +kubebuilder:resource:path=dynakubes,scope=Namespaced,categories=dynatrace,shortName={dk,dks} @@ -93,10 +91,6 @@ type DynaKubeSpec struct { //nolint:revive // +kubebuilder:validation:Optional Extensions *ExtensionsSpec `json:"extensions,omitempty"` - // When a TelemetryIngestSpec is provided, the OTEL collector is deployed by the operator. - // +kubebuilder:validation:Optional - TelemetryIngest *telemetryingest.Spec `json:"telemetryIngest,omitempty"` - // General configuration about OneAgent instances. // You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text" @@ -151,8 +145,6 @@ type DynaKubeSpec struct { //nolint:revive // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Enable Istio automatic management",order=9,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} EnableIstio bool `json:"enableIstio,omitempty"` - - EnableOTLPingest bool `json:"-"` } type TemplatesSpec struct { diff --git a/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go b/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go index 637cad38ec..f9813d44b4 100644 --- a/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go +++ b/pkg/api/v1beta3/dynakube/zz_generated.deepcopy.go @@ -22,7 +22,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -116,11 +115,6 @@ func (in *DynaKubeSpec) DeepCopyInto(out *DynaKubeSpec) { *out = new(ExtensionsSpec) **out = **in } - if in.TelemetryIngest != nil { - in, out := &in.TelemetryIngest, &out.TelemetryIngest - *out = new(telemetryingest.Spec) - (*in).DeepCopyInto(*out) - } in.OneAgent.DeepCopyInto(&out.OneAgent) in.Templates.DeepCopyInto(&out.Templates) in.ActiveGate.DeepCopyInto(&out.ActiveGate) diff --git a/pkg/api/v1beta4/dynakube/activegate/props.go b/pkg/api/v1beta4/dynakube/activegate/props.go new file mode 100644 index 0000000000..e6d70e5f3f --- /dev/null +++ b/pkg/api/v1beta4/dynakube/activegate/props.go @@ -0,0 +1,154 @@ +package activegate + +import ( + "net/url" + "strings" + + "github.com/Dynatrace/dynatrace-operator/pkg/api" + "github.com/Dynatrace/dynatrace-operator/pkg/util/dtversion" +) + +const ( + TenantSecretSuffix = "-activegate-tenant-secret" + TlsSecretSuffix = "-activegate-tls-secret" + ConnectionInfoConfigMapSuffix = "-activegate-connection-info" + AuthTokenSecretSuffix = "-activegate-authtoken-secret" + DefaultImageRegistrySubPath = "/linux/activegate" +) + +func (ag *Spec) SetApiUrl(apiUrl string) { + ag.apiUrl = apiUrl +} + +func (ag *Spec) SetName(name string) { + ag.name = name +} + +func (ag *Spec) SetAutomaticTLSCertificate(enabled bool) { + ag.automaticTLSCertificateEnabled = enabled +} +func (ag *Spec) SetExtensionsDependency(isEnabled bool) { + ag.enabledDependencies.extensions = isEnabled +} + +func (ag *Spec) SetOTLPingestDependency(isEnabled bool) { + ag.enabledDependencies.otlpIngest = isEnabled +} + +func (ag *Spec) apiUrlHost() string { + parsedUrl, err := url.Parse(ag.apiUrl) + if err != nil { + return "" + } + + return parsedUrl.Host +} + +// NeedsActiveGate returns true when a feature requires ActiveGate instances. +func (ag *Spec) IsEnabled() bool { + return len(ag.Capabilities) > 0 || ag.enabledDependencies.Any() +} + +func (ag *Spec) IsMode(mode CapabilityDisplayName) bool { + for _, capability := range ag.Capabilities { + if capability == mode { + return true + } + } + + return false +} + +func (ag *Spec) GetServiceAccountOwner() string { + if ag.IsKubernetesMonitoringEnabled() { + return string(KubeMonCapability.DisplayName) + } else { + return "activegate" + } +} + +func (ag *Spec) GetReplicas() int32 { + var defaultReplicas int32 = 1 + if ag.Replicas == nil { + return defaultReplicas + } + + return *ag.Replicas +} + +func (ag *Spec) GetServiceAccountName() string { + return "dynatrace-" + ag.GetServiceAccountOwner() +} + +func (ag *Spec) IsKubernetesMonitoringEnabled() bool { + return ag.IsMode(KubeMonCapability.DisplayName) +} + +func (ag *Spec) IsRoutingEnabled() bool { + return ag.IsMode(RoutingCapability.DisplayName) +} + +func (ag *Spec) IsApiEnabled() bool { + return ag.IsMode(DynatraceApiCapability.DisplayName) +} + +func (ag *Spec) IsMetricsIngestEnabled() bool { + return ag.IsMode(MetricsIngestCapability.DisplayName) +} + +func (ag *Spec) IsAutomaticTlsSecretEnabled() bool { + return ag.automaticTLSCertificateEnabled +} +func (ag *Spec) HasCaCert() bool { + return ag.IsEnabled() && (ag.TlsSecretName != "" || ag.IsAutomaticTlsSecretEnabled()) +} + +// GetTenantSecretName returns the name of the secret containing tenant UUID, token and communication endpoints for ActiveGate. +func (ag *Spec) GetTenantSecretName() string { + return ag.name + TenantSecretSuffix +} + +// GetAuthTokenSecretName returns the name of the secret containing the ActiveGateAuthToken, which is mounted to the AGs. +func (ag *Spec) GetAuthTokenSecretName() string { + return ag.name + AuthTokenSecretSuffix +} + +// GetTLSSecretName returns the name of the AG TLS secret. +func (ag *Spec) GetTLSSecretName() string { + if ag.TlsSecretName != "" { + return ag.TlsSecretName + } + + if ag.IsAutomaticTlsSecretEnabled() { + return ag.name + TlsSecretSuffix + } + + return "" +} + +func (ag *Spec) GetConnectionInfoConfigMapName() string { + return ag.name + ConnectionInfoConfigMapSuffix +} + +// GetDefaultImage provides the image reference for the ActiveGate from tenant registry. +// Format: repo:tag. +func (ag *Spec) GetDefaultImage(version string) string { + apiUrlHost := ag.apiUrlHost() + if apiUrlHost == "" { + return "" + } + + truncatedVersion := dtversion.ToImageTag(version) + tag := truncatedVersion + + if !strings.Contains(tag, api.RawTag) { + tag += "-" + api.RawTag + } + + return apiUrlHost + DefaultImageRegistrySubPath + ":" + tag +} + +// CustomActiveGateImage provides the image reference for the ActiveGate provided in the Spec. +func (ag *Spec) GetCustomImage() string { + return ag.Image +} diff --git a/pkg/api/v1beta4/dynakube/activegate/spec.go b/pkg/api/v1beta4/dynakube/activegate/spec.go new file mode 100644 index 0000000000..f4323e6624 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/activegate/spec.go @@ -0,0 +1,182 @@ +package activegate + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" + corev1 "k8s.io/api/core/v1" +) + +type CapabilityDisplayName string + +type Capability struct { + + // The name of the capability known by the user, mainly used in the CR + DisplayName CapabilityDisplayName + + // The name used for marking the pod for given capability + ShortName string + + // The string passed to the active gate image to enable a given capability + ArgumentName string +} + +var ( + RoutingCapability = Capability{ + DisplayName: "routing", + ShortName: "routing", + ArgumentName: "MSGrouter", + } + + KubeMonCapability = Capability{ + DisplayName: "kubernetes-monitoring", + ShortName: "kubemon", + ArgumentName: "kubernetes_monitoring", + } + + MetricsIngestCapability = Capability{ + DisplayName: "metrics-ingest", + ShortName: "metrics-ingest", + ArgumentName: "metrics_ingest", + } + + DynatraceApiCapability = Capability{ + DisplayName: "dynatrace-api", + ShortName: "dynatrace-api", + ArgumentName: "restInterface", + } + DebuggingCapability = Capability{ + DisplayName: "debugging", + ShortName: "debugging", + ArgumentName: "debugging", + } +) + +var CapabilityDisplayNames = map[CapabilityDisplayName]struct{}{ + RoutingCapability.DisplayName: {}, + KubeMonCapability.DisplayName: {}, + MetricsIngestCapability.DisplayName: {}, + DynatraceApiCapability.DisplayName: {}, + DebuggingCapability.DisplayName: {}, +} + +type ActiveGate struct { + *Spec + *Status +} + +// dependencies is a collection of possible other feature/components that need an ActiveGate, but is not directly configured in the ActiveGate section. +type dependencies struct { + extensions bool + otlpIngest bool +} + +func (d dependencies) Any() bool { + return d.extensions || d.otlpIngest // kspm is a dependency too, but blocked by validation webhook to not run standalone +} + +// +kubebuilder:object:generate=true + +type Spec struct { + + // Adds additional annotations to the ActiveGate pods + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Annotations",order=27,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Annotations map[string]string `json:"annotations,omitempty"` + + // Defines storage device + // +kubebuilder:validation:Optional + PersistentVolumeClaim *corev1.PersistentVolumeClaimSpec `json:"persistentVolumeClaim,omitempty"` + + name string + apiUrl string + + // The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. + // server.p12: certificate+key pair in pkcs12 format + // password: passphrase to read server.p12 + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="TlsSecretName",order=10,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + TlsSecretName string `json:"tlsSecretName,omitempty"` + + // Sets DNS Policy for the ActiveGate pods + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="DNS Policy",order=24,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + DNSPolicy corev1.DNSPolicy `json:"dnsPolicy,omitempty"` + + // If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that + // name. If not specified the setting will be removed from the StatefulSet. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Priority Class name",order=23,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:io.kubernetes:PriorityClass"} + PriorityClassName string `json:"priorityClassName,omitempty"` + + CapabilityProperties `json:",inline"` + + // Activegate capabilities enabled (routing, kubernetes-monitoring, metrics-ingest, dynatrace-api) + Capabilities []CapabilityDisplayName `json:"capabilities,omitempty"` + + enabledDependencies dependencies + + automaticTLSCertificateEnabled bool + + // UseEphemeralVolume + UseEphemeralVolume bool `json:"useEphemeralVolume,omitempty"` +} + +// +kubebuilder:object:generate=true + +// CapabilityProperties is a struct which can be embedded by ActiveGate capabilities +// Such as KubernetesMonitoring or Routing +// It encapsulates common properties. +type CapabilityProperties struct { + + // Add a custom properties file by providing it as a value or reference it from a secret + // +kubebuilder:validation:Optional + // If referenced from a secret, make sure the key is called 'customProperties' + CustomProperties *value.Source `json:"customProperties,omitempty"` + + // Node selector to control the selection of nodes + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Node Selector",order=35,xDescriptors="urn:alm:descriptor:com.tectonic.ui:selector:Node" + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // Adds additional labels for the ActiveGate pods + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Labels",order=37,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Labels map[string]string `json:"labels,omitempty"` + + // Amount of replicas for your ActiveGates + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Replicas",order=30,xDescriptors="urn:alm:descriptor:com.tectonic.ui:podCount" + Replicas *int32 `json:"replicas,omitempty"` + + // The ActiveGate container image. Defaults to the latest ActiveGate image provided by the registry on the tenant + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Image",order=10,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Image string `json:"image,omitempty"` + + // Set activation group for ActiveGate + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Activation group",order=31,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Group string `json:"group,omitempty"` + + // Define resources requests and limits for single ActiveGate pods + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Resource Requirements",order=34,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:resourceRequirements"} + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + + // Set tolerations for the ActiveGate pods + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Tolerations",order=36,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:hidden"} + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // List of environment variables to set for the ActiveGate + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Environment variables",order=39,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:hidden"} + // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true + // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName="Environment variables" + // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.x-descriptors="urn:alm:descriptor:com.tectonic.ui:advanced,urn:alm:descriptor:com.tectonic.ui:text" + Env []corev1.EnvVar `json:"env,omitempty"` + + // Adds TopologySpreadConstraints for the ActiveGate pods + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="topologySpreadConstraints",order=40,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:hidden"} + TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"` +} diff --git a/pkg/api/v1beta4/dynakube/activegate/status.go b/pkg/api/v1beta4/dynakube/activegate/status.go new file mode 100644 index 0000000000..364f3c45bf --- /dev/null +++ b/pkg/api/v1beta4/dynakube/activegate/status.go @@ -0,0 +1,28 @@ +package activegate + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" +) + +// +kubebuilder:object:generate=true +type Status struct { + status.VersionStatus `json:",inline"` + + // Information about Active Gate's connections + ConnectionInfo communication.ConnectionInfo `json:"connectionInfoStatus,omitempty"` + + // The ClusterIPs set by Kubernetes on the ActiveGate Service created by the Operator + ServiceIPs []string `json:"serviceIPs,omitempty"` +} + +// Image provides the image reference set in Status for the ActiveGate. +// Format: repo@sha256:digest. +func (ag *Status) GetImage() string { + return ag.ImageID +} + +// Version provides version set in Status for the ActiveGate. +func (ag *Status) GetVersion() string { + return ag.Version +} diff --git a/pkg/api/v1beta4/dynakube/activegate/zz_generated.deepcopy.go b/pkg/api/v1beta4/dynakube/activegate/zz_generated.deepcopy.go new file mode 100644 index 0000000000..910cebcf43 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/activegate/zz_generated.deepcopy.go @@ -0,0 +1,141 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package activegate + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" + "k8s.io/api/core/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CapabilityProperties) DeepCopyInto(out *CapabilityProperties) { + *out = *in + if in.CustomProperties != nil { + in, out := &in.CustomProperties, &out.CustomProperties + *out = new(value.Source) + **out = **in + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + in.Resources.DeepCopyInto(&out.Resources) + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.TopologySpreadConstraints != nil { + in, out := &in.TopologySpreadConstraints, &out.TopologySpreadConstraints + *out = make([]v1.TopologySpreadConstraint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CapabilityProperties. +func (in *CapabilityProperties) DeepCopy() *CapabilityProperties { + if in == nil { + return nil + } + out := new(CapabilityProperties) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Spec) DeepCopyInto(out *Spec) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.PersistentVolumeClaim != nil { + in, out := &in.PersistentVolumeClaim, &out.PersistentVolumeClaim + *out = new(v1.PersistentVolumeClaimSpec) + (*in).DeepCopyInto(*out) + } + in.CapabilityProperties.DeepCopyInto(&out.CapabilityProperties) + if in.Capabilities != nil { + in, out := &in.Capabilities, &out.Capabilities + *out = make([]CapabilityDisplayName, len(*in)) + copy(*out, *in) + } + out.enabledDependencies = in.enabledDependencies +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. +func (in *Spec) DeepCopy() *Spec { + if in == nil { + return nil + } + out := new(Spec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in + in.VersionStatus.DeepCopyInto(&out.VersionStatus) + in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo) + if in.ServiceIPs != nil { + in, out := &in.ServiceIPs, &out.ServiceIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/api/v1beta4/dynakube/activegate_props.go b/pkg/api/v1beta4/dynakube/activegate_props.go new file mode 100644 index 0000000000..9f82b1d60b --- /dev/null +++ b/pkg/api/v1beta4/dynakube/activegate_props.go @@ -0,0 +1,18 @@ +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" +) + +func (dk *DynaKube) ActiveGate() *activegate.ActiveGate { + dk.Spec.ActiveGate.SetApiUrl(dk.ApiUrl()) + dk.Spec.ActiveGate.SetName(dk.Name) + dk.Spec.ActiveGate.SetAutomaticTLSCertificate(dk.FeatureActiveGateAutomaticTLSCertificate()) + dk.Spec.ActiveGate.SetExtensionsDependency(dk.IsExtensionsEnabled()) + dk.Spec.ActiveGate.SetOTLPingestDependency(dk.IsOTLPingestEnabled()) + + return &activegate.ActiveGate{ + Spec: &dk.Spec.ActiveGate, + Status: &dk.Status.ActiveGate, + } +} diff --git a/pkg/api/v1beta4/dynakube/certs.go b/pkg/api/v1beta4/dynakube/certs.go new file mode 100644 index 0000000000..f6e5aa1068 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/certs.go @@ -0,0 +1,66 @@ +/* +Copyright 2021 Dynatrace LLC. + +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. +*/ + +package dynakube + +import ( + "context" + "fmt" + + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + TrustedCAKey = "certs" + TLSCertKey = "server.crt" +) + +func (dk *DynaKube) TrustedCAs(ctx context.Context, kubeReader client.Reader) ([]byte, error) { + configName := dk.Spec.TrustedCAs + if configName != "" { + var caConfigMap corev1.ConfigMap + + err := kubeReader.Get(ctx, client.ObjectKey{Name: configName, Namespace: dk.Namespace}, &caConfigMap) + if err != nil { + return nil, errors.WithMessage(err, fmt.Sprintf("failed to get trustedCa from %s configmap", configName)) + } + + return []byte(caConfigMap.Data[TrustedCAKey]), nil + } + + return nil, nil +} + +func (dk *DynaKube) ActiveGateTLSCert(ctx context.Context, kubeReader client.Reader) ([]byte, error) { + if dk.ActiveGate().HasCaCert() { + secretName := dk.Spec.ActiveGate.GetTLSSecretName() + + var tlsSecret corev1.Secret + + err := kubeReader.Get(ctx, client.ObjectKey{Name: secretName, Namespace: dk.Namespace}, &tlsSecret) + if err != nil { + return nil, errors.WithMessage(err, fmt.Sprintf("failed to get activeGate tlsCert from %s secret", secretName)) + } + + if tlsCertKey, ok := tlsSecret.Data[TLSCertKey]; ok { + return tlsCertKey, nil + } + } + + return nil, nil +} diff --git a/pkg/api/v1beta3/dynakube/conversion.go b/pkg/api/v1beta4/dynakube/conversion.go similarity index 100% rename from pkg/api/v1beta3/dynakube/conversion.go rename to pkg/api/v1beta4/dynakube/conversion.go diff --git a/pkg/api/v1beta4/dynakube/dynakube_props.go b/pkg/api/v1beta4/dynakube/dynakube_props.go new file mode 100644 index 0000000000..62597fe173 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/dynakube_props.go @@ -0,0 +1,110 @@ +package dynakube + +import ( + "net/url" + "time" + + "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + // MaxNameLength is the maximum length of a DynaKube's name, we tend to add suffixes to the name to avoid name collisions for resources related to the DynaKube. (example: dkName-activegate-) + // The limit is necessary because kubernetes uses the name of some resources (ActiveGate StatefulSet) for the label value, which has a limit of 63 characters. (see https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set) + MaxNameLength = 40 + + // PullSecretSuffix is the suffix appended to the DynaKube name to n. + PullSecretSuffix = "-pull-secret" +) + +// ApiUrl is a getter for dk.Spec.APIURL. +func (dk *DynaKube) ApiUrl() string { + return dk.Spec.APIURL +} + +func (dk *DynaKube) Conditions() *[]metav1.Condition { return &dk.Status.Conditions } + +// ApiUrlHost returns the host of dk.Spec.APIURL +// E.g. if the APIURL is set to "https://my-tenant.dynatrace.com/api", it returns "my-tenant.dynatrace.com" +// If the URL cannot be parsed, it returns an empty string. +func (dk *DynaKube) ApiUrlHost() string { + parsedUrl, err := url.Parse(dk.ApiUrl()) + if err != nil { + return "" + } + + return parsedUrl.Host +} + +// PullSecretName returns the name of the pull secret to be used for immutable images. +func (dk *DynaKube) PullSecretName() string { + if dk.Spec.CustomPullSecret != "" { + return dk.Spec.CustomPullSecret + } + + return dk.Name + PullSecretSuffix +} + +// PullSecretsNames returns the names of the pull secrets to be used for immutable images. +func (dk *DynaKube) PullSecretNames() []string { + names := []string{ + dk.Name + PullSecretSuffix, + } + if dk.Spec.CustomPullSecret != "" { + names = append(names, dk.Spec.CustomPullSecret) + } + + return names +} + +func (dk *DynaKube) ImagePullSecretReferences() []corev1.LocalObjectReference { + imagePullSecrets := make([]corev1.LocalObjectReference, 0) + for _, pullSecretName := range dk.PullSecretNames() { + imagePullSecrets = append(imagePullSecrets, corev1.LocalObjectReference{ + Name: pullSecretName, + }) + } + + return imagePullSecrets +} + +// Tokens returns the name of the Secret to be used for tokens. +func (dk *DynaKube) Tokens() string { + if tkns := dk.Spec.Tokens; tkns != "" { + return tkns + } + + return dk.Name +} + +func (dk *DynaKube) TenantUUID() (string, error) { + if dk.Status.OneAgent.ConnectionInfoStatus.TenantUUID != "" { + return dk.Status.OneAgent.ConnectionInfoStatus.TenantUUID, nil + } else if dk.Status.ActiveGate.ConnectionInfo.TenantUUID != "" { + return dk.Status.ActiveGate.ConnectionInfo.TenantUUID, nil + } + + return "", errors.New("tenant UUID not available") +} + +func (dk *DynaKube) GetDynatraceApiRequestThreshold() uint16 { + if dk.Spec.DynatraceApiRequestThreshold == nil { + return DefaultMinRequestThresholdMinutes + } + + return *dk.Spec.DynatraceApiRequestThreshold +} + +func (dk *DynaKube) ApiRequestThreshold() time.Duration { + return time.Duration(dk.GetDynatraceApiRequestThreshold()) * time.Minute +} + +func (dk *DynaKube) IsTokenScopeVerificationAllowed(timeProvider *timeprovider.Provider) bool { + return timeProvider.IsOutdated(&dk.Status.DynatraceApi.LastTokenScopeRequest, dk.ApiRequestThreshold()) +} + +func (dk *DynaKube) FeatureBootstrapperInjection() bool { + return dk.FeatureRemoteImageDownload() && !dk.OneAgent().IsCSIAvailable() +} diff --git a/pkg/api/v1beta4/dynakube/dynakube_props_test.go b/pkg/api/v1beta4/dynakube/dynakube_props_test.go new file mode 100644 index 0000000000..bb470f80c9 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/dynakube_props_test.go @@ -0,0 +1,118 @@ +/* +Copyright 2021 Dynatrace LLC. + +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. +*/ + +package dynakube + +import ( + "testing" + "time" + + "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" +) + +func TestTokens(t *testing.T) { + testName := "test-name" + testValue := "test-value" + + t.Run(`GetTokensName returns custom token name`, func(t *testing.T) { + dk := DynaKube{ + ObjectMeta: metav1.ObjectMeta{Name: testName}, + Spec: DynaKubeSpec{Tokens: testValue}, + } + assert.Equal(t, dk.Tokens(), testValue) + }) + t.Run(`GetTokensName uses instance name as default value`, func(t *testing.T) { + dk := DynaKube{ObjectMeta: metav1.ObjectMeta{Name: testName}} + assert.Equal(t, dk.Tokens(), testName) + }) +} + +func TestIsTokenScopeVerificationAllowed(t *testing.T) { + dk := DynaKube{ + Status: DynaKubeStatus{ + DynatraceApi: DynatraceApiStatus{ + LastTokenScopeRequest: metav1.Time{}, + }, + }, + } + + timeProvider := timeprovider.New().Freeze() + tests := map[string]struct { + lastRequestTimeDeltaMinutes int + updateExpected bool + threshold *uint16 + }{ + "Do not update after 10 minutes using default interval": { + lastRequestTimeDeltaMinutes: -10, + updateExpected: false, + threshold: nil, + }, + "Do update after 20 minutes using default interval": { + lastRequestTimeDeltaMinutes: -20, + updateExpected: true, + threshold: nil, + }, + "Do not update after 3 minutes using 5m interval": { + lastRequestTimeDeltaMinutes: -3, + updateExpected: false, + threshold: ptr.To(uint16(5)), + }, + "Do update after 7 minutes using 5m interval": { + lastRequestTimeDeltaMinutes: -7, + updateExpected: true, + threshold: ptr.To(uint16(5)), + }, + "Do not update after 17 minutes using 20m interval": { + lastRequestTimeDeltaMinutes: -17, + updateExpected: false, + threshold: ptr.To(uint16(20)), + }, + "Do update after 22 minutes using 20m interval": { + lastRequestTimeDeltaMinutes: -22, + updateExpected: true, + threshold: ptr.To(uint16(20)), + }, + "Do update immediately using 0m interval": { + lastRequestTimeDeltaMinutes: 0, + updateExpected: true, + threshold: ptr.To(uint16(0)), + }, + "Do update after 1 minute using 0m interval": { + lastRequestTimeDeltaMinutes: -1, + updateExpected: true, + threshold: ptr.To(uint16(0)), + }, + "Do update after 20 minutes using 0m interval": { + lastRequestTimeDeltaMinutes: -20, + updateExpected: true, + threshold: ptr.To(uint16(0)), + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + dk.Spec.DynatraceApiRequestThreshold = test.threshold + + lastRequestTime := timeProvider.Now().Add(time.Duration(test.lastRequestTimeDeltaMinutes) * time.Minute) + dk.Status.DynatraceApi.LastTokenScopeRequest.Time = lastRequestTime + + assert.Equal(t, test.updateExpected, dk.IsTokenScopeVerificationAllowed(timeProvider)) + }) + } +} diff --git a/pkg/api/v1beta4/dynakube/dynakube_status.go b/pkg/api/v1beta4/dynakube/dynakube_status.go new file mode 100644 index 0000000000..f5bbe6d317 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/dynakube_status.go @@ -0,0 +1,123 @@ +package dynakube + +import ( + "context" + "fmt" + "time" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "github.com/pkg/errors" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// DynaKubeStatus defines the observed state of DynaKube +// +k8s:openapi-gen=true +type DynaKubeStatus struct { //nolint:revive + + // Observed state of OneAgent + OneAgent oneagent.Status `json:"oneAgent,omitempty"` + + // Observed state of ActiveGate + ActiveGate activegate.Status `json:"activeGate,omitempty"` + + // Observed state of Code Modules + CodeModules oneagent.CodeModulesStatus `json:"codeModules,omitempty"` + + // Observed state of Metadata-Enrichment + MetadataEnrichment MetadataEnrichmentStatus `json:"metadataEnrichment,omitempty"` + + // Observed state of Kspm + Kspm kspm.Status `json:"kspm,omitempty"` + + // UpdatedTimestamp indicates when the instance was last updated + // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true + // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName="Last Updated" + // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors.x-descriptors="urn:alm:descriptor:text" + UpdatedTimestamp metav1.Time `json:"updatedTimestamp,omitempty"` + + // Observed state of Dynatrace API + DynatraceApi DynatraceApiStatus `json:"dynatraceApi,omitempty"` + + // Defines the current state (Running, Updating, Error, ...) + Phase status.DeploymentPhase `json:"phase,omitempty"` + + // KubeSystemUUID contains the UUID of the current Kubernetes cluster + KubeSystemUUID string `json:"kubeSystemUUID,omitempty"` + + // KubernetesClusterMEID contains the ID of the monitored entity that points to the Kubernetes cluster + KubernetesClusterMEID string `json:"kubernetesClusterMEID,omitempty"` + + // KubernetesClusterName contains the display name (also know as label) of the monitored entity that points to the Kubernetes cluster + KubernetesClusterName string `json:"kubernetesClusterName,omitempty"` + + // Conditions includes status about the current state of the instance + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +type DynatraceApiStatus struct { + // Time of the last token request + LastTokenScopeRequest metav1.Time `json:"lastTokenScopeRequest,omitempty"` +} + +func GetCacheValidMessage(functionName string, lastRequestTimestamp metav1.Time, timeout time.Duration) string { + remaining := timeout - time.Since(lastRequestTimestamp.Time) + + return fmt.Sprintf("skipping %s, last request was made less than %d minutes ago, %d minutes remaining until next request", + functionName, + int(timeout.Minutes()), + int(remaining.Minutes())) +} + +type EnrichmentRuleType string + +const ( + EnrichmentLabelRule EnrichmentRuleType = "LABEL" + EnrichmentAnnotationRule EnrichmentRuleType = "ANNOTATION" +) + +const MetadataPrefix string = "metadata.dynatrace.com/" + +type MetadataEnrichmentStatus struct { + Rules []EnrichmentRule `json:"rules,omitempty"` +} + +type EnrichmentRule struct { + Type EnrichmentRuleType `json:"type,omitempty"` + Source string `json:"source,omitempty"` + Target string `json:"target,omitempty"` + Enabled bool `json:"enabled,omitempty"` +} + +func (rule EnrichmentRule) ToAnnotationKey() string { + if rule.Target == "" { + return "" + } + + return MetadataPrefix + rule.Target +} + +// SetPhase sets the status phase on the DynaKube object. +func (dk *DynaKubeStatus) SetPhase(phase status.DeploymentPhase) bool { + upd := phase != dk.Phase + dk.Phase = phase + + return upd +} + +func (dk *DynaKube) UpdateStatus(ctx context.Context, client client.Client) error { + dk.Status.UpdatedTimestamp = metav1.Now() + err := client.Status().Update(ctx, dk) + + if err != nil && k8serrors.IsConflict(err) { + log.Info("could not update dynakube due to conflict", "name", dk.Name) + + return nil + } + + return errors.WithStack(err) +} diff --git a/pkg/api/v1beta4/dynakube/dynakube_types.go b/pkg/api/v1beta4/dynakube/dynakube_types.go new file mode 100644 index 0000000000..7779b12dc6 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/dynakube_types.go @@ -0,0 +1,182 @@ +// +kubebuilder:object:generate=true +// +groupName=dynatrace.com +// +versionName=v1beta4 +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TODO: Move these conditions related consts to a place where they are used, so we don't bloat this package further. +const ( + // TokenConditionType identifies the token validity condition. + TokenConditionType string = "Tokens" + + // APITokenConditionType identifies the API Token validity condition. + APITokenConditionType string = "APIToken" + + // PaaSTokenConditionType identifies the PaaS Token validity condition. + PaaSTokenConditionType string = "PaaSToken" + + // DataIngestTokenConditionType identifies the DataIngest Token validity condition. + DataIngestTokenConditionType string = "DataIngestToken" +) + +// Possible reasons for ApiToken and PaaSToken conditions. +const ( + // ReasonTokenReady is set when a token has passed verifications. + ReasonTokenReady string = "TokenReady" + + // ReasonTokenError is set when an unknown error has been found when verifying the token. + ReasonTokenError string = "TokenError" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// DynaKube is the Schema for the DynaKube API +// +k8s:openapi-gen=true +// +kubebuilder:storageversion +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:path=dynakubes,scope=Namespaced,categories=dynatrace,shortName={dk,dks} +// +kubebuilder:printcolumn:name="ApiUrl",type=string,JSONPath=`.spec.apiUrl` +// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +operator-sdk:csv:customresourcedefinitions:displayName="Dynatrace DynaKube" +// +operator-sdk:csv:customresourcedefinitions:resources={{StatefulSet,v1,},{DaemonSet,v1,},{Pod,v1,}} +type DynaKube struct { + metav1.TypeMeta `json:",inline"` + + Status DynaKubeStatus `json:"status,omitempty"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec DynaKubeSpec `json:"spec,omitempty"` +} + +// DynaKubeSpec defines the desired state of DynaKube +// +k8s:openapi-gen=true +type DynaKubeSpec struct { //nolint:revive + // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html + + // Configuration for Metadata Enrichment. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Metadata Enrichment",order=9,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"} + MetadataEnrichment MetadataEnrichment `json:"metadataEnrichment,omitempty"` + + // Set custom proxy settings either directly or from a secret with the field proxy. + // Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Proxy",order=3,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + Proxy *value.Source `json:"proxy,omitempty"` + + // General configuration about the LogMonitoring feature. + // +kubebuilder:validation:Optional + LogMonitoring *logmonitoring.Spec `json:"logMonitoring,omitempty"` + + // General configuration about the KSPM feature. + // +kubebuilder:validation:Optional + Kspm *kspm.Spec `json:"kspm,omitempty"` + + // Configuration for thresholding Dynatrace API requests. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Dynatrace API Request Threshold",order=9,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"} + DynatraceApiRequestThreshold *uint16 `json:"dynatraceApiRequestThreshold,omitempty"` + + // When an (empty) ExtensionsSpec is provided, the extensions related components (extensions controller and extensions collector) + // are deployed by the operator. + // +kubebuilder:validation:Optional + Extensions *ExtensionsSpec `json:"extensions,omitempty"` + + // When a TelemetryIngestSpec is provided, the OTEL collector is deployed by the operator. + // +kubebuilder:validation:Optional + TelemetryIngest *telemetryingest.Spec `json:"telemetryIngest,omitempty"` + + // General configuration about OneAgent instances. + // You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text" + OneAgent oneagent.Spec `json:"oneAgent,omitempty"` + + // Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. + // For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace.com/support/help/get-started/monitoring-environment/environment-id). + // +kubebuilder:validation:Required + // +kubebuilder:validation:MaxLength=128 + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="API URL",order=1,xDescriptors="urn:alm:descriptor:com.tectonic.ui:text" + APIURL string `json:"apiUrl"` + + // Name of the secret holding the tokens used for connecting to Dynatrace. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Tenant specific secrets",order=2,xDescriptors="urn:alm:descriptor:io.kubernetes:Secret" + Tokens string `json:"tokens,omitempty"` + + // Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. + // Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Trusted CAs",order=6,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:io.kubernetes:ConfigMap"} + TrustedCAs string `json:"trustedCAs,omitempty"` + + // Sets a network zone for the OneAgent and ActiveGate pods. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Network Zone",order=7,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + NetworkZone string `json:"networkZone,omitempty"` + + // Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. + // To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret + // (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring/dto-config-options-k8s#custompullsecret). + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Custom PullSecret",order=8,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:io.kubernetes:Secret"} + CustomPullSecret string `json:"customPullSecret,omitempty"` + + // +kubebuilder:validation:Optional + Templates TemplatesSpec `json:"templates,omitempty"` + + // General configuration about ActiveGate instances. + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="ActiveGate",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text" + ActiveGate activegate.Spec `json:"activeGate,omitempty"` + + // Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + // Set to true if you want to skip certification validation checks. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Skip Certificate Check",order=3,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + SkipCertCheck bool `json:"skipCertCheck,omitempty"` + + // When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding + // VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. + // Disabled by default. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Enable Istio automatic management",order=9,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + EnableIstio bool `json:"enableIstio,omitempty"` + + EnableOTLPingest bool `json:"-"` +} + +type TemplatesSpec struct { + // Low-level configuration options for the LogMonitoring feature. + // +kubebuilder:validation:Optional + LogMonitoring *logmonitoring.TemplateSpec `json:"logMonitoring,omitempty"` + // +kubebuilder:validation:Optional + KspmNodeConfigurationCollector kspm.NodeConfigurationCollectorSpec `json:"kspmNodeConfigurationCollector,omitempty"` + // +kubebuilder:validation:Optional + OpenTelemetryCollector OpenTelemetryCollectorSpec `json:"openTelemetryCollector,omitempty"` + // +kubebuilder:validation:Optional + ExtensionExecutionController ExtensionExecutionControllerSpec `json:"extensionExecutionController,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// DynaKubeList contains a list of DynaKube +// +kubebuilder:object:root=true +type DynaKubeList struct { //nolint:revive + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []DynaKube `json:"items"` +} + +func init() { + v1beta4.SchemeBuilder.Register(&DynaKube{}, &DynaKubeList{}) +} diff --git a/pkg/api/v1beta4/dynakube/dynakube_webhook.go b/pkg/api/v1beta4/dynakube/dynakube_webhook.go new file mode 100644 index 0000000000..e09373cbc9 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/dynakube_webhook.go @@ -0,0 +1,13 @@ +package dynakube + +import ( + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +func SetupWebhookWithManager(mgr ctrl.Manager, validator admission.CustomValidator) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&DynaKube{}). + WithValidator(validator). // will create an endpoint at /validate-dynatrace-com-v1beta4-dynakube + Complete() +} diff --git a/pkg/api/v1beta4/dynakube/extensions.go b/pkg/api/v1beta4/dynakube/extensions.go new file mode 100644 index 0000000000..572a3db6d4 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/extensions.go @@ -0,0 +1,88 @@ +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" + corev1 "k8s.io/api/core/v1" +) + +// +kubebuilder:validation:Optional +type ExtensionsSpec struct { +} + +type ExtensionExecutionControllerSpec struct { + + // Defines storage device + // +kubebuilder:validation:Optional + PersistentVolumeClaim *corev1.PersistentVolumeClaimSpec `json:"persistentVolumeClaim,omitempty"` + + // Adds additional labels for the ExtensionExecutionController pods + // +kubebuilder:validation:Optional + Labels map[string]string `json:"labels,omitempty"` + + // Adds additional annotations to the ExtensionExecutionController pods + Annotations map[string]string `json:"annotations,omitempty"` + + // Overrides the default image + // +kubebuilder:validation:Optional + ImageRef image.Ref `json:"imageRef,omitempty"` + + // +kubebuilder:validation:Optional + TlsRefName string `json:"tlsRefName,omitempty"` + + // Defines name of ConfigMap containing custom configuration file + // +kubebuilder:validation:Optional + CustomConfig string `json:"customConfig,omitempty"` + + // Defines name of Secret containing certificates for custom extensions signature validation + // +kubebuilder:validation:Optional + CustomExtensionCertificates string `json:"customExtensionCertificates,omitempty"` + + // Define resources' requests and limits for single ExtensionExecutionController pod + // +kubebuilder:validation:Optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + + // Set tolerations for the ExtensionExecutionController pods + // +kubebuilder:validation:Optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // Adds TopologySpreadConstraints for the ExtensionExecutionController pods + // +kubebuilder:validation:Optional + TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"` + // Selects EmptyDir volume to be storage device + // +kubebuilder:validation:Optional + UseEphemeralVolume bool `json:"useEphemeralVolume,omitempty"` +} + +type OpenTelemetryCollectorSpec struct { + + // Adds additional labels for the OtelCollector pods + // +kubebuilder:validation:Optional + Labels map[string]string `json:"labels,omitempty"` + + // Adds additional annotations to the OtelCollector pods + // +kubebuilder:validation:Optional + Annotations map[string]string `json:"annotations,omitempty"` + + // Number of replicas for your OtelCollector + // +kubebuilder:validation:Optional + Replicas *int32 `json:"replicas"` + + // Overrides the default image + // +kubebuilder:validation:Optional + ImageRef image.Ref `json:"imageRef,omitempty"` + + // +kubebuilder:validation:Optional + TlsRefName string `json:"tlsRefName,omitempty"` + + // Define resources' requests and limits for single OtelCollector pod + // +kubebuilder:validation:Optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + + // Set tolerations for the OtelCollector pods + // +kubebuilder:validation:Optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // Adds TopologySpreadConstraints for the OtelCollector pods + // +kubebuilder:validation:Optional + TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"` +} diff --git a/pkg/api/v1beta4/dynakube/extensions_props.go b/pkg/api/v1beta4/dynakube/extensions_props.go new file mode 100644 index 0000000000..acdd7a3911 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/extensions_props.go @@ -0,0 +1,49 @@ +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/consts" +) + +func (dk *DynaKube) IsExtensionsEnabled() bool { + return dk.Spec.Extensions != nil +} + +func (dk *DynaKube) ExtensionsTLSRefName() string { + return dk.Spec.Templates.ExtensionExecutionController.TlsRefName +} + +func (dk *DynaKube) ExtensionsNeedsSelfSignedTLS() bool { + return dk.ExtensionsTLSRefName() == "" +} + +func (dk *DynaKube) ExtensionsTLSSecretName() string { + if dk.ExtensionsNeedsSelfSignedTLS() { + return dk.ExtensionsSelfSignedTLSSecretName() + } + + return dk.ExtensionsTLSRefName() +} + +func (dk *DynaKube) ExtensionsSelfSignedTLSSecretName() string { + return dk.Name + consts.ExtensionsSelfSignedTLSSecretSuffix +} + +func (dk *DynaKube) ExtensionsExecutionControllerStatefulsetName() string { + return dk.Name + "-extensions-controller" +} + +func (dk *DynaKube) ExtensionsTokenSecretName() string { + return dk.Name + "-extensions-token" +} + +func (dk *DynaKube) ExtensionsPortName() string { + return "dynatrace" + consts.ExtensionsControllerSuffix + "-" + consts.ExtensionsCollectorTargetPortName +} + +func (dk *DynaKube) ExtensionsServiceNameFQDN() string { + return dk.ExtensionsServiceName() + "." + dk.Namespace +} + +func (dk *DynaKube) ExtensionsServiceName() string { + return dk.Name + consts.ExtensionsControllerSuffix +} diff --git a/pkg/api/v1beta4/dynakube/feature_flags.go b/pkg/api/v1beta4/dynakube/feature_flags.go new file mode 100644 index 0000000000..674b9fae8d --- /dev/null +++ b/pkg/api/v1beta4/dynakube/feature_flags.go @@ -0,0 +1,304 @@ +/* +Copyright 2021 Dynatrace LLC. + +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. +*/ + +package dynakube + +import ( + "encoding/json" + "fmt" + "math" + "strconv" + "time" + + "github.com/Dynatrace/dynatrace-operator/pkg/logd" +) + +const ( + AnnotationFeaturePrefix = "feature.dynatrace.com/" + AnnotationFeatureCodeModulesPrefix = "codemodules.oneagent.dynatrace.com/" + + // General. + AnnotationFeaturePublicRegistry = AnnotationFeaturePrefix + "public-registry" + + // activeGate. + + // Deprecated: AnnotationFeatureDisableActiveGateUpdates use AnnotationFeatureActiveGateUpdates instead. + AnnotationFeatureDisableActiveGateUpdates = AnnotationFeaturePrefix + "disable-activegate-updates" + // Deprecated: AnnotationFeatureActiveGateIgnoreProxy use AnnotationFeatureNoProxy instead. + AnnotationFeatureActiveGateIgnoreProxy = AnnotationFeaturePrefix + "activegate-ignore-proxy" + + AnnotationFeatureActiveGateUpdates = AnnotationFeaturePrefix + "activegate-updates" + + AnnotationFeatureActiveGateAppArmor = AnnotationFeaturePrefix + "activegate-apparmor" + AnnotationFeatureAutomaticK8sApiMonitoring = AnnotationFeaturePrefix + "automatic-kubernetes-api-monitoring" + AnnotationFeatureAutomaticK8sApiMonitoringClusterName = AnnotationFeaturePrefix + "automatic-kubernetes-api-monitoring-cluster-name" + AnnotationFeatureK8sAppEnabled = AnnotationFeaturePrefix + "k8s-app-enabled" + + AnnotationFeatureActiveGateAutomaticTLSCertificate = AnnotationFeaturePrefix + "automatic-tls-certificate" + + // dtClient. + + AnnotationFeatureNoProxy = AnnotationFeaturePrefix + "no-proxy" + + // oneAgent. + + // Deprecated: AnnotationFeatureOneAgentIgnoreProxy use AnnotationFeatureNoProxy instead. + AnnotationFeatureOneAgentIgnoreProxy = AnnotationFeaturePrefix + "oneagent-ignore-proxy" + + AnnotationFeatureOneAgentMaxUnavailable = AnnotationFeaturePrefix + "oneagent-max-unavailable" + AnnotationFeatureOneAgentInitialConnectRetry = AnnotationFeaturePrefix + "oneagent-initial-connect-retry-ms" + AnnotationFeatureRunOneAgentContainerPrivileged = AnnotationFeaturePrefix + "oneagent-privileged" + AnnotationFeatureOneAgentSkipLivenessProbe = AnnotationFeaturePrefix + "oneagent-skip-liveness-probe" + + AnnotationFeatureIgnoreUnknownState = AnnotationFeaturePrefix + "ignore-unknown-state" + AnnotationFeatureIgnoredNamespaces = AnnotationFeaturePrefix + "ignored-namespaces" + AnnotationFeatureAutomaticInjection = AnnotationFeaturePrefix + "automatic-injection" + AnnotationFeatureLabelVersionDetection = AnnotationFeaturePrefix + "label-version-detection" + AnnotationInjectionFailurePolicy = AnnotationFeaturePrefix + "injection-failure-policy" + AnnotationFeatureInitContainerSeccomp = AnnotationFeaturePrefix + "init-container-seccomp-profile" + AnnotationFeatureEnforcementMode = AnnotationFeaturePrefix + "enforcement-mode" + + // CSI. + AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" + AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" + AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" + AnnotationFeatureRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remote-image-download" + + falsePhrase = "false" + truePhrase = "true" + silentPhrase = "silent" + failPhrase = "fail" +) + +const ( + DefaultMaxCsiMountTimeout = "10m" + DefaultMaxFailedCsiMountAttempts = 10 + DefaultMinRequestThresholdMinutes = 15 + IstioDefaultOneAgentInitialConnectRetry = 6000 +) + +var ( + log = logd.Get().WithName("dynakube-api") +) + +func (dk *DynaKube) getDisableFlagWithDeprecatedAnnotation(annotation string, deprecatedAnnotation string) bool { + return dk.getFeatureFlagRaw(annotation) == falsePhrase || + dk.getFeatureFlagRaw(deprecatedAnnotation) == truePhrase && dk.getFeatureFlagRaw(annotation) == "" +} + +func (dk *DynaKube) getFeatureFlagRaw(annotation string) string { + if raw, ok := dk.Annotations[annotation]; ok { + return raw + } + + return "" +} + +func (dk *DynaKube) getFeatureFlagInt(annotation string, defaultVal int) int { + raw := dk.getFeatureFlagRaw(annotation) + if raw == "" { + return defaultVal + } + + val, err := strconv.Atoi(raw) + if err != nil { + return defaultVal + } + + return val +} + +// FeatureDisableActiveGateUpdates is a feature flag to disable ActiveGate updates. +func (dk *DynaKube) FeatureDisableActiveGateUpdates() bool { + return dk.getDisableFlagWithDeprecatedAnnotation(AnnotationFeatureActiveGateUpdates, AnnotationFeatureDisableActiveGateUpdates) +} + +// FeatureNoProxy is a feature flag to set the NO_PROXY value to be used by the dtClient. +func (dk *DynaKube) FeatureNoProxy() string { + return dk.getFeatureFlagRaw(AnnotationFeatureNoProxy) +} + +// FeatureActiveGateAutomaticTLSCertificate is a feature flag to enable automatic creation of AG TLS certificate if TrustedCAs are used. +func (dk *DynaKube) FeatureActiveGateAutomaticTLSCertificate() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureActiveGateAutomaticTLSCertificate) == truePhrase +} + +// FeatureOneAgentMaxUnavailable is a feature flag to configure maxUnavailable on the OneAgent DaemonSets rolling upgrades. +func (dk *DynaKube) FeatureOneAgentMaxUnavailable() int { + return dk.getFeatureFlagInt(AnnotationFeatureOneAgentMaxUnavailable, 1) +} + +// FeatureIgnoreUnknownState is a feature flag that makes the operator inject into applications even when the dynakube is in an UNKNOWN state, +// this may cause extra host to appear in the tenant for each process. +func (dk *DynaKube) FeatureIgnoreUnknownState() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureIgnoreUnknownState) == truePhrase +} + +// FeatureIgnoredNamespaces is a feature flag for ignoring certain namespaces. +// defaults to "[ \"^dynatrace$\", \"^kube-.*\", \"openshift(-.*)?\" ]". +func (dk *DynaKube) FeatureIgnoredNamespaces() []string { + raw := dk.getFeatureFlagRaw(AnnotationFeatureIgnoredNamespaces) + if raw == "" { + return dk.getDefaultIgnoredNamespaces() + } + + ignoredNamespaces := &[]string{} + + err := json.Unmarshal([]byte(raw), ignoredNamespaces) + if err != nil { + log.Error(err, "failed to unmarshal ignoredNamespaces feature-flag") + + return dk.getDefaultIgnoredNamespaces() + } + + return *ignoredNamespaces +} + +func (dk *DynaKube) getDefaultIgnoredNamespaces() []string { + defaultIgnoredNamespaces := []string{ + fmt.Sprintf("^%s$", dk.Namespace), + "^kube-.*", + "^openshift(-.*)?", + "^gke-.*", + "^gmp-.*", + } + + return defaultIgnoredNamespaces +} + +// FeatureAutomaticKubernetesApiMonitoring is a feature flag to enable automatic kubernetes api monitoring, +// which ensures that settings for this kubernetes cluster exist in Dynatrace. +func (dk *DynaKube) FeatureAutomaticKubernetesApiMonitoring() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureAutomaticK8sApiMonitoring) != falsePhrase +} + +// FeatureAutomaticKubernetesApiMonitoringClusterName is a feature flag to set custom cluster name for automatic-kubernetes-api-monitoring. +func (dk *DynaKube) FeatureAutomaticKubernetesApiMonitoringClusterName() string { + return dk.getFeatureFlagRaw(AnnotationFeatureAutomaticK8sApiMonitoringClusterName) +} + +// FeatureEnableK8sAppEnabled is a feature flag to enable automatically enable current Kubernetes cluster for the Kubernetes app. +func (dk *DynaKube) FeatureEnableK8sAppEnabled() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureK8sAppEnabled) == truePhrase +} + +// FeatureAutomaticInjection controls OneAgent is injected to pods in selected namespaces automatically ("automatic-injection=true" or flag not set) +// or if pods need to be opted-in one by one ("automatic-injection=false"). +func (dk *DynaKube) FeatureAutomaticInjection() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureAutomaticInjection) != falsePhrase +} + +// FeatureActiveGateAppArmor is a feature flag to enable AppArmor in ActiveGate container. +func (dk *DynaKube) FeatureActiveGateAppArmor() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureActiveGateAppArmor) == truePhrase +} + +// FeatureOneAgentIgnoreProxy is a feature flag to ignore the proxy for oneAgents when set in CR. +func (dk *DynaKube) FeatureOneAgentIgnoreProxy() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureOneAgentIgnoreProxy) == truePhrase +} + +// FeatureActiveGateIgnoreProxy is a feature flag to ignore the proxy for ActiveGate when set in CR. +func (dk *DynaKube) FeatureActiveGateIgnoreProxy() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureActiveGateIgnoreProxy) == truePhrase +} + +// FeatureLabelVersionDetection is a feature flag to enable injecting additional environment variables based on user labels. +func (dk *DynaKube) FeatureLabelVersionDetection() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureLabelVersionDetection) == truePhrase +} + +// FeatureAgentInitialConnectRetry is a feature flag to configure startup delay of standalone agents. +func (dk *DynaKube) FeatureAgentInitialConnectRetry() int { + defaultValue := -1 + ffValue := dk.getFeatureFlagInt(AnnotationFeatureOneAgentInitialConnectRetry, defaultValue) + + // In case of istio, we want to have a longer initial delay for codemodules to ensure the DT service is created consistently + if ffValue == defaultValue && dk.Spec.EnableIstio { + ffValue = IstioDefaultOneAgentInitialConnectRetry + } + + return ffValue +} + +func (dk *DynaKube) FeatureOneAgentPrivileged() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureRunOneAgentContainerPrivileged) == truePhrase +} + +func (dk *DynaKube) FeatureOneAgentSkipLivenessProbe() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureOneAgentSkipLivenessProbe) == truePhrase +} + +func (dk *DynaKube) FeatureMaxFailedCsiMountAttempts() int { + maxCsiMountAttemptsValue := dk.getFeatureFlagInt(AnnotationFeatureMaxFailedCsiMountAttempts, DefaultMaxFailedCsiMountAttempts) + if maxCsiMountAttemptsValue < 0 { + return DefaultMaxFailedCsiMountAttempts + } + + return maxCsiMountAttemptsValue +} + +func (dk *DynaKube) FeatureMaxCSIRetryTimeout() time.Duration { + maxCsiMountTimeoutValue := dk.getFeatureFlagRaw(AnnotationFeatureMaxCsiMountTimeout) + + duration, err := time.ParseDuration(maxCsiMountTimeoutValue) + if err != nil || duration < 0 { + duration, _ = time.ParseDuration(DefaultMaxCsiMountTimeout) + } + + return duration +} + +// MountAttemptsToTimeout converts the (old) number of csi mount attempts into a time.Duration string. +// The converted value is based on the exponential backoff's algorithm. +// The output is string because it's main purpose is to convert the value of an annotation to another annotation. +func MountAttemptsToTimeout(maxAttempts int) string { + var baseDelay = time.Second / 2 + + delay := time.Duration(math.Exp2(float64(maxAttempts))) * baseDelay + + return delay.String() +} + +func (dk *DynaKube) FeatureReadOnlyCsiVolume() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureReadOnlyCsiVolume) == truePhrase +} + +func (dk *DynaKube) FeatureRemoteImageDownload() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureRemoteImageDownload) == truePhrase +} + +func (dk *DynaKube) FeatureInjectionFailurePolicy() string { + if dk.getFeatureFlagRaw(AnnotationInjectionFailurePolicy) == failPhrase { + return failPhrase + } + + return silentPhrase +} + +func (dk *DynaKube) FeaturePublicRegistry() bool { + return dk.getFeatureFlagRaw(AnnotationFeaturePublicRegistry) == truePhrase +} + +func (dk *DynaKube) FeatureInitContainerSeccomp() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureInitContainerSeccomp) == truePhrase +} + +// FeatureEnforcementMode is a feature flag to control how the initContainer +// sets the tenantUUID to the container.conf file (always vs if oneAgent is present). +func (dk *DynaKube) FeatureEnforcementMode() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureEnforcementMode) != falsePhrase +} diff --git a/pkg/api/v1beta4/dynakube/feature_flags_test.go b/pkg/api/v1beta4/dynakube/feature_flags_test.go new file mode 100644 index 0000000000..6d2692cfbb --- /dev/null +++ b/pkg/api/v1beta4/dynakube/feature_flags_test.go @@ -0,0 +1,321 @@ +package dynakube + +import ( + "regexp" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func createDynakubeWithAnnotation(keyValues ...string) DynaKube { + dk := DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{}, + }, + } + + for i := 0; i < len(keyValues); i += 2 { + dk.Annotations[keyValues[i]] = keyValues[i+1] + } + + return dk +} + +func createDynakubeEmptyDynakube() DynaKube { + dk := DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{}, + }, + } + + return dk +} + +func TestCreateDynakubeWithAnnotation(t *testing.T) { + dk := createDynakubeWithAnnotation("test", "true") + + assert.Contains(t, dk.Annotations, "test") + assert.Equal(t, "true", dk.Annotations["test"]) + + dk = createDynakubeWithAnnotation("other test", "false") + + assert.Contains(t, dk.Annotations, "other test") + assert.Equal(t, "false", dk.Annotations["other test"]) + assert.NotContains(t, dk.Annotations, "test") + + dk = createDynakubeWithAnnotation("test", "true", "other test", "false") + + assert.Contains(t, dk.Annotations, "other test") + assert.Equal(t, "false", dk.Annotations["other test"]) + assert.Contains(t, dk.Annotations, "test") + assert.Equal(t, "true", dk.Annotations["test"]) +} + +func testDeprecateDisableAnnotation(t *testing.T, + newAnnotation string, + deprecatedAnnotation string, + propertyFunction func(dk DynaKube) bool) { + // New annotation works + dk := createDynakubeWithAnnotation(newAnnotation, "false") + + assert.True(t, propertyFunction(dk)) + + dk = createDynakubeWithAnnotation(newAnnotation, "true") + + assert.False(t, propertyFunction(dk)) + + // Old annotation works + dk = createDynakubeWithAnnotation(deprecatedAnnotation, "true") + + assert.True(t, propertyFunction(dk)) + + dk = createDynakubeWithAnnotation(deprecatedAnnotation, "false") + + assert.False(t, propertyFunction(dk)) + + // New annotation takes precedent + dk = createDynakubeWithAnnotation( + newAnnotation, "true", + deprecatedAnnotation, "true") + + assert.False(t, propertyFunction(dk)) + + dk = createDynakubeWithAnnotation( + newAnnotation, "false", + deprecatedAnnotation, "false") + + assert.True(t, propertyFunction(dk)) + + // Default is false + dk = createDynakubeWithAnnotation() + + assert.False(t, propertyFunction(dk)) +} + +func TestDeprecatedDisableAnnotations(t *testing.T) { + t.Run(AnnotationFeatureActiveGateUpdates, func(t *testing.T) { + testDeprecateDisableAnnotation(t, + AnnotationFeatureActiveGateUpdates, + AnnotationFeatureDisableActiveGateUpdates, + func(dk DynaKube) bool { + return dk.FeatureDisableActiveGateUpdates() + }) + }) +} + +func TestDeprecatedEnableAnnotations(t *testing.T) { + dk := createDynakubeWithAnnotation(AnnotationInjectionFailurePolicy, "fail") + assert.Equal(t, "fail", dk.FeatureInjectionFailurePolicy()) +} + +func TestMaxMountAttempts(t *testing.T) { + dk := createDynakubeWithAnnotation( + AnnotationFeatureMaxFailedCsiMountAttempts, "5") + + assert.Equal(t, 5, dk.FeatureMaxFailedCsiMountAttempts()) + + dk = createDynakubeWithAnnotation( + AnnotationFeatureMaxFailedCsiMountAttempts, "3") + + assert.Equal(t, 3, dk.FeatureMaxFailedCsiMountAttempts()) + + dk = createDynakubeWithAnnotation() + + assert.Equal(t, DefaultMaxFailedCsiMountAttempts, dk.FeatureMaxFailedCsiMountAttempts()) + + dk = createDynakubeWithAnnotation( + AnnotationFeatureMaxFailedCsiMountAttempts, "a") + + assert.Equal(t, DefaultMaxFailedCsiMountAttempts, dk.FeatureMaxFailedCsiMountAttempts()) + + dk = createDynakubeWithAnnotation( + AnnotationFeatureMaxFailedCsiMountAttempts, "-5") + + assert.Equal(t, DefaultMaxFailedCsiMountAttempts, dk.FeatureMaxFailedCsiMountAttempts()) +} + +func TestMaxCSIMountTimeout(t *testing.T) { + type testCase struct { + title string + input string + expected time.Duration + } + + defaultDuration, err := time.ParseDuration(DefaultMaxCsiMountTimeout) + require.NoError(t, err) + + tests := []testCase{ + { + title: "no annotation -> use default", + input: "", + expected: defaultDuration, + }, + { + title: "incorrect annotation (format) -> use default", + input: "5", + expected: defaultDuration, + }, + { + title: "incorrect annotation (negative) -> use default", + input: "-5m", + expected: defaultDuration, + }, + { + title: "correct annotation -> use value", + input: "5m", + expected: time.Minute * 5, + }, + } + + for _, test := range tests { + t.Run(test.title, func(t *testing.T) { + dk := createDynakubeWithAnnotation(AnnotationFeatureMaxCsiMountTimeout, test.input) + + assert.Equal(t, test.expected, dk.FeatureMaxCSIRetryTimeout()) + }) + } +} + +func TestMountAttemptsToTimeout(t *testing.T) { + type testCase struct { + title string + input int + expected time.Duration + delta float64 + } + + defaultDuration, err := time.ParseDuration(DefaultMaxCsiMountTimeout) + require.NoError(t, err) + + tests := []testCase{ + { + title: "default attempts ~ default duration", // 10 attempts ==> ~8 minutes + input: DefaultMaxFailedCsiMountAttempts, + expected: defaultDuration, + delta: float64(time.Minute * 2), + }, + + { + title: "1/2 of default attempts ~ NOT 1/2 of default duration (so it is actually exponential)", // 5 attempts ==> ~15 seconds + input: DefaultMaxFailedCsiMountAttempts / 2, + expected: defaultDuration / DefaultMaxFailedCsiMountAttempts / 4, + delta: float64(time.Second * 5), + }, + } + + for _, test := range tests { + t.Run(test.title, func(t *testing.T) { + duration, err := time.ParseDuration(MountAttemptsToTimeout(test.input)) + require.NoError(t, err) + assert.InDelta(t, test.expected, duration, test.delta) + }) + } +} + +func TestDynaKube_FeatureIgnoredNamespaces(t *testing.T) { + dk := DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + }, + } + ignoredNamespaces := dk.getDefaultIgnoredNamespaces() + dynakubeNamespaceMatches := false + + for _, namespace := range ignoredNamespaces { + regex, err := regexp.Compile(namespace) + + require.NoError(t, err) + + match := regex.MatchString(dk.Namespace) + + if match { + dynakubeNamespaceMatches = true + } + } + + assert.True(t, dynakubeNamespaceMatches) +} + +func TestDefaultEnabledFeatureFlags(t *testing.T) { + dk := createDynakubeEmptyDynakube() + + assert.True(t, dk.FeatureAutomaticKubernetesApiMonitoring()) + assert.True(t, dk.FeatureAutomaticInjection()) + assert.Equal(t, "silent", dk.FeatureInjectionFailurePolicy()) + + assert.False(t, dk.FeatureDisableActiveGateUpdates()) + assert.False(t, dk.FeatureLabelVersionDetection()) +} + +func TestInjectionFailurePolicy(t *testing.T) { + dk := createDynakubeEmptyDynakube() + + modes := map[string]string{ + failPhrase: failPhrase, + silentPhrase: silentPhrase, + } + for configuredMode, expectedMode := range modes { + t.Run(`injection failure policy: `+configuredMode, func(t *testing.T) { + dk.Annotations[AnnotationInjectionFailurePolicy] = configuredMode + + assert.Equal(t, expectedMode, dk.FeatureInjectionFailurePolicy()) + }) + } +} + +func TestAgentInitialConnectRetry(t *testing.T) { + t.Run("default => not set", func(t *testing.T) { + dk := createDynakubeEmptyDynakube() + + initialRetry := dk.FeatureAgentInitialConnectRetry() + require.Equal(t, -1, initialRetry) + }) + t.Run("istio default => set", func(t *testing.T) { + dk := createDynakubeEmptyDynakube() + dk.Spec.EnableIstio = true + + initialRetry := dk.FeatureAgentInitialConnectRetry() + require.Equal(t, IstioDefaultOneAgentInitialConnectRetry, initialRetry) + }) + t.Run("istio default can be overruled", func(t *testing.T) { + dk := createDynakubeEmptyDynakube() + dk.Spec.EnableIstio = true + dk.Annotations[AnnotationFeatureOneAgentInitialConnectRetry] = "5" + + initialRetry := dk.FeatureAgentInitialConnectRetry() + require.Equal(t, 5, initialRetry) + }) +} + +func TestIsOneAgentPrivileged(t *testing.T) { + t.Run("is false by default", func(t *testing.T) { + dk := DynaKube{} + + assert.False(t, dk.FeatureOneAgentPrivileged()) + }) + t.Run("is true when annotation is set to true", func(t *testing.T) { + dk := DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + AnnotationFeatureRunOneAgentContainerPrivileged: "true", + }, + }, + } + + assert.True(t, dk.FeatureOneAgentPrivileged()) + }) + t.Run("is false when annotation is set to false", func(t *testing.T) { + dk := DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + AnnotationFeatureRunOneAgentContainerPrivileged: "false", + }, + }, + } + + assert.False(t, dk.FeatureOneAgentPrivileged()) + }) +} diff --git a/pkg/api/v1beta4/dynakube/kspm/props.go b/pkg/api/v1beta4/dynakube/kspm/props.go new file mode 100644 index 0000000000..0d59f9e68e --- /dev/null +++ b/pkg/api/v1beta4/dynakube/kspm/props.go @@ -0,0 +1,17 @@ +package kspm + +func (kspm *Kspm) SetName(name string) { + kspm.name = name +} + +func (kspm *Kspm) IsEnabled() bool { + return kspm.Spec != nil +} + +func (kspm *Kspm) GetTokenSecretName() string { + return kspm.name + "-" + TokenSecretKey +} + +func (kspm *Kspm) GetDaemonSetName() string { + return kspm.name + "-" + NodeCollectorNameSuffix +} diff --git a/pkg/api/v1beta4/dynakube/kspm/spec.go b/pkg/api/v1beta4/dynakube/kspm/spec.go new file mode 100644 index 0000000000..b8f2fb3848 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/kspm/spec.go @@ -0,0 +1,80 @@ +package kspm + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" +) + +const ( + TokenSecretKey = "kspm-token" + NodeCollectorNameSuffix = "node-config-collector" +) + +type Kspm struct { + *Spec + *Status + *NodeConfigurationCollectorSpec + + name string +} + +// +kubebuilder:object:generate=true + +type Spec struct{} + +// +kubebuilder:object:generate=true +type Status struct { + // TokenSecretHash contains the hash of the token that is passed to both the ActiveGate and Node-Configuration-Collector. + // Meant to keep the two in sync. + TokenSecretHash string `json:"tokenSecretHash,omitempty"` +} + +// +kubebuilder:object:generate=true + +type NodeConfigurationCollectorSpec struct { + + // Define the NodeConfigurationCollector daemonSet updateStrategy + // +kubebuilder:validation:Optional + UpdateStrategy *appsv1.DaemonSetUpdateStrategy `json:"updateStrategy,omitempty"` + // Adds additional labels for the NodeConfigurationCollector pods + // +kubebuilder:validation:Optional + Labels map[string]string `json:"labels,omitempty"` + + // Adds additional annotations for the NodeConfigurationCollector pods + // +kubebuilder:validation:Optional + Annotations map[string]string `json:"annotations,omitempty"` + + // Specify the node selector that controls on which nodes NodeConfigurationCollector pods will be deployed. + // +kubebuilder:validation:Optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // Overrides the default image + // +kubebuilder:validation:Optional + ImageRef image.Ref `json:"imageRef,omitempty"` + + // If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that + // name. If not specified the setting will be removed from the DaemonSet. + // +kubebuilder:validation:Optional + PriorityClassName string `json:"priorityClassName,omitempty"` + + // Define resources' requests and limits for single NodeConfigurationCollector pod + // +kubebuilder:validation:Optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + + // Define the nodeAffinity for the DaemonSet of the NodeConfigurationCollector + // +kubebuilder:validation:Optional + NodeAffinity corev1.NodeAffinity `json:"nodeAffinity,omitempty"` + + // Set tolerations for the NodeConfigurationCollector pods + // +kubebuilder:validation:Optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // Set additional arguments to the NodeConfigurationCollector pods + // +kubebuilder:validation:Optional + Args []string `json:"args,omitempty"` + + // Set additional environment variables for the NodeConfigurationCollector pods + // +kubebuilder:validation:Optional + Env []corev1.EnvVar `json:"env,omitempty"` +} diff --git a/pkg/api/v1beta4/dynakube/kspm/zz_generated.deepcopy.go b/pkg/api/v1beta4/dynakube/kspm/zz_generated.deepcopy.go new file mode 100644 index 0000000000..502ac4f400 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/kspm/zz_generated.deepcopy.go @@ -0,0 +1,117 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package kspm + +import ( + "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeConfigurationCollectorSpec) DeepCopyInto(out *NodeConfigurationCollectorSpec) { + *out = *in + if in.UpdateStrategy != nil { + in, out := &in.UpdateStrategy, &out.UpdateStrategy + *out = new(v1.DaemonSetUpdateStrategy) + (*in).DeepCopyInto(*out) + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + out.ImageRef = in.ImageRef + in.Resources.DeepCopyInto(&out.Resources) + in.NodeAffinity.DeepCopyInto(&out.NodeAffinity) + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]corev1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeConfigurationCollectorSpec. +func (in *NodeConfigurationCollectorSpec) DeepCopy() *NodeConfigurationCollectorSpec { + if in == nil { + return nil + } + out := new(NodeConfigurationCollectorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Spec) DeepCopyInto(out *Spec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. +func (in *Spec) DeepCopy() *Spec { + if in == nil { + return nil + } + out := new(Spec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/api/v1beta4/dynakube/kspm_props.go b/pkg/api/v1beta4/dynakube/kspm_props.go new file mode 100644 index 0000000000..ee0ac86fda --- /dev/null +++ b/pkg/api/v1beta4/dynakube/kspm_props.go @@ -0,0 +1,14 @@ +package dynakube + +import "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" + +func (dk *DynaKube) KSPM() *kspm.Kspm { + _kspm := &kspm.Kspm{ + Spec: dk.Spec.Kspm, + Status: &dk.Status.Kspm, + NodeConfigurationCollectorSpec: &dk.Spec.Templates.KspmNodeConfigurationCollector, + } + _kspm.SetName(dk.GetName()) + + return _kspm +} diff --git a/pkg/api/v1beta4/dynakube/logmonitoring/ingestrulematchers.go b/pkg/api/v1beta4/dynakube/logmonitoring/ingestrulematchers.go new file mode 100644 index 0000000000..f3bb407722 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/logmonitoring/ingestrulematchers.go @@ -0,0 +1,10 @@ +package logmonitoring + +// +kubebuilder:object:generate=true +type IngestRuleMatchers struct { + // +kubebuilder:validation:Optional + Attribute string `json:"attribute,omitempty"` + + // +kubebuilder:validation:Optional + Values []string `json:"values,omitempty"` +} diff --git a/pkg/api/v1beta4/dynakube/logmonitoring/props.go b/pkg/api/v1beta4/dynakube/logmonitoring/props.go new file mode 100644 index 0000000000..3b014065c2 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/logmonitoring/props.go @@ -0,0 +1,42 @@ +package logmonitoring + +const ( + daemonSetSuffix = "-logmonitoring" +) + +func (lm *LogMonitoring) SetName(name string) { + lm.name = name +} + +func (lm *LogMonitoring) SetHostAgentDependency(isEnabled bool) { + lm.enabledDependencies.hostAgents = isEnabled +} + +func (lm *LogMonitoring) IsEnabled() bool { + return lm.Spec != nil +} + +func (lm *LogMonitoring) GetDaemonSetName() string { + return lm.name + daemonSetSuffix +} + +func (lm *LogMonitoring) IsStandalone() bool { + return lm.IsEnabled() && !lm.enabledDependencies.hostAgents +} + +func (lm *LogMonitoring) GetNodeSelector() map[string]string { + if lm.IsStandalone() && lm.TemplateSpec != nil { + return lm.TemplateSpec.NodeSelector + } + + return nil +} + +// Template is a nil-safe way to access the underlying TemplateSpec. +func (lm *LogMonitoring) Template() TemplateSpec { + if lm.TemplateSpec == nil { + return TemplateSpec{} + } + + return *lm.TemplateSpec +} diff --git a/pkg/api/v1beta4/dynakube/logmonitoring/spec.go b/pkg/api/v1beta4/dynakube/logmonitoring/spec.go new file mode 100644 index 0000000000..78294d383a --- /dev/null +++ b/pkg/api/v1beta4/dynakube/logmonitoring/spec.go @@ -0,0 +1,66 @@ +package logmonitoring + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" + corev1 "k8s.io/api/core/v1" +) + +type dependencies struct { + hostAgents bool +} + +type LogMonitoring struct { + *Spec + *TemplateSpec + + name string + enabledDependencies dependencies +} + +// +kubebuilder:object:generate=true +type Spec struct { + IngestRuleMatchers []IngestRuleMatchers `json:"ingestRuleMatchers,omitempty"` +} + +// +kubebuilder:object:generate=true +type TemplateSpec struct { + // Add custom annotations to the LogMonitoring pods + // +kubebuilder:validation:Optional + Annotations map[string]string `json:"annotations,omitempty"` + + // Add custom labels to the LogMonitoring pods + // +kubebuilder:validation:Optional + Labels map[string]string `json:"labels,omitempty"` + + // Node selector to control the selection of nodes for the LogMonitoring pods + // +kubebuilder:validation:Optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // Overrides the default image for the LogMonitoring pods + // +kubebuilder:validation:Optional + ImageRef image.Ref `json:"imageRef,omitempty"` + + // Sets DNS Policy for the LogMonitoring pods + // +kubebuilder:validation:Optional + DNSPolicy corev1.DNSPolicy `json:"dnsPolicy,omitempty"` + + // Assign a priority class to the LogMonitoring pods. By default, no class is set + // +kubebuilder:validation:Optional + PriorityClassName string `json:"priorityClassName,omitempty"` + + // The SecComp Profile that will be configured in order to run in secure computing mode for the LogMonitoring pods + // +kubebuilder:validation:Optional + SecCompProfile string `json:"secCompProfile,omitempty"` + + // Define resources' requests and limits for all the LogMonitoring pods + // +kubebuilder:validation:Optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + + // Set tolerations for the LogMonitoring pods + // +kubebuilder:validation:Optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // Set additional arguments to the LogMonitoring main container + // +kubebuilder:validation:Optional + Args []string `json:"args,omitempty"` +} diff --git a/pkg/api/v1beta4/dynakube/logmonitoring/zz_generated.deepcopy.go b/pkg/api/v1beta4/dynakube/logmonitoring/zz_generated.deepcopy.go new file mode 100644 index 0000000000..2290bd8826 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/logmonitoring/zz_generated.deepcopy.go @@ -0,0 +1,115 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package logmonitoring + +import ( + "k8s.io/api/core/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IngestRuleMatchers) DeepCopyInto(out *IngestRuleMatchers) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngestRuleMatchers. +func (in *IngestRuleMatchers) DeepCopy() *IngestRuleMatchers { + if in == nil { + return nil + } + out := new(IngestRuleMatchers) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Spec) DeepCopyInto(out *Spec) { + *out = *in + if in.IngestRuleMatchers != nil { + in, out := &in.IngestRuleMatchers, &out.IngestRuleMatchers + *out = make([]IngestRuleMatchers, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. +func (in *Spec) DeepCopy() *Spec { + if in == nil { + return nil + } + out := new(Spec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TemplateSpec) DeepCopyInto(out *TemplateSpec) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + out.ImageRef = in.ImageRef + in.Resources.DeepCopyInto(&out.Resources) + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TemplateSpec. +func (in *TemplateSpec) DeepCopy() *TemplateSpec { + if in == nil { + return nil + } + out := new(TemplateSpec) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/api/v1beta4/dynakube/logmonitoring_props.go b/pkg/api/v1beta4/dynakube/logmonitoring_props.go new file mode 100644 index 0000000000..f076f75805 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/logmonitoring_props.go @@ -0,0 +1,16 @@ +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" +) + +func (dk *DynaKube) LogMonitoring() *logmonitoring.LogMonitoring { + lm := &logmonitoring.LogMonitoring{ + Spec: dk.Spec.LogMonitoring, + TemplateSpec: dk.Spec.Templates.LogMonitoring, + } + lm.SetName(dk.Name) + lm.SetHostAgentDependency(dk.OneAgent().IsDaemonsetRequired()) + + return lm +} diff --git a/pkg/api/v1beta4/dynakube/metada_enrichment.go b/pkg/api/v1beta4/dynakube/metada_enrichment.go new file mode 100644 index 0000000000..a14de184c0 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/metada_enrichment.go @@ -0,0 +1,13 @@ +package dynakube + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +type MetadataEnrichment struct { + // Enables MetadataEnrichment, `false` by default. + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="MetaDataEnrichment",xDescriptors="urn:alm:descriptor:com.tectonic.ui:selector:booleanSwitch" + Enabled *bool `json:"enabled,omitempty"` + + // The namespaces where you want Dynatrace Operator to inject enrichment. + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Namespace Selector",xDescriptors="urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Namespace" + NamespaceSelector metav1.LabelSelector `json:"namespaceSelector,omitempty"` +} diff --git a/pkg/api/v1beta4/dynakube/metadata_enrichment_props.go b/pkg/api/v1beta4/dynakube/metadata_enrichment_props.go new file mode 100644 index 0000000000..21ff3015eb --- /dev/null +++ b/pkg/api/v1beta4/dynakube/metadata_enrichment_props.go @@ -0,0 +1,13 @@ +package dynakube + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func (dk *DynaKube) MetadataEnrichmentEnabled() bool { + return dk.Spec.MetadataEnrichment.Enabled != nil && *dk.Spec.MetadataEnrichment.Enabled +} + +func (dk *DynaKube) MetadataEnrichmentNamespaceSelector() *metav1.LabelSelector { + return &dk.Spec.MetadataEnrichment.NamespaceSelector +} diff --git a/pkg/api/v1beta4/dynakube/oneagent/props.go b/pkg/api/v1beta4/dynakube/oneagent/props.go new file mode 100644 index 0000000000..3e65f767cd --- /dev/null +++ b/pkg/api/v1beta4/dynakube/oneagent/props.go @@ -0,0 +1,327 @@ +package oneagent + +import ( + "fmt" + "strings" + + "github.com/Dynatrace/dynatrace-operator/pkg/api" + "github.com/Dynatrace/dynatrace-operator/pkg/util/dtversion" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + OneAgentTenantSecretSuffix = "-oneagent-tenant-secret" + OneAgentConnectionInfoConfigMapSuffix = "-oneagent-connection-info" + PodNameOsAgent = "oneagent" + DefaultOneAgentImageRegistrySubPath = "/linux/oneagent" +) + +func NewOneAgent(spec *Spec, status *Status, codeModulesStatus *CodeModulesStatus, //nolint:revive + name, apiUrlHost string, + featureOneAgentPrivileged, featureOneAgentSkipLivenessProbe bool) *OneAgent { + return &OneAgent{ + Spec: spec, + Status: status, + CodeModulesStatus: codeModulesStatus, + + name: name, + apiUrlHost: apiUrlHost, + + featureOneAgentPrivileged: featureOneAgentPrivileged, + featureOneAgentSkipLivenessProbe: featureOneAgentSkipLivenessProbe, + } +} + +func (oa *OneAgent) IsCSIAvailable() bool { + return installconfig.GetModules().CSIDriver +} + +// IsApplicationMonitoringMode returns true when application only section is used. +func (oa *OneAgent) IsApplicationMonitoringMode() bool { + return oa.ApplicationMonitoring != nil +} + +// IsCloudNativeFullstackMode returns true when cloud native fullstack section is used. +func (oa *OneAgent) IsCloudNativeFullstackMode() bool { + return oa.CloudNativeFullStack != nil +} + +// IsHostMonitoringMode returns true when host monitoring section is used. +func (oa *OneAgent) IsHostMonitoringMode() bool { + return oa.HostMonitoring != nil +} + +// IsClassicFullStackMode returns true when classic fullstack section is used. +func (oa *OneAgent) IsClassicFullStackMode() bool { + return oa.ClassicFullStack != nil +} + +// IsDaemonsetRequired returns true when a feature requires OneAgent instances. +func (oa *OneAgent) IsDaemonsetRequired() bool { + return oa.IsClassicFullStackMode() || oa.IsCloudNativeFullstackMode() || oa.IsHostMonitoringMode() +} + +func (oa *OneAgent) GetDaemonsetName() string { + return fmt.Sprintf("%s-%s", oa.name, PodNameOsAgent) +} + +func (oa *OneAgent) IsPrivilegedNeeded() bool { + return oa.featureOneAgentPrivileged +} + +func (oa *OneAgent) IsReadinessProbeNeeded() bool { + return oa.Healthcheck != nil +} + +func (oa *OneAgent) IsLivenessProbeNeeded() bool { + return oa.Healthcheck != nil && !oa.featureOneAgentSkipLivenessProbe +} + +// IsAutoUpdateEnabled returns true if the Operator should update OneAgent instances automatically. +func (oa *OneAgent) IsAutoUpdateEnabled() bool { + switch { + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.AutoUpdate == nil || *oa.CloudNativeFullStack.AutoUpdate + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.AutoUpdate == nil || *oa.HostMonitoring.AutoUpdate + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.AutoUpdate == nil || *oa.ClassicFullStack.AutoUpdate + default: + return false + } +} + +// GetTenantSecret returns the name of the secret containing the token for the OneAgent. +func (oa *OneAgent) GetTenantSecret() string { + return oa.name + OneAgentTenantSecretSuffix +} + +func (oa *OneAgent) GetConnectionInfoConfigMapName() string { + return oa.name + OneAgentConnectionInfoConfigMapSuffix +} + +func (oa *OneAgent) IsReadOnlyOneAgentsMode() bool { + return oa.IsCloudNativeFullstackMode() || (oa.IsHostMonitoringMode() && oa.IsCSIAvailable()) +} + +func (oa *OneAgent) IsAppInjectionNeeded() bool { + return oa.IsCloudNativeFullstackMode() || oa.IsApplicationMonitoringMode() +} + +func (oa *OneAgent) GetInitResources() *corev1.ResourceRequirements { + if oa.IsApplicationMonitoringMode() { + return oa.ApplicationMonitoring.InitResources + } else if oa.IsCloudNativeFullstackMode() { + return oa.CloudNativeFullStack.InitResources + } + + return nil +} + +func (oa *OneAgent) GetNamespaceSelector() *metav1.LabelSelector { + switch { + case oa.IsCloudNativeFullstackMode(): + return &oa.CloudNativeFullStack.NamespaceSelector + case oa.IsApplicationMonitoringMode(): + return &oa.ApplicationMonitoring.NamespaceSelector + } + + return nil +} + +func (oa *OneAgent) GetSecCompProfile() string { + switch { + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.SecCompProfile + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.SecCompProfile + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.SecCompProfile + default: + return "" + } +} + +func (oa *OneAgent) GetNodeSelector(fallbackNodeSelector map[string]string) map[string]string { + switch { + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.NodeSelector + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.NodeSelector + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.NodeSelector + } + + return fallbackNodeSelector +} + +// GetImage provides the image reference set in Status for the OneAgent. +// Format: repo@sha256:digest. +func (oa *OneAgent) GetImage() string { + return oa.Status.ImageID +} + +// GetVersion provides version set in Status for the OneAgent. +func (oa *OneAgent) GetVersion() string { + return oa.Status.Version +} + +// GetCustomVersion provides the version for the OneAgent provided in the Spec. +func (oa *OneAgent) GetCustomVersion() string { + switch { + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.Version + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.Version + case oa.IsApplicationMonitoringMode(): + return oa.ApplicationMonitoring.Version + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.Version + } + + return "" +} + +// GetCustomImage provides the image reference for the OneAgent provided in the Spec. +func (oa *OneAgent) GetCustomImage() string { + switch { + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.Image + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.Image + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.Image + } + + return "" +} + +// GetDefaultImage provides the image reference for the OneAgent from tenant registry. +func (oa *OneAgent) GetDefaultImage(version string) string { + if oa.apiUrlHost == "" { + return "" + } + + truncatedVersion := dtversion.ToImageTag(version) + tag := truncatedVersion + + if !strings.Contains(tag, api.RawTag) { + tag += "-" + api.RawTag + } + + return oa.apiUrlHost + DefaultOneAgentImageRegistrySubPath + ":" + tag +} + +func (oa *OneAgent) GetHostGroup() string { + if oa.HostGroup != "" { + return oa.HostGroup + } + + return oa.GetHostGroupAsParam() +} + +func (oa *OneAgent) GetArguments() []string { + switch { + case oa.IsCloudNativeFullstackMode() && oa.CloudNativeFullStack.Args != nil: + return oa.CloudNativeFullStack.Args + case oa.IsClassicFullStackMode() && oa.ClassicFullStack.Args != nil: + return oa.ClassicFullStack.Args + case oa.IsHostMonitoringMode() && oa.HostMonitoring.Args != nil: + return oa.HostMonitoring.Args + } + + return []string{} +} + +func (oa *OneAgent) GetHostGroupAsParam() string { + var hostGroup string + + args := oa.GetArguments() + + for _, arg := range args { + key, value := splitArg(arg) + if key == "--set-host-group" { + hostGroup = value + + break + } + } + + return hostGroup +} + +func splitArg(arg string) (string, string) { + key, value, found := strings.Cut(arg, "=") + if !found { + return arg, "" + } + + return key, value +} + +func (oa *OneAgent) IsCommunicationRouteClear() bool { + return len(oa.ConnectionInfoStatus.CommunicationHosts) > 0 +} + +func (oa *OneAgent) GetEnvironment() []corev1.EnvVar { + switch { + case oa.IsCloudNativeFullstackMode(): + return oa.CloudNativeFullStack.Env + case oa.IsClassicFullStackMode(): + return oa.ClassicFullStack.Env + case oa.IsHostMonitoringMode(): + return oa.HostMonitoring.Env + } + + return []corev1.EnvVar{} +} + +func (oa *OneAgent) GetEndpoints() string { + return oa.ConnectionInfoStatus.Endpoints +} + +// GetCustomCodeModulesImage provides the image reference for the CodeModules provided in the Spec. +func (oa *OneAgent) GetCustomCodeModulesImage() string { + if oa.IsCloudNativeFullstackMode() { + return oa.CloudNativeFullStack.CodeModulesImage + } else if oa.IsApplicationMonitoringMode() && oa.IsCSIAvailable() { + return oa.ApplicationMonitoring.CodeModulesImage + } + + return "" +} + +// GetCustomCodeModulesVersion provides the version for the CodeModules provided in the Spec. +func (oa *OneAgent) GetCustomCodeModulesVersion() string { + return oa.GetCustomVersion() +} + +// GetCodeModulesVersion provides version set in Status for the CodeModules. +func (oa *OneAgent) GetCodeModulesVersion() string { + return oa.CodeModulesStatus.Version +} + +// GetCodeModulesImage provides the image reference set in Status for the CodeModules. +// Format: repo@sha256:digest. +func (oa *OneAgent) GetCodeModulesImage() string { + return oa.CodeModulesStatus.ImageID +} + +func (oa *OneAgent) GetArgumentsMap() map[string][]string { + args := oa.GetArguments() + + argMap := make(map[string][]string) + + for _, arg := range args { + key, value := splitArg(arg) + if _, exists := argMap[key]; !exists { + argMap[key] = []string{value} + } else { + argMap[key] = append(argMap[key], value) + } + } + + return argMap +} diff --git a/pkg/api/v1beta4/dynakube/oneagent/props_test.go b/pkg/api/v1beta4/dynakube/oneagent/props_test.go new file mode 100644 index 0000000000..00987176f8 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/oneagent/props_test.go @@ -0,0 +1,386 @@ +/* +Copyright 2021 Dynatrace LLC. + +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. +*/ + +package oneagent + +import ( + "net/url" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" +) + +const testAPIURL = "http://test-endpoint/api" + +func TestNeedsReadonlyOneagent(t *testing.T) { + t.Run("cloud native fullstack always use readonly host agent", func(t *testing.T) { + oneagent := OneAgent{ + Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{}, + }, + } + assert.True(t, oneagent.IsReadOnlyOneAgentsMode()) + }) + + t.Run("host monitoring with readonly host agent", func(t *testing.T) { + oneAgent := OneAgent{ + Spec: &Spec{ + HostMonitoring: &HostInjectSpec{}, + }, + } + assert.True(t, oneAgent.IsReadOnlyOneAgentsMode()) + }) + + t.Run("host monitoring without readonly host agent", func(t *testing.T) { + setupDisabledCSIEnv(t) + + oneAgent := OneAgent{ + Spec: &Spec{ + HostMonitoring: &HostInjectSpec{}, + }, + } + assert.False(t, oneAgent.IsReadOnlyOneAgentsMode()) + }) +} + +func TestDefaultOneAgentImage(t *testing.T) { + t.Run("OneAgentImage with no API URL", func(t *testing.T) { + oneAgent := OneAgent{} + assert.Equal(t, "", oneAgent.GetDefaultImage("")) + }) + + t.Run("OneAgentImage adds raw postfix", func(t *testing.T) { + hostUrl, _ := url.Parse(testAPIURL) + oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false) + assert.Equal(t, "test-endpoint/linux/oneagent:1.234.5-raw", oneAgent.GetDefaultImage("1.234.5")) + }) + + t.Run("OneAgentImage doesn't add 'raw' postfix if present", func(t *testing.T) { + hostUrl, _ := url.Parse(testAPIURL) + oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false) + assert.Equal(t, "test-endpoint/linux/oneagent:1.234.5-raw", oneAgent.GetDefaultImage("1.234.5-raw")) + }) + + t.Run("OneAgentImage with custom version truncates build date", func(t *testing.T) { + version := "1.239.14.20220325-164521" + expectedImage := "test-endpoint/linux/oneagent:1.239.14-raw" + hostUrl, _ := url.Parse(testAPIURL) + oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false) + assert.Equal(t, expectedImage, oneAgent.GetDefaultImage(version)) + }) +} + +func TestCustomOneAgentImage(t *testing.T) { + t.Run("OneAgentImage with custom image", func(t *testing.T) { + customImg := "registry/my/oneagent:latest" + oneAgent := OneAgent{Spec: &Spec{ClassicFullStack: &HostInjectSpec{Image: customImg}}} + assert.Equal(t, customImg, oneAgent.GetCustomImage()) + }) + + t.Run("OneAgentImage with no custom image", func(t *testing.T) { + oneAgent := OneAgent{Spec: &Spec{ClassicFullStack: &HostInjectSpec{}}} + assert.Equal(t, "", oneAgent.GetCustomImage()) + }) +} + +func TestOneAgentDaemonsetName(t *testing.T) { + oneAgent := OneAgent{name: "test-name"} + assert.Equal(t, "test-name-oneagent", oneAgent.GetDaemonsetName()) +} + +func TestCodeModulesVersion(t *testing.T) { + testVersion := "1.2.3" + + t.Run("use status", func(t *testing.T) { + codeModulesStatus := &CodeModulesStatus{VersionStatus: status.VersionStatus{Version: testVersion}} + oneAgent := NewOneAgent(&Spec{}, &Status{}, codeModulesStatus, "", "", false, false) + version := oneAgent.GetCodeModulesVersion() + assert.Equal(t, testVersion, version) + }) + t.Run("use version ", func(t *testing.T) { + codeModulesStatus := &CodeModulesStatus{VersionStatus: status.VersionStatus{Version: "other"}} + oneAgent := NewOneAgent(&Spec{ + ApplicationMonitoring: &ApplicationMonitoringSpec{Version: testVersion}, + }, &Status{}, codeModulesStatus, "", "", false, false) + version := oneAgent.GetCustomCodeModulesVersion() + + assert.Equal(t, testVersion, version) + }) +} + +func TestGetOneAgentEnvironment(t *testing.T) { + t.Run("get environment from classicFullstack", func(t *testing.T) { + oneAgent := OneAgent{ + Spec: &Spec{ + ClassicFullStack: &HostInjectSpec{ + Env: []corev1.EnvVar{ + { + Name: "classicFullstack", + Value: "true", + }, + }, + }, + }, + } + env := oneAgent.GetEnvironment() + + require.Len(t, env, 1) + assert.Equal(t, "classicFullstack", env[0].Name) + }) + + t.Run("get environment from hostMonitoring", func(t *testing.T) { + oneAgent := OneAgent{ + Spec: &Spec{ + HostMonitoring: &HostInjectSpec{ + Env: []corev1.EnvVar{ + { + Name: "hostMonitoring", + Value: "true", + }, + }, + }, + }, + } + env := oneAgent.GetEnvironment() + + require.Len(t, env, 1) + assert.Equal(t, "hostMonitoring", env[0].Name) + }) + + t.Run("get environment from cloudNative", func(t *testing.T) { + oneAgent := OneAgent{ + Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Env: []corev1.EnvVar{ + { + Name: "cloudNative", + Value: "true", + }, + }, + }, + }, + }, + } + env := oneAgent.GetEnvironment() + + require.Len(t, env, 1) + assert.Equal(t, "cloudNative", env[0].Name) + }) + + t.Run("get environment from applicationMonitoring", func(t *testing.T) { + oneAgent := OneAgent{Spec: &Spec{ + ApplicationMonitoring: &ApplicationMonitoringSpec{}, + }} + env := oneAgent.GetEnvironment() + + require.NotNil(t, env) + assert.Empty(t, env) + }) + + t.Run("get environment from unconfigured dynakube", func(t *testing.T) { + oneAgent := OneAgent{Spec: &Spec{}} + env := oneAgent.GetEnvironment() + + require.NotNil(t, env) + assert.Empty(t, env) + }) +} + +func TestOneAgentHostGroup(t *testing.T) { + t.Run("get host group from cloudNativeFullstack.args", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-group=arg", + }, + }, + }, + }, + } + hostGroup := dk.GetHostGroup() + assert.Equal(t, "arg", hostGroup) + }) + + t.Run("get host group from oneagent.hostGroup", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + HostGroup: "field", + }, + } + hostGroup := dk.GetHostGroup() + assert.Equal(t, "field", hostGroup) + }) + + t.Run("get host group if both methods used", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-group=arg", + }, + }, + }, + HostGroup: "field", + }, + } + hostGroup := dk.GetHostGroup() + assert.Equal(t, "field", hostGroup) + }) +} + +func TestOneAgentArgumentsMap(t *testing.T) { + t.Run("straight forward argument list", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-id-source=k8s-node-name", + "--set-host-property=OperatorVersion=$(DT_OPERATOR_VERSION)", + "--set-host-property=dt.security_context=kubernetes_clusters", + "--set-host-property=dynakube-name=$(CUSTOM_CRD_NAME)", + "--set-no-proxy=", + "--set-proxy=", + "--set-tenant=$(DT_TENANT)", + "--set-server=dynatrace.com", + "--set-host-property=prop1=val1", + "--set-host-property=prop2=val2", + "--set-host-property=prop3=val3", + "--set-host-tag=tag1", + "--set-host-tag=tag2", + "--set-host-tag=tag3", + }, + }, + }, + HostGroup: "field", + }, + } + argMap := dk.GetArgumentsMap() + require.Len(t, argMap, 7) + + require.Len(t, argMap["--set-host-id-source"], 1) + assert.Equal(t, "k8s-node-name", argMap["--set-host-id-source"][0]) + + require.Len(t, argMap["--set-host-property"], 6) + assert.Equal(t, "OperatorVersion=$(DT_OPERATOR_VERSION)", argMap["--set-host-property"][0]) + assert.Equal(t, "dt.security_context=kubernetes_clusters", argMap["--set-host-property"][1]) + assert.Equal(t, "dynakube-name=$(CUSTOM_CRD_NAME)", argMap["--set-host-property"][2]) + assert.Equal(t, "prop1=val1", argMap["--set-host-property"][3]) + assert.Equal(t, "prop2=val2", argMap["--set-host-property"][4]) + assert.Equal(t, "prop3=val3", argMap["--set-host-property"][5]) + + require.Len(t, argMap["--set-no-proxy"], 1) + assert.Equal(t, "", argMap["--set-no-proxy"][0]) + + require.Len(t, argMap["--set-proxy"], 1) + assert.Equal(t, "", argMap["--set-proxy"][0]) + + require.Len(t, argMap["--set-tenant"], 1) + assert.Equal(t, "$(DT_TENANT)", argMap["--set-tenant"][0]) + + require.Len(t, argMap["--set-server"], 1) + assert.Equal(t, "dynatrace.com", argMap["--set-server"][0]) + }) + + t.Run("multiple --set-host-property arguments", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-property=prop1=val1", + "--set-host-property=prop2=val2", + "--set-host-property=prop3=val3", + "--set-host-property=prop3=val3", + }, + }, + }, + HostGroup: "field", + }, + } + argMap := dk.GetArgumentsMap() + require.Len(t, argMap, 1) + require.Len(t, argMap["--set-host-property"], 4) + + assert.Equal(t, "prop1=val1", argMap["--set-host-property"][0]) + assert.Equal(t, "prop2=val2", argMap["--set-host-property"][1]) + assert.Equal(t, "prop3=val3", argMap["--set-host-property"][2]) + }) + + t.Run("multiple --set-host-tag arguments", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--set-host-tag=tag1=1", + "--set-host-tag=tag1=2", + "--set-host-tag=tag1=3", + "--set-host-tag=tag2", + "--set-host-tag=tag3", + }, + }, + }, + HostGroup: "field", + }, + } + argMap := dk.GetArgumentsMap() + require.Len(t, argMap, 1) + require.Len(t, argMap["--set-host-tag"], 5) + + assert.Equal(t, "tag1=1", argMap["--set-host-tag"][0]) + assert.Equal(t, "tag1=2", argMap["--set-host-tag"][1]) + assert.Equal(t, "tag1=3", argMap["--set-host-tag"][2]) + assert.Equal(t, "tag2", argMap["--set-host-tag"][3]) + assert.Equal(t, "tag3", argMap["--set-host-tag"][4]) + }) + + t.Run("arguments without value", func(t *testing.T) { + dk := OneAgent{Spec: &Spec{ + CloudNativeFullStack: &CloudNativeFullStackSpec{ + HostInjectSpec: HostInjectSpec{ + Args: []string{ + "--enable-feature-a", + "--enable-feature-b", + "--enable-feature-c", + }, + }, + }, + HostGroup: "field", + }, + } + argMap := dk.GetArgumentsMap() + require.Len(t, argMap, 3) + require.Len(t, argMap["--enable-feature-a"], 1) + require.Len(t, argMap["--enable-feature-b"], 1) + require.Len(t, argMap["--enable-feature-c"], 1) + }) +} + +func setupDisabledCSIEnv(t *testing.T) { + t.Helper() + installconfig.SetModulesOverride(t, installconfig.Modules{ + CSIDriver: false, + ActiveGate: true, + OneAgent: true, + Extensions: true, + LogMonitoring: true, + EdgeConnect: true, + Supportability: true, + }) +} diff --git a/pkg/api/v1beta4/dynakube/oneagent/spec.go b/pkg/api/v1beta4/dynakube/oneagent/spec.go new file mode 100644 index 0000000000..eb2c78fe4c --- /dev/null +++ b/pkg/api/v1beta4/dynakube/oneagent/spec.go @@ -0,0 +1,165 @@ +package oneagent + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type OneAgent struct { + *Spec + *Status + *CodeModulesStatus + + name string + apiUrlHost string + + featureOneAgentPrivileged bool + featureOneAgentSkipLivenessProbe bool +} + +type Mode string + +// +kubebuilder:object:generate=true +type Spec struct { + // Has a single OneAgent per node via DaemonSet. + // Injection is performed via the same OneAgent DaemonSet. + // +nullable + ClassicFullStack *HostInjectSpec `json:"classicFullStack,omitempty"` + + // Has a single OneAgent per node via DaemonSet. + // dynatrace-webhook injects into application pods based on labeled namespaces. + // Has a CSI driver per node via DaemonSet to provide binaries to pods. + // +nullable + CloudNativeFullStack *CloudNativeFullStackSpec `json:"cloudNativeFullStack,omitempty"` + + // dynatrace-webhook injects into application pods based on labeled namespaces. + // Has an optional CSI driver per node via DaemonSet to provide binaries to pods. + // +nullable + ApplicationMonitoring *ApplicationMonitoringSpec `json:"applicationMonitoring,omitempty"` + + // Has a single OneAgent per node via DaemonSet. + // Doesn't inject into application pods. + // +nullable + HostMonitoring *HostInjectSpec `json:"hostMonitoring,omitempty"` + + // Sets a host group for OneAgent. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Host Group",order=5,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + HostGroup string `json:"hostGroup,omitempty"` +} + +// +kubebuilder:object:generate=true +type CloudNativeFullStackSpec struct { + HostInjectSpec `json:",inline"` + AppInjectionSpec `json:",inline"` +} + +// +kubebuilder:object:generate=true +type HostInjectSpec struct { + + // Add custom OneAgent annotations. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Annotations",order=27,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Annotations map[string]string `json:"annotations,omitempty"` + + // Your defined labels for OneAgent pods in order to structure workloads as desired. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Labels",order=26,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Labels map[string]string `json:"labels,omitempty"` + + // Specify the node selector that controls on which nodes OneAgent will be deployed. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Node Selector",order=17,xDescriptors="urn:alm:descriptor:com.tectonic.ui:selector:Node" + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + // Enabled by default. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Automatically update Agent",order=13,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + AutoUpdate *bool `json:"autoUpdate"` + + // Use a specific OneAgent version. Defaults to the latest version from the Dynatrace cluster. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent version",order=11,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Version string `json:"version,omitempty"` + + // Use a custom OneAgent image. Defaults to the latest image from the Dynatrace cluster. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Image",order=12,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Image string `json:"image,omitempty"` + + // Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="DNS Policy",order=24,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + DNSPolicy corev1.DNSPolicy `json:"dnsPolicy,omitempty"` + + // Assign a priority class to the OneAgent pods. By default, no class is set. + // For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Priority Class name",order=23,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:io.kubernetes:PriorityClass"} + PriorityClassName string `json:"priorityClassName,omitempty"` + + // The SecComp Profile that will be configured in order to run in secure computing mode. + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent SecComp Profile",order=17,xDescriptors="urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Namespace" + SecCompProfile string `json:"secCompProfile,omitempty"` + + // Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + // Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Resource Requirements",order=20,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:resourceRequirements"} + OneAgentResources corev1.ResourceRequirements `json:"oneAgentResources,omitempty"` + + // Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Tolerations",order=18,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:hidden"} + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // Set additional environment variables for the OneAgent pods. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent environment variable installer arguments",order=22,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:hidden"} + Env []corev1.EnvVar `json:"env,omitempty"` + + // Set additional arguments to the OneAgent installer. + // For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + // For the list of limitations, see Limitations (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/docker/set-up-dynatrace-oneagent-as-docker-container#limitations). + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent installer arguments",order=21,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:hidden"} + // +listType=set + Args []string `json:"args,omitempty"` +} + +// +kubebuilder:object:generate=true +type ApplicationMonitoringSpec struct { + + // Use a specific OneAgent CodeModule version. Defaults to the latest version from the Dynatrace cluster. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent version",order=11,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Version string `json:"version,omitempty"` + + AppInjectionSpec `json:",inline"` +} + +// +kubebuilder:object:generate=true +type AppInjectionSpec struct { + // Define resources requests and limits for the initContainer. For details, see Managing resources for containers + // (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Resource Requirements",order=15,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:resourceRequirements"} + InitResources *corev1.ResourceRequirements `json:"initResources,omitempty"` + + // Use a custom OneAgent CodeModule image to download binaries. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="CodeModulesImage",order=12,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + CodeModulesImage string `json:"codeModulesImage,omitempty"` + + // Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. + // For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring/dto-config-options-k8s#annotate). + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Namespace Selector",order=17,xDescriptors="urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Namespace" + NamespaceSelector metav1.LabelSelector `json:"namespaceSelector,omitempty"` +} + +// +kubebuilder:object:generate=true +type CodeModulesStatus struct { + status.VersionStatus `json:",inline"` +} diff --git a/pkg/api/v1beta4/dynakube/oneagent/status.go b/pkg/api/v1beta4/dynakube/oneagent/status.go new file mode 100644 index 0000000000..b1a9427bdb --- /dev/null +++ b/pkg/api/v1beta4/dynakube/oneagent/status.go @@ -0,0 +1,58 @@ +package oneagent + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + containerv1 "github.com/google/go-containerregistry/pkg/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +kubebuilder:object:generate=true +type Status struct { + status.VersionStatus `json:",inline"` + + // List of deployed OneAgent instances + Instances map[string]Instance `json:"instances,omitempty"` + + // Time of the last instance status update + LastInstanceStatusUpdate *metav1.Time `json:"lastInstanceStatusUpdate,omitempty"` + + // Commands used for OneAgent's readiness probe + // +kubebuilder:validation:Type=object + // +kubebuilder:validation:Schemaless + // +kubebuilder:pruning:PreserveUnknownFields + Healthcheck *containerv1.HealthConfig `json:"healthcheck,omitempty"` + + // Information about OneAgent's connections + ConnectionInfoStatus ConnectionInfoStatus `json:"connectionInfoStatus,omitempty"` +} + +// +kubebuilder:object:generate=true +type Instance struct { + // Name of the OneAgent pod + PodName string `json:"podName,omitempty"` + + // IP address of the pod + IPAddress string `json:"ipAddress,omitempty"` +} + +// +kubebuilder:object:generate=true +type ConnectionInfoStatus struct { + // Information for communicating with the tenant + communication.ConnectionInfo `json:",inline"` + + // List of communication hosts + CommunicationHosts []CommunicationHostStatus `json:"communicationHosts,omitempty"` +} + +// +kubebuilder:object:generate=true +type CommunicationHostStatus struct { + // Connection protocol + Protocol string `json:"protocol,omitempty"` + + // Host domain + Host string `json:"host,omitempty"` + + // Connection port + Port uint32 `json:"port,omitempty"` +} diff --git a/pkg/api/v1beta4/dynakube/oneagent/zz_generated.deepcopy.go b/pkg/api/v1beta4/dynakube/oneagent/zz_generated.deepcopy.go new file mode 100644 index 0000000000..a2878735cc --- /dev/null +++ b/pkg/api/v1beta4/dynakube/oneagent/zz_generated.deepcopy.go @@ -0,0 +1,274 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package oneagent + +import ( + pkgv1 "github.com/google/go-containerregistry/pkg/v1" + "k8s.io/api/core/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AppInjectionSpec) DeepCopyInto(out *AppInjectionSpec) { + *out = *in + if in.InitResources != nil { + in, out := &in.InitResources, &out.InitResources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + in.NamespaceSelector.DeepCopyInto(&out.NamespaceSelector) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppInjectionSpec. +func (in *AppInjectionSpec) DeepCopy() *AppInjectionSpec { + if in == nil { + return nil + } + out := new(AppInjectionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationMonitoringSpec) DeepCopyInto(out *ApplicationMonitoringSpec) { + *out = *in + in.AppInjectionSpec.DeepCopyInto(&out.AppInjectionSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationMonitoringSpec. +func (in *ApplicationMonitoringSpec) DeepCopy() *ApplicationMonitoringSpec { + if in == nil { + return nil + } + out := new(ApplicationMonitoringSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CloudNativeFullStackSpec) DeepCopyInto(out *CloudNativeFullStackSpec) { + *out = *in + in.HostInjectSpec.DeepCopyInto(&out.HostInjectSpec) + in.AppInjectionSpec.DeepCopyInto(&out.AppInjectionSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudNativeFullStackSpec. +func (in *CloudNativeFullStackSpec) DeepCopy() *CloudNativeFullStackSpec { + if in == nil { + return nil + } + out := new(CloudNativeFullStackSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CodeModulesStatus) DeepCopyInto(out *CodeModulesStatus) { + *out = *in + in.VersionStatus.DeepCopyInto(&out.VersionStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CodeModulesStatus. +func (in *CodeModulesStatus) DeepCopy() *CodeModulesStatus { + if in == nil { + return nil + } + out := new(CodeModulesStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommunicationHostStatus) DeepCopyInto(out *CommunicationHostStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommunicationHostStatus. +func (in *CommunicationHostStatus) DeepCopy() *CommunicationHostStatus { + if in == nil { + return nil + } + out := new(CommunicationHostStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConnectionInfoStatus) DeepCopyInto(out *ConnectionInfoStatus) { + *out = *in + in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo) + if in.CommunicationHosts != nil { + in, out := &in.CommunicationHosts, &out.CommunicationHosts + *out = make([]CommunicationHostStatus, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectionInfoStatus. +func (in *ConnectionInfoStatus) DeepCopy() *ConnectionInfoStatus { + if in == nil { + return nil + } + out := new(ConnectionInfoStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HostInjectSpec) DeepCopyInto(out *HostInjectSpec) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.AutoUpdate != nil { + in, out := &in.AutoUpdate, &out.AutoUpdate + *out = new(bool) + **out = **in + } + in.OneAgentResources.DeepCopyInto(&out.OneAgentResources) + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostInjectSpec. +func (in *HostInjectSpec) DeepCopy() *HostInjectSpec { + if in == nil { + return nil + } + out := new(HostInjectSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Instance) DeepCopyInto(out *Instance) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Instance. +func (in *Instance) DeepCopy() *Instance { + if in == nil { + return nil + } + out := new(Instance) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Spec) DeepCopyInto(out *Spec) { + *out = *in + if in.ClassicFullStack != nil { + in, out := &in.ClassicFullStack, &out.ClassicFullStack + *out = new(HostInjectSpec) + (*in).DeepCopyInto(*out) + } + if in.CloudNativeFullStack != nil { + in, out := &in.CloudNativeFullStack, &out.CloudNativeFullStack + *out = new(CloudNativeFullStackSpec) + (*in).DeepCopyInto(*out) + } + if in.ApplicationMonitoring != nil { + in, out := &in.ApplicationMonitoring, &out.ApplicationMonitoring + *out = new(ApplicationMonitoringSpec) + (*in).DeepCopyInto(*out) + } + if in.HostMonitoring != nil { + in, out := &in.HostMonitoring, &out.HostMonitoring + *out = new(HostInjectSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. +func (in *Spec) DeepCopy() *Spec { + if in == nil { + return nil + } + out := new(Spec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in + in.VersionStatus.DeepCopyInto(&out.VersionStatus) + if in.Instances != nil { + in, out := &in.Instances, &out.Instances + *out = make(map[string]Instance, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.LastInstanceStatusUpdate != nil { + in, out := &in.LastInstanceStatusUpdate, &out.LastInstanceStatusUpdate + *out = (*in).DeepCopy() + } + if in.Healthcheck != nil { + in, out := &in.Healthcheck, &out.Healthcheck + *out = new(pkgv1.HealthConfig) + (*in).DeepCopyInto(*out) + } + in.ConnectionInfoStatus.DeepCopyInto(&out.ConnectionInfoStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/api/v1beta4/dynakube/oneagent_props.go b/pkg/api/v1beta4/dynakube/oneagent_props.go new file mode 100644 index 0000000000..6e5d3b21a5 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/oneagent_props.go @@ -0,0 +1,18 @@ +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" +) + +func (dk *DynaKube) OneAgent() *oneagent.OneAgent { + oa := oneagent.NewOneAgent( + &dk.Spec.OneAgent, + &dk.Status.OneAgent, + &dk.Status.CodeModules, + dk.Name, + dk.ApiUrlHost(), + dk.FeatureOneAgentPrivileged(), + dk.FeatureOneAgentSkipLivenessProbe()) + + return oa +} diff --git a/pkg/api/v1beta3/dynakube/otelc_props.go b/pkg/api/v1beta4/dynakube/otelc_props.go similarity index 99% rename from pkg/api/v1beta3/dynakube/otelc_props.go rename to pkg/api/v1beta4/dynakube/otelc_props.go index f493f3612d..a9ef0c1cc3 100644 --- a/pkg/api/v1beta3/dynakube/otelc_props.go +++ b/pkg/api/v1beta4/dynakube/otelc_props.go @@ -11,7 +11,6 @@ func (dk *DynaKube) IsAGCertificateNeeded() bool { return false } - func (dk *DynaKube) IsCACertificateNeeded() bool { if !dk.isInClusterActiveGate() && dk.Spec.TrustedCAs != "" { return true @@ -19,7 +18,6 @@ func (dk *DynaKube) IsCACertificateNeeded() bool { return false } - func (dk *DynaKube) isInClusterActiveGate() bool { if dk.ActiveGate().IsEnabled() && dk.ActiveGate().IsApiEnabled() { return true diff --git a/pkg/api/v1beta3/dynakube/otelc_props_test.go b/pkg/api/v1beta4/dynakube/otelc_props_test.go similarity index 97% rename from pkg/api/v1beta3/dynakube/otelc_props_test.go rename to pkg/api/v1beta4/dynakube/otelc_props_test.go index 8d76e1052b..3ded4c9f00 100644 --- a/pkg/api/v1beta3/dynakube/otelc_props_test.go +++ b/pkg/api/v1beta4/dynakube/otelc_props_test.go @@ -3,7 +3,7 @@ package dynakube import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/stretchr/testify/assert" ) diff --git a/pkg/api/v1beta3/dynakube/otlp_props.go b/pkg/api/v1beta4/dynakube/otlp_props.go similarity index 100% rename from pkg/api/v1beta3/dynakube/otlp_props.go rename to pkg/api/v1beta4/dynakube/otlp_props.go diff --git a/pkg/api/v1beta4/dynakube/proxy.go b/pkg/api/v1beta4/dynakube/proxy.go new file mode 100644 index 0000000000..bf83996403 --- /dev/null +++ b/pkg/api/v1beta4/dynakube/proxy.go @@ -0,0 +1,81 @@ +/* +Copyright 2021 Dynatrace LLC. + +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. +*/ + +package dynakube + +import ( + "context" + "fmt" + + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + ProxyKey = "proxy" + NoProxyKey = "noProxy" +) + +func (dk *DynaKube) Proxy(ctx context.Context, kubeReader client.Reader) (string, error) { + if dk.Spec.Proxy == nil { + return "", nil + } + + if dk.Spec.Proxy.Value != "" { + return dk.Spec.Proxy.Value, nil + } else if dk.Spec.Proxy.ValueFrom != "" { + return dk.proxyUrlFromUserSecret(ctx, kubeReader) + } + + return "", nil +} + +func (dk *DynaKube) HasProxy() bool { + return dk.Spec.Proxy != nil && (dk.Spec.Proxy.Value != "" || dk.Spec.Proxy.ValueFrom != "") +} + +func (dk *DynaKube) NeedsCustomNoProxy() bool { + return dk.HasProxy() && dk.FeatureNoProxy() != "" +} + +func (dk *DynaKube) NeedsActiveGateProxy() bool { + return !dk.FeatureActiveGateIgnoreProxy() && dk.HasProxy() && dk.ActiveGate().IsEnabled() +} + +func (dk *DynaKube) NeedsOneAgentProxy() bool { + return !dk.FeatureOneAgentIgnoreProxy() && dk.HasProxy() +} + +func (dk *DynaKube) proxyUrlFromUserSecret(ctx context.Context, kubeReader client.Reader) (string, error) { + secretName := dk.Spec.Proxy.ValueFrom + + var proxySecret corev1.Secret + + err := kubeReader.Get(ctx, client.ObjectKey{Name: secretName, Namespace: dk.Namespace}, &proxySecret) + if err != nil { + return "", errors.WithMessage(err, fmt.Sprintf("failed to get proxy from %s secret", secretName)) + } + + proxy, hasKey := proxySecret.Data[ProxyKey] + if !hasKey { + err := errors.Errorf("missing token %s in proxy secret %s", ProxyKey, secretName) + + return "", err + } + + return string(proxy), nil +} diff --git a/pkg/api/v1beta3/dynakube/telemetryingest/props.go b/pkg/api/v1beta4/dynakube/telemetryingest/props.go similarity index 100% rename from pkg/api/v1beta3/dynakube/telemetryingest/props.go rename to pkg/api/v1beta4/dynakube/telemetryingest/props.go diff --git a/pkg/api/v1beta3/dynakube/telemetryingest/spec.go b/pkg/api/v1beta4/dynakube/telemetryingest/spec.go similarity index 100% rename from pkg/api/v1beta3/dynakube/telemetryingest/spec.go rename to pkg/api/v1beta4/dynakube/telemetryingest/spec.go diff --git a/pkg/api/v1beta3/dynakube/telemetryingest/zz_generated.deepcopy.go b/pkg/api/v1beta4/dynakube/telemetryingest/zz_generated.deepcopy.go similarity index 100% rename from pkg/api/v1beta3/dynakube/telemetryingest/zz_generated.deepcopy.go rename to pkg/api/v1beta4/dynakube/telemetryingest/zz_generated.deepcopy.go diff --git a/pkg/api/v1beta3/dynakube/telemetryservice_props.go b/pkg/api/v1beta4/dynakube/telemetryservice_props.go similarity index 78% rename from pkg/api/v1beta3/dynakube/telemetryservice_props.go rename to pkg/api/v1beta4/dynakube/telemetryservice_props.go index 591774afe8..43e596bc5a 100644 --- a/pkg/api/v1beta3/dynakube/telemetryservice_props.go +++ b/pkg/api/v1beta4/dynakube/telemetryservice_props.go @@ -1,7 +1,7 @@ package dynakube import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" ) func (dk *DynaKube) TelemetryIngest() *telemetryingest.TelemetryIngest { diff --git a/pkg/api/v1beta4/dynakube/test/certs_test.go b/pkg/api/v1beta4/dynakube/test/certs_test.go new file mode 100644 index 0000000000..e63788103d --- /dev/null +++ b/pkg/api/v1beta4/dynakube/test/certs_test.go @@ -0,0 +1,107 @@ +package test + +import ( + "context" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + testConfigMapName = "test-config-map" + testConfigMapValue = "test-config-map-value" + + testSecretName = "test-secret" + testSecretValue = "test-secret-value" +) + +func TestCerts(t *testing.T) { + t.Run(`get trusted certificate authorities`, trustedCAsTester) + t.Run(`get no tls certificates`, activeGateTlsNoCertificateTester) + activeGateTLSCertificate(t) +} + +func trustedCAsTester(t *testing.T) { + kubeReader := fake.NewClient(&corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{Name: testConfigMapName}, + Data: map[string]string{ + dynakube.TrustedCAKey: testConfigMapValue, + }, + }) + dk := dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + TrustedCAs: testConfigMapName, + }, + } + trustedCAs, err := dk.TrustedCAs(context.TODO(), kubeReader) + require.NoError(t, err) + assert.Equal(t, []byte(testConfigMapValue), trustedCAs) + + kubeReader = fake.NewClient() + trustedCAs, err = dk.TrustedCAs(context.TODO(), kubeReader) + + require.Error(t, err) + assert.Empty(t, trustedCAs) + + emptyDk := dynakube.DynaKube{} + trustedCAs, err = emptyDk.TrustedCAs(context.TODO(), kubeReader) + require.NoError(t, err) + assert.Empty(t, trustedCAs) +} + +func activeGateTlsNoCertificateTester(t *testing.T) { + dk := dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{activegate.KubeMonCapability.DisplayName}, + TlsSecretName: testSecretName, + }, + }, + } + + kubeReader := fake.NewClient() + tlsCert, err := dk.ActiveGateTLSCert(context.TODO(), kubeReader) + + require.Error(t, err) + assert.Empty(t, tlsCert) + + emptyDk := dynakube.DynaKube{} + tlsCert, err = emptyDk.ActiveGateTLSCert(context.TODO(), kubeReader) + + require.NoError(t, err) + assert.Empty(t, tlsCert) +} + +func activeGateTLSCertificate(t *testing.T) { + testFunc := func(t *testing.T, data map[string][]byte) { + kubeReader := fake.NewClient(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: testSecretName}, + Data: data, + }) + + dk := dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + ActiveGate: activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{activegate.KubeMonCapability.DisplayName}, + TlsSecretName: testSecretName, + }, + }, + } + tlsCert, err := dk.ActiveGateTLSCert(context.TODO(), kubeReader) + + require.NoError(t, err) + assert.Equal(t, testSecretValue, string(tlsCert)) + } + + t.Run("get tls certificates from server.crt", func(t *testing.T) { + testFunc(t, map[string][]byte{ + dynakube.TLSCertKey: []byte(testSecretValue), + }) + }) +} diff --git a/pkg/api/v1beta4/dynakube/test/proxy_test.go b/pkg/api/v1beta4/dynakube/test/proxy_test.go new file mode 100644 index 0000000000..b2bf42ceda --- /dev/null +++ b/pkg/api/v1beta4/dynakube/test/proxy_test.go @@ -0,0 +1,61 @@ +package test + +import ( + "context" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + testProxyName = "test-proxy" + testProxyData = "test-proxy-value" +) + +func TestProxy(t *testing.T) { + t.Run(`get proxy value`, proxyValueTester) + t.Run(`get proxy value from secret`, proxyValueFromTester) +} + +func proxyValueTester(t *testing.T) { + dk := dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + Proxy: &value.Source{Value: testProxyData}, + }, + } + proxy, err := dk.Proxy(context.TODO(), nil) + require.NoError(t, err) + assert.Equal(t, testProxyData, proxy) + + emptyDk := dynakube.DynaKube{} + proxy, err = emptyDk.Proxy(context.TODO(), nil) + require.NoError(t, err) + assert.Equal(t, "", proxy) +} + +func proxyValueFromTester(t *testing.T) { + kubeReader := fake.NewClient(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: testProxyName}, + Data: map[string][]byte{ + dynakube.ProxyKey: []byte(testProxyData), + }}) + dk := dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + Proxy: &value.Source{ValueFrom: testProxyName}, + }, + } + proxy, err := dk.Proxy(context.TODO(), kubeReader) + require.NoError(t, err) + assert.Equal(t, testProxyData, proxy) + + kubeReader = fake.NewClient() + proxy, err = dk.Proxy(context.TODO(), kubeReader) + require.Error(t, err) + assert.Equal(t, "", proxy) +} diff --git a/pkg/api/v1beta4/dynakube/zz_generated.deepcopy.go b/pkg/api/v1beta4/dynakube/zz_generated.deepcopy.go new file mode 100644 index 0000000000..6ab093947e --- /dev/null +++ b/pkg/api/v1beta4/dynakube/zz_generated.deepcopy.go @@ -0,0 +1,376 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package dynakube + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DynaKube) DeepCopyInto(out *DynaKube) { + *out = *in + out.TypeMeta = in.TypeMeta + in.Status.DeepCopyInto(&out.Status) + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DynaKube. +func (in *DynaKube) DeepCopy() *DynaKube { + if in == nil { + return nil + } + out := new(DynaKube) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DynaKube) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DynaKubeList) DeepCopyInto(out *DynaKubeList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DynaKube, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DynaKubeList. +func (in *DynaKubeList) DeepCopy() *DynaKubeList { + if in == nil { + return nil + } + out := new(DynaKubeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DynaKubeList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DynaKubeSpec) DeepCopyInto(out *DynaKubeSpec) { + *out = *in + in.MetadataEnrichment.DeepCopyInto(&out.MetadataEnrichment) + if in.Proxy != nil { + in, out := &in.Proxy, &out.Proxy + *out = new(value.Source) + **out = **in + } + if in.LogMonitoring != nil { + in, out := &in.LogMonitoring, &out.LogMonitoring + *out = new(logmonitoring.Spec) + (*in).DeepCopyInto(*out) + } + if in.Kspm != nil { + in, out := &in.Kspm, &out.Kspm + *out = new(kspm.Spec) + **out = **in + } + if in.DynatraceApiRequestThreshold != nil { + in, out := &in.DynatraceApiRequestThreshold, &out.DynatraceApiRequestThreshold + *out = new(uint16) + **out = **in + } + if in.Extensions != nil { + in, out := &in.Extensions, &out.Extensions + *out = new(ExtensionsSpec) + **out = **in + } + if in.TelemetryIngest != nil { + in, out := &in.TelemetryIngest, &out.TelemetryIngest + *out = new(telemetryingest.Spec) + (*in).DeepCopyInto(*out) + } + in.OneAgent.DeepCopyInto(&out.OneAgent) + in.Templates.DeepCopyInto(&out.Templates) + in.ActiveGate.DeepCopyInto(&out.ActiveGate) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DynaKubeSpec. +func (in *DynaKubeSpec) DeepCopy() *DynaKubeSpec { + if in == nil { + return nil + } + out := new(DynaKubeSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DynaKubeStatus) DeepCopyInto(out *DynaKubeStatus) { + *out = *in + in.OneAgent.DeepCopyInto(&out.OneAgent) + in.ActiveGate.DeepCopyInto(&out.ActiveGate) + in.CodeModules.DeepCopyInto(&out.CodeModules) + in.MetadataEnrichment.DeepCopyInto(&out.MetadataEnrichment) + out.Kspm = in.Kspm + in.UpdatedTimestamp.DeepCopyInto(&out.UpdatedTimestamp) + in.DynatraceApi.DeepCopyInto(&out.DynatraceApi) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DynaKubeStatus. +func (in *DynaKubeStatus) DeepCopy() *DynaKubeStatus { + if in == nil { + return nil + } + out := new(DynaKubeStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DynatraceApiStatus) DeepCopyInto(out *DynatraceApiStatus) { + *out = *in + in.LastTokenScopeRequest.DeepCopyInto(&out.LastTokenScopeRequest) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DynatraceApiStatus. +func (in *DynatraceApiStatus) DeepCopy() *DynatraceApiStatus { + if in == nil { + return nil + } + out := new(DynatraceApiStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnrichmentRule) DeepCopyInto(out *EnrichmentRule) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnrichmentRule. +func (in *EnrichmentRule) DeepCopy() *EnrichmentRule { + if in == nil { + return nil + } + out := new(EnrichmentRule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtensionExecutionControllerSpec) DeepCopyInto(out *ExtensionExecutionControllerSpec) { + *out = *in + if in.PersistentVolumeClaim != nil { + in, out := &in.PersistentVolumeClaim, &out.PersistentVolumeClaim + *out = new(corev1.PersistentVolumeClaimSpec) + (*in).DeepCopyInto(*out) + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + out.ImageRef = in.ImageRef + in.Resources.DeepCopyInto(&out.Resources) + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.TopologySpreadConstraints != nil { + in, out := &in.TopologySpreadConstraints, &out.TopologySpreadConstraints + *out = make([]corev1.TopologySpreadConstraint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionExecutionControllerSpec. +func (in *ExtensionExecutionControllerSpec) DeepCopy() *ExtensionExecutionControllerSpec { + if in == nil { + return nil + } + out := new(ExtensionExecutionControllerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtensionsSpec) DeepCopyInto(out *ExtensionsSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionsSpec. +func (in *ExtensionsSpec) DeepCopy() *ExtensionsSpec { + if in == nil { + return nil + } + out := new(ExtensionsSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetadataEnrichment) DeepCopyInto(out *MetadataEnrichment) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + in.NamespaceSelector.DeepCopyInto(&out.NamespaceSelector) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetadataEnrichment. +func (in *MetadataEnrichment) DeepCopy() *MetadataEnrichment { + if in == nil { + return nil + } + out := new(MetadataEnrichment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetadataEnrichmentStatus) DeepCopyInto(out *MetadataEnrichmentStatus) { + *out = *in + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]EnrichmentRule, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetadataEnrichmentStatus. +func (in *MetadataEnrichmentStatus) DeepCopy() *MetadataEnrichmentStatus { + if in == nil { + return nil + } + out := new(MetadataEnrichmentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenTelemetryCollectorSpec) DeepCopyInto(out *OpenTelemetryCollectorSpec) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + out.ImageRef = in.ImageRef + in.Resources.DeepCopyInto(&out.Resources) + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.TopologySpreadConstraints != nil { + in, out := &in.TopologySpreadConstraints, &out.TopologySpreadConstraints + *out = make([]corev1.TopologySpreadConstraint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryCollectorSpec. +func (in *OpenTelemetryCollectorSpec) DeepCopy() *OpenTelemetryCollectorSpec { + if in == nil { + return nil + } + out := new(OpenTelemetryCollectorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TemplatesSpec) DeepCopyInto(out *TemplatesSpec) { + *out = *in + if in.LogMonitoring != nil { + in, out := &in.LogMonitoring, &out.LogMonitoring + *out = new(logmonitoring.TemplateSpec) + (*in).DeepCopyInto(*out) + } + in.KspmNodeConfigurationCollector.DeepCopyInto(&out.KspmNodeConfigurationCollector) + in.OpenTelemetryCollector.DeepCopyInto(&out.OpenTelemetryCollector) + in.ExtensionExecutionController.DeepCopyInto(&out.ExtensionExecutionController) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TemplatesSpec. +func (in *TemplatesSpec) DeepCopy() *TemplatesSpec { + if in == nil { + return nil + } + out := new(TemplatesSpec) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/api/v1beta4/groupversion_info.go b/pkg/api/v1beta4/groupversion_info.go new file mode 100644 index 0000000000..6afda4d829 --- /dev/null +++ b/pkg/api/v1beta4/groupversion_info.go @@ -0,0 +1,34 @@ +/* +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. +*/ + +// Package v1beta4 contains API Schema definitions for the dynatrace v1beta4 API group +// +kubebuilder:object:generate=true +// +groupName=dynatrace.com +package v1beta4 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "dynatrace.com", Version: "v1beta4"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/pkg/api/validation/dynakube/activegate.go b/pkg/api/validation/dynakube/activegate.go index 5c421403bf..6025a9b4ba 100644 --- a/pkg/api/validation/dynakube/activegate.go +++ b/pkg/api/validation/dynakube/activegate.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" corev1 "k8s.io/api/core/v1" ) diff --git a/pkg/api/validation/dynakube/activegate_test.go b/pkg/api/validation/dynakube/activegate_test.go index e39347700a..caa04adae2 100644 --- a/pkg/api/validation/dynakube/activegate_test.go +++ b/pkg/api/validation/dynakube/activegate_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" ) diff --git a/pkg/api/validation/dynakube/api_url.go b/pkg/api/validation/dynakube/api_url.go index ccb066ccdd..2336f6e681 100644 --- a/pkg/api/validation/dynakube/api_url.go +++ b/pkg/api/validation/dynakube/api_url.go @@ -5,7 +5,7 @@ import ( "net/url" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" ) const ( diff --git a/pkg/api/validation/dynakube/api_url_test.go b/pkg/api/validation/dynakube/api_url_test.go index 9d0edef20c..2d5dc9a4fa 100644 --- a/pkg/api/validation/dynakube/api_url_test.go +++ b/pkg/api/validation/dynakube/api_url_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" ) diff --git a/pkg/api/validation/dynakube/csi_daemonset.go b/pkg/api/validation/dynakube/csi_daemonset.go index 99f24e26bb..0549d526c4 100644 --- a/pkg/api/validation/dynakube/csi_daemonset.go +++ b/pkg/api/validation/dynakube/csi_daemonset.go @@ -3,7 +3,7 @@ package validation import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" ) const ( diff --git a/pkg/api/validation/dynakube/csi_daemonset_test.go b/pkg/api/validation/dynakube/csi_daemonset_test.go index 305ca0c9cd..920d16f979 100644 --- a/pkg/api/validation/dynakube/csi_daemonset_test.go +++ b/pkg/api/validation/dynakube/csi_daemonset_test.go @@ -3,8 +3,8 @@ package validation import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" ) func TestDisabledCSIForReadonlyCSIVolume(t *testing.T) { diff --git a/pkg/api/validation/dynakube/dynakube_name.go b/pkg/api/validation/dynakube/dynakube_name.go index f87deea951..9f4d8d9963 100644 --- a/pkg/api/validation/dynakube/dynakube_name.go +++ b/pkg/api/validation/dynakube/dynakube_name.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "k8s.io/apimachinery/pkg/util/validation" ) diff --git a/pkg/api/validation/dynakube/dynakube_name_test.go b/pkg/api/validation/dynakube/dynakube_name_test.go index ee55d7410e..07cfe2a032 100644 --- a/pkg/api/validation/dynakube/dynakube_name_test.go +++ b/pkg/api/validation/dynakube/dynakube_name_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/api/validation/dynakube/eec.go b/pkg/api/validation/dynakube/eec.go index 4308060375..a38c558e7e 100644 --- a/pkg/api/validation/dynakube/eec.go +++ b/pkg/api/validation/dynakube/eec.go @@ -3,7 +3,7 @@ package validation import ( "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "golang.org/x/net/context" "sigs.k8s.io/controller-runtime/pkg/client" ) diff --git a/pkg/api/validation/dynakube/eec_test.go b/pkg/api/validation/dynakube/eec_test.go index 22c3dc375a..cc5d7a95c2 100644 --- a/pkg/api/validation/dynakube/eec_test.go +++ b/pkg/api/validation/dynakube/eec_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" diff --git a/pkg/api/validation/dynakube/extensions.go b/pkg/api/validation/dynakube/extensions.go index 54bd30e255..5853ead1e5 100644 --- a/pkg/api/validation/dynakube/extensions.go +++ b/pkg/api/validation/dynakube/extensions.go @@ -3,7 +3,7 @@ package validation import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" ) const ( diff --git a/pkg/api/validation/dynakube/extensions_test.go b/pkg/api/validation/dynakube/extensions_test.go index 03c5760477..9d047bce50 100644 --- a/pkg/api/validation/dynakube/extensions_test.go +++ b/pkg/api/validation/dynakube/extensions_test.go @@ -4,8 +4,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/api/validation/dynakube/featureflag.go b/pkg/api/validation/dynakube/featureflag.go index b40a5056bd..f36c56b2fc 100644 --- a/pkg/api/validation/dynakube/featureflag.go +++ b/pkg/api/validation/dynakube/featureflag.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" ) const ( diff --git a/pkg/api/validation/dynakube/featureflag_test.go b/pkg/api/validation/dynakube/featureflag_test.go index 6f88798179..f283775adc 100644 --- a/pkg/api/validation/dynakube/featureflag_test.go +++ b/pkg/api/validation/dynakube/featureflag_test.go @@ -5,7 +5,7 @@ import ( "fmt" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/api/validation/dynakube/image.go b/pkg/api/validation/dynakube/image.go index eaee6ba5e3..90840b8d1f 100644 --- a/pkg/api/validation/dynakube/image.go +++ b/pkg/api/validation/dynakube/image.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/google/go-containerregistry/pkg/name" ) diff --git a/pkg/api/validation/dynakube/image_test.go b/pkg/api/validation/dynakube/image_test.go index badcec42ef..2f2ed1dd80 100644 --- a/pkg/api/validation/dynakube/image_test.go +++ b/pkg/api/validation/dynakube/image_test.go @@ -5,9 +5,9 @@ import ( "strings" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/api/validation/dynakube/istio.go b/pkg/api/validation/dynakube/istio.go index 67b50237d5..050c0a7a2c 100644 --- a/pkg/api/validation/dynakube/istio.go +++ b/pkg/api/validation/dynakube/istio.go @@ -3,7 +3,7 @@ package validation import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/istio" ) diff --git a/pkg/api/validation/dynakube/istio_test.go b/pkg/api/validation/dynakube/istio_test.go index 26ad6c1593..43253dd274 100644 --- a/pkg/api/validation/dynakube/istio_test.go +++ b/pkg/api/validation/dynakube/istio_test.go @@ -3,7 +3,7 @@ package validation import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" ) func TestNoResourcesAvailable(t *testing.T) { diff --git a/pkg/api/validation/dynakube/kspm.go b/pkg/api/validation/dynakube/kspm.go index 2a005f339a..cca7d5d782 100644 --- a/pkg/api/validation/dynakube/kspm.go +++ b/pkg/api/validation/dynakube/kspm.go @@ -3,7 +3,7 @@ package validation import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" ) const ( diff --git a/pkg/api/validation/dynakube/kspm_test.go b/pkg/api/validation/dynakube/kspm_test.go index 39810516fe..52c51e4ab1 100644 --- a/pkg/api/validation/dynakube/kspm_test.go +++ b/pkg/api/validation/dynakube/kspm_test.go @@ -4,9 +4,9 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/api/validation/dynakube/logmonitoring.go b/pkg/api/validation/dynakube/logmonitoring.go index 1607668633..c3912af4b5 100644 --- a/pkg/api/validation/dynakube/logmonitoring.go +++ b/pkg/api/validation/dynakube/logmonitoring.go @@ -3,7 +3,7 @@ package validation import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" ) const ( diff --git a/pkg/api/validation/dynakube/logmonitoring_test.go b/pkg/api/validation/dynakube/logmonitoring_test.go index 0abd6b1341..82ce2c6654 100644 --- a/pkg/api/validation/dynakube/logmonitoring_test.go +++ b/pkg/api/validation/dynakube/logmonitoring_test.go @@ -4,10 +4,10 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/api/validation/dynakube/module_test.go b/pkg/api/validation/dynakube/module_test.go index 943defa509..82cd7f1bbc 100644 --- a/pkg/api/validation/dynakube/module_test.go +++ b/pkg/api/validation/dynakube/module_test.go @@ -4,11 +4,11 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/stretchr/testify/assert" ) diff --git a/pkg/api/validation/dynakube/modules.go b/pkg/api/validation/dynakube/modules.go index 1c3636f9ac..66c070876b 100644 --- a/pkg/api/validation/dynakube/modules.go +++ b/pkg/api/validation/dynakube/modules.go @@ -3,7 +3,7 @@ package validation import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" ) diff --git a/pkg/api/validation/dynakube/namespace_selector.go b/pkg/api/validation/dynakube/namespace_selector.go index 0d656712b7..1be8ac2476 100644 --- a/pkg/api/validation/dynakube/namespace_selector.go +++ b/pkg/api/validation/dynakube/namespace_selector.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/util/validation/field" diff --git a/pkg/api/validation/dynakube/namespace_selector_test.go b/pkg/api/validation/dynakube/namespace_selector_test.go index 112e5a27c6..1a858b69f1 100644 --- a/pkg/api/validation/dynakube/namespace_selector_test.go +++ b/pkg/api/validation/dynakube/namespace_selector_test.go @@ -3,8 +3,8 @@ package validation import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index b252d68312..0302918a5d 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -7,7 +7,7 @@ import ( "slices" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/dtversion" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "k8s.io/apimachinery/pkg/labels" diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index 33f01ecb61..8415cdb894 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/api/validation/dynakube/preview_test.go b/pkg/api/validation/dynakube/preview_test.go index 30c65e50da..89165a5551 100644 --- a/pkg/api/validation/dynakube/preview_test.go +++ b/pkg/api/validation/dynakube/preview_test.go @@ -3,8 +3,8 @@ package validation import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" ) func TestPreviewWarning(t *testing.T) { diff --git a/pkg/api/validation/dynakube/proxy_url.go b/pkg/api/validation/dynakube/proxy_url.go index db5ec10e9c..81d0f29967 100644 --- a/pkg/api/validation/dynakube/proxy_url.go +++ b/pkg/api/validation/dynakube/proxy_url.go @@ -5,7 +5,7 @@ import ( "net/url" "regexp" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/pkg/errors" ) diff --git a/pkg/api/validation/dynakube/proxy_url_test.go b/pkg/api/validation/dynakube/proxy_url_test.go index 7062fe4ffc..7fbc0b9006 100644 --- a/pkg/api/validation/dynakube/proxy_url_test.go +++ b/pkg/api/validation/dynakube/proxy_url_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/api/validation/dynakube/telemetryservice.go b/pkg/api/validation/dynakube/telemetryservice.go index 627a73b595..bec02607f8 100644 --- a/pkg/api/validation/dynakube/telemetryservice.go +++ b/pkg/api/validation/dynakube/telemetryservice.go @@ -6,7 +6,7 @@ import ( "slices" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" "k8s.io/apimachinery/pkg/util/validation" ) diff --git a/pkg/api/validation/dynakube/telemetryservice_test.go b/pkg/api/validation/dynakube/telemetryservice_test.go index 262c230eff..383d7530af 100644 --- a/pkg/api/validation/dynakube/telemetryservice_test.go +++ b/pkg/api/validation/dynakube/telemetryservice_test.go @@ -3,8 +3,8 @@ package validation import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" ) diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 9f7bfab7ef..f972497391 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -6,7 +6,8 @@ import ( v1beta1 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta1/dynakube" //nolint:staticcheck v1beta2 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta2/dynakube" //nolint:staticcheck - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + v1beta3 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" //nolint:staticcheck + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/validation" "k8s.io/apimachinery/pkg/runtime" @@ -161,6 +162,11 @@ func getDynakube(obj runtime.Object) (dk *dynakube.DynaKube, err error) { switch v := obj.(type) { case *dynakube.DynaKube: dk = v + case *v1beta3.DynaKube: + err = v.ConvertTo(dk) + if err != nil { + return + } case *v1beta2.DynaKube: err = v.ConvertTo(dk) if err != nil { diff --git a/pkg/api/validation/dynakube/validation_test.go b/pkg/api/validation/dynakube/validation_test.go index caead5ec50..6b7688ef15 100644 --- a/pkg/api/validation/dynakube/validation_test.go +++ b/pkg/api/validation/dynakube/validation_test.go @@ -6,9 +6,9 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/clients/dynatrace/client.go b/pkg/clients/dynatrace/client.go index d51f0c7873..d02ec8f4e3 100644 --- a/pkg/clients/dynatrace/client.go +++ b/pkg/clients/dynatrace/client.go @@ -10,7 +10,7 @@ import ( "strings" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" "github.com/pkg/errors" "golang.org/x/net/http/httpproxy" ) diff --git a/pkg/clients/dynatrace/processmoduleconfig.go b/pkg/clients/dynatrace/processmoduleconfig.go index 060c900a1c..c9d716dd42 100644 --- a/pkg/clients/dynatrace/processmoduleconfig.go +++ b/pkg/clients/dynatrace/processmoduleconfig.go @@ -6,7 +6,7 @@ import ( "net/http" "strconv" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/clients/utils" "github.com/pkg/errors" ) diff --git a/pkg/clients/dynatrace/settings_enrichment.go b/pkg/clients/dynatrace/settings_enrichment.go index d89f914d6a..6ca0800ca4 100644 --- a/pkg/clients/dynatrace/settings_enrichment.go +++ b/pkg/clients/dynatrace/settings_enrichment.go @@ -5,7 +5,7 @@ import ( "net/http" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/clients/utils" "github.com/pkg/errors" ) diff --git a/pkg/clients/dynatrace/settings_enrichment_test.go b/pkg/clients/dynatrace/settings_enrichment_test.go index b6acd72d9a..95786697e9 100644 --- a/pkg/clients/dynatrace/settings_enrichment_test.go +++ b/pkg/clients/dynatrace/settings_enrichment_test.go @@ -7,7 +7,7 @@ import ( "net/http/httptest" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/pkg/clients/dynatrace/settings_logmonitoring.go b/pkg/clients/dynatrace/settings_logmonitoring.go index ebd32f9efa..38a6cbce7b 100644 --- a/pkg/clients/dynatrace/settings_logmonitoring.go +++ b/pkg/clients/dynatrace/settings_logmonitoring.go @@ -7,7 +7,7 @@ import ( "io" "net/http" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/clients/utils" "github.com/pkg/errors" ) diff --git a/pkg/clients/dynatrace/settings_logmonitoring_test.go b/pkg/clients/dynatrace/settings_logmonitoring_test.go index 75ead5cbea..31965462f5 100644 --- a/pkg/clients/dynatrace/settings_logmonitoring_test.go +++ b/pkg/clients/dynatrace/settings_logmonitoring_test.go @@ -6,8 +6,8 @@ import ( "net/http/httptest" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/pkg/controllers/csi/driver/volumes/volume_config.go b/pkg/controllers/csi/driver/volumes/volume_config.go index 523b466567..c53bd2415c 100644 --- a/pkg/controllers/csi/driver/volumes/volume_config.go +++ b/pkg/controllers/csi/driver/volumes/volume_config.go @@ -3,7 +3,7 @@ package csivolumes import ( "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/container-storage-interface/spec/lib/go/csi" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/pkg/controllers/csi/metadata/correctness.go b/pkg/controllers/csi/metadata/correctness.go index 3c24bac18b..230dc78193 100644 --- a/pkg/controllers/csi/metadata/correctness.go +++ b/pkg/controllers/csi/metadata/correctness.go @@ -6,7 +6,7 @@ import ( "path/filepath" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/symlink" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" diff --git a/pkg/controllers/csi/provisioner/cleanup/binaries.go b/pkg/controllers/csi/provisioner/cleanup/binaries.go index 3089ba180b..9c2c3206fe 100644 --- a/pkg/controllers/csi/provisioner/cleanup/binaries.go +++ b/pkg/controllers/csi/provisioner/cleanup/binaries.go @@ -3,7 +3,7 @@ package cleanup import ( "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "golang.org/x/exp/maps" ) diff --git a/pkg/controllers/csi/provisioner/cleanup/binaries_test.go b/pkg/controllers/csi/provisioner/cleanup/binaries_test.go index f425a0fb64..2b7003e09b 100644 --- a/pkg/controllers/csi/provisioner/cleanup/binaries_test.go +++ b/pkg/controllers/csi/provisioner/cleanup/binaries_test.go @@ -4,8 +4,8 @@ import ( "os" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/controllers/csi/provisioner/cleanup/hostmounts.go b/pkg/controllers/csi/provisioner/cleanup/hostmounts.go index 3f7335024f..8847af05e7 100644 --- a/pkg/controllers/csi/provisioner/cleanup/hostmounts.go +++ b/pkg/controllers/csi/provisioner/cleanup/hostmounts.go @@ -3,7 +3,7 @@ package cleanup import ( "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "golang.org/x/exp/maps" "k8s.io/mount-utils" diff --git a/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go b/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go index 7001be115a..e0f0094b23 100644 --- a/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go +++ b/pkg/controllers/csi/provisioner/cleanup/hostmounts_test.go @@ -5,8 +5,8 @@ import ( "os" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "k8s.io/mount-utils" diff --git a/pkg/controllers/csi/provisioner/controller.go b/pkg/controllers/csi/provisioner/controller.go index 17ce40b9c3..d7f42765c5 100644 --- a/pkg/controllers/csi/provisioner/controller.go +++ b/pkg/controllers/csi/provisioner/controller.go @@ -20,7 +20,7 @@ import ( "context" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" diff --git a/pkg/controllers/csi/provisioner/controller_test.go b/pkg/controllers/csi/provisioner/controller_test.go index e2e71b71f3..dbc70c7683 100644 --- a/pkg/controllers/csi/provisioner/controller_test.go +++ b/pkg/controllers/csi/provisioner/controller_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/provisioner/cleanup" diff --git a/pkg/controllers/csi/provisioner/install.go b/pkg/controllers/csi/provisioner/install.go index e20e8d4ba1..946c5b132e 100644 --- a/pkg/controllers/csi/provisioner/install.go +++ b/pkg/controllers/csi/provisioner/install.go @@ -6,7 +6,7 @@ import ( "errors" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/arch" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" diff --git a/pkg/controllers/dynakube/activegate.go b/pkg/controllers/dynakube/activegate.go index 9cff4ec612..dcced9d956 100644 --- a/pkg/controllers/dynakube/activegate.go +++ b/pkg/controllers/dynakube/activegate.go @@ -3,7 +3,7 @@ package dynakube import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/istio" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/activegate/capability/capability.go b/pkg/controllers/dynakube/activegate/capability/capability.go index 76b3b92148..540018d5f4 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability.go +++ b/pkg/controllers/dynakube/activegate/capability/capability.go @@ -4,8 +4,8 @@ import ( "fmt" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "k8s.io/utils/net" "k8s.io/utils/ptr" diff --git a/pkg/controllers/dynakube/activegate/capability/capability_test.go b/pkg/controllers/dynakube/activegate/capability/capability_test.go index 2cc8ca027c..327cbf2b3b 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability_test.go +++ b/pkg/controllers/dynakube/activegate/capability/capability_test.go @@ -3,9 +3,9 @@ package capability import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/controllers/dynakube/activegate/internal/authtoken/reconciler.go b/pkg/controllers/dynakube/activegate/internal/authtoken/reconciler.go index ae4a64cec4..e688d48158 100644 --- a/pkg/controllers/dynakube/activegate/internal/authtoken/reconciler.go +++ b/pkg/controllers/dynakube/activegate/internal/authtoken/reconciler.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/activegate/internal/authtoken/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/authtoken/reconciler_test.go index c6a7f7435e..66aa59ffed 100644 --- a/pkg/controllers/dynakube/activegate/internal/authtoken/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/internal/authtoken/reconciler_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" diff --git a/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go b/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go index 420ac86db9..fef2fd909d 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/reconciler.go @@ -4,7 +4,7 @@ import ( "context" "reflect" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go index ff6e146c9d..cd1aa41ef5 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/reconciler_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/authtoken" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubesystem" diff --git a/pkg/controllers/dynakube/activegate/internal/capability/service.go b/pkg/controllers/dynakube/activegate/internal/capability/service.go index a02b07eb8d..76ef4f6444 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/service.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/service.go @@ -1,7 +1,7 @@ package capability import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" diff --git a/pkg/controllers/dynakube/activegate/internal/capability/service_test.go b/pkg/controllers/dynakube/activegate/internal/capability/service_test.go index ce00f66325..e7202d9583 100644 --- a/pkg/controllers/dynakube/activegate/internal/capability/service_test.go +++ b/pkg/controllers/dynakube/activegate/internal/capability/service_test.go @@ -3,8 +3,8 @@ package capability import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" agutil "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" diff --git a/pkg/controllers/dynakube/activegate/internal/customproperties/reconciler.go b/pkg/controllers/dynakube/activegate/internal/customproperties/reconciler.go index f21d8e6f80..7908b010f6 100644 --- a/pkg/controllers/dynakube/activegate/internal/customproperties/reconciler.go +++ b/pkg/controllers/dynakube/activegate/internal/customproperties/reconciler.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" diff --git a/pkg/controllers/dynakube/activegate/internal/customproperties/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/customproperties/reconciler_test.go index 0c2dcda370..a902385fdb 100644 --- a/pkg/controllers/dynakube/activegate/internal/customproperties/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/internal/customproperties/reconciler_test.go @@ -6,7 +6,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/authtoken.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/authtoken.go index b378c546aa..356b2f757d 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/authtoken.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/authtoken.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/authtoken" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs.go index 5c22cf1b93..bca47c6068 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs.go @@ -3,7 +3,7 @@ package modifiers import ( "path/filepath" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs_test.go index 7d3247f556..a21e0db748 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs_test.go @@ -3,7 +3,7 @@ package modifiers import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config.go index ca8e8a9590..94706a4589 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/util/prioritymap" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config_test.go index 8d95367158..c747c1e183 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/config_test.go @@ -3,8 +3,8 @@ package modifiers import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/customprops.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/customprops.go index 2f8dd20f2e..752136db42 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/customprops.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/customprops.go @@ -3,7 +3,7 @@ package modifiers import ( "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/customproperties" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/customprops_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/customprops_test.go index d6222c2d24..869a4be2f6 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/customprops_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/customprops_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec.go index 5aa66850bf..9658bc52bd 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" eecconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec_test.go index fc4416f767..ab517a9dbc 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/eec_test.go @@ -3,7 +3,7 @@ package modifiers import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kspm.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kspm.go index a5b872d382..576972ace0 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kspm.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kspm.go @@ -2,8 +2,8 @@ package modifiers import ( "github.com/Dynatrace/dynatrace-operator/pkg/api" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kspm_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kspm_test.go index a5b4d064e0..456666fb3a 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kspm_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kspm_test.go @@ -3,8 +3,8 @@ package modifiers import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon.go index 37f787b963..02e368342c 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon_test.go index dec5446179..9b4e547274 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/kubemon_test.go @@ -3,7 +3,7 @@ package modifiers import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/proxy.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/proxy.go index 9016a85be7..4c428542af 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/proxy.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/proxy.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/proxy_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/proxy_test.go index 38f8e5f752..17144ec164 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/proxy_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/proxy_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/rawimage.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/rawimage.go index 43b1894dd3..bc355b713e 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/rawimage.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/rawimage.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go index 15ced80792..513cdbd61f 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/readonly.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport.go index acad9f5465..f0b43e6a03 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/serviceport.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/ssl_volume.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/ssl_volume.go index 644d048e4d..9485646237 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/ssl_volume.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/ssl_volume.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/trustedcas_volume.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/trustedcas_volume.go index 4b99be2ac2..74bdd54a2c 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/trustedcas_volume.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/trustedcas_volume.go @@ -1,7 +1,7 @@ package modifiers import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler.go b/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler.go index e8b3b061f7..8a2041d2ff 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler.go @@ -5,7 +5,7 @@ import ( "strconv" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/authtoken" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler_test.go index c128f5558e..32dba75c78 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/reconciler_test.go @@ -9,8 +9,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" dynafake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/authtoken" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/customproperties" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index 6859d1ab13..de7115c67b 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -4,7 +4,7 @@ import ( "strconv" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index 918c55c097..24c0743da7 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -7,9 +7,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/internal/statefulset/builder" diff --git a/pkg/controllers/dynakube/activegate/internal/tls/reconciler.go b/pkg/controllers/dynakube/activegate/internal/tls/reconciler.go index 606d509daa..639fb24a49 100644 --- a/pkg/controllers/dynakube/activegate/internal/tls/reconciler.go +++ b/pkg/controllers/dynakube/activegate/internal/tls/reconciler.go @@ -5,7 +5,7 @@ import ( "crypto/x509" "net" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/certificates" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go index 09dc93e5de..68412c66ad 100644 --- a/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/controllers/dynakube/activegate/reconciler.go b/pkg/controllers/dynakube/activegate/reconciler.go index 7f219ec45c..e73b6458c0 100644 --- a/pkg/controllers/dynakube/activegate/reconciler.go +++ b/pkg/controllers/dynakube/activegate/reconciler.go @@ -2,7 +2,7 @@ package activegate import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" diff --git a/pkg/controllers/dynakube/activegate/reconciler_test.go b/pkg/controllers/dynakube/activegate/reconciler_test.go index d5e7525b60..6bf264d1d0 100644 --- a/pkg/controllers/dynakube/activegate/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/reconciler_test.go @@ -7,8 +7,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" diff --git a/pkg/controllers/dynakube/activegate_test.go b/pkg/controllers/dynakube/activegate_test.go index 25cbaf44f3..566ba17210 100644 --- a/pkg/controllers/dynakube/activegate_test.go +++ b/pkg/controllers/dynakube/activegate_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/apimonitoring" controllermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/controllers" diff --git a/pkg/controllers/dynakube/apimonitoring/reconciler.go b/pkg/controllers/dynakube/apimonitoring/reconciler.go index a59bc4c087..084f8dddaa 100644 --- a/pkg/controllers/dynakube/apimonitoring/reconciler.go +++ b/pkg/controllers/dynakube/apimonitoring/reconciler.go @@ -3,7 +3,7 @@ package apimonitoring import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/monitoredentities" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/apimonitoring/reconciler_test.go b/pkg/controllers/dynakube/apimonitoring/reconciler_test.go index 6bc542572b..5ae32efee6 100644 --- a/pkg/controllers/dynakube/apimonitoring/reconciler_test.go +++ b/pkg/controllers/dynakube/apimonitoring/reconciler_test.go @@ -4,8 +4,8 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/conditions.go b/pkg/controllers/dynakube/conditions.go index 57c8548f33..6bf05dcfad 100644 --- a/pkg/controllers/dynakube/conditions.go +++ b/pkg/controllers/dynakube/conditions.go @@ -1,7 +1,7 @@ package dynakube import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts.go b/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts.go index 97c8b481c5..aa0de5de7c 100644 --- a/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts.go +++ b/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts.go @@ -5,7 +5,7 @@ import ( "net/url" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/pkg/errors" ) diff --git a/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts_test.go b/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts_test.go index cd826eb6a6..d88d440966 100644 --- a/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts_test.go +++ b/pkg/controllers/dynakube/connectioninfo/activegate/communication_hosts_test.go @@ -4,8 +4,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler.go b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler.go index f3dfce99b5..9cf0c4fe77 100644 --- a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler.go +++ b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler.go @@ -4,7 +4,7 @@ import ( "context" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" diff --git a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go index cafe0d8637..38020bb26e 100644 --- a/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go +++ b/pkg/controllers/dynakube/connectioninfo/activegate/reconciler_test.go @@ -7,8 +7,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts.go b/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts.go index df2b9f27e0..2ec59c751f 100644 --- a/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts.go +++ b/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts.go @@ -1,7 +1,7 @@ package oaconnectioninfo import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" ) diff --git a/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts_test.go b/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts_test.go index c9479fa1e7..2d3cd2ad5e 100644 --- a/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts_test.go +++ b/pkg/controllers/dynakube/connectioninfo/oneagent/communication_hosts_test.go @@ -4,8 +4,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go index c445742255..52b5106035 100644 --- a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go +++ b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler.go @@ -1,8 +1,8 @@ package oaconnectioninfo import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" diff --git a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go index f3e0b233a4..480f1e55d0 100644 --- a/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go +++ b/pkg/controllers/dynakube/connectioninfo/oneagent/reconciler_test.go @@ -7,8 +7,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/controller.go b/pkg/controllers/dynakube/controller.go index ff9e4df9ad..45b3ab5053 100644 --- a/pkg/controllers/dynakube/controller.go +++ b/pkg/controllers/dynakube/controller.go @@ -7,7 +7,7 @@ import ( "time" dynatracestatus "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/apimonitoring" diff --git a/pkg/controllers/dynakube/controller_system_test.go b/pkg/controllers/dynakube/controller_system_test.go index 1d48ec7593..23e9b2cd9b 100644 --- a/pkg/controllers/dynakube/controller_system_test.go +++ b/pkg/controllers/dynakube/controller_system_test.go @@ -8,10 +8,10 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" ag "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" diff --git a/pkg/controllers/dynakube/controller_test.go b/pkg/controllers/dynakube/controller_test.go index e72ed465d8..dec95523e0 100644 --- a/pkg/controllers/dynakube/controller_test.go +++ b/pkg/controllers/dynakube/controller_test.go @@ -10,9 +10,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" ag "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate" diff --git a/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata.go b/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata.go index d38cb81e9a..38574b1961 100644 --- a/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata.go +++ b/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/version" ) diff --git a/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata_test.go b/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata_test.go index b30493039d..96606d076c 100644 --- a/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata_test.go +++ b/pkg/controllers/dynakube/deploymentmetadata/deploymentmetadata_test.go @@ -3,8 +3,8 @@ package deploymentmetadata import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/stretchr/testify/assert" ) diff --git a/pkg/controllers/dynakube/deploymentmetadata/reconciler.go b/pkg/controllers/dynakube/deploymentmetadata/reconciler.go index 936c081a79..e715f1b211 100644 --- a/pkg/controllers/dynakube/deploymentmetadata/reconciler.go +++ b/pkg/controllers/dynakube/deploymentmetadata/reconciler.go @@ -3,7 +3,7 @@ package deploymentmetadata import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/configmap" "github.com/Dynatrace/dynatrace-operator/pkg/version" diff --git a/pkg/controllers/dynakube/deploymentmetadata/reconciler_test.go b/pkg/controllers/dynakube/deploymentmetadata/reconciler_test.go index 202f170bc6..d87a0022ef 100644 --- a/pkg/controllers/dynakube/deploymentmetadata/reconciler_test.go +++ b/pkg/controllers/dynakube/deploymentmetadata/reconciler_test.go @@ -4,9 +4,9 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" diff --git a/pkg/controllers/dynakube/dtpullsecret/find.go b/pkg/controllers/dynakube/dtpullsecret/find.go index 44de16c68b..8d85cc7963 100644 --- a/pkg/controllers/dynakube/dtpullsecret/find.go +++ b/pkg/controllers/dynakube/dtpullsecret/find.go @@ -3,7 +3,7 @@ package dtpullsecret import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" diff --git a/pkg/controllers/dynakube/dtpullsecret/find_test.go b/pkg/controllers/dynakube/dtpullsecret/find_test.go index 8770bee11e..ab926aefbd 100644 --- a/pkg/controllers/dynakube/dtpullsecret/find_test.go +++ b/pkg/controllers/dynakube/dtpullsecret/find_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/controllers/dynakube/dtpullsecret/generate_test.go b/pkg/controllers/dynakube/dtpullsecret/generate_test.go index f2022097aa..5934a46aa2 100644 --- a/pkg/controllers/dynakube/dtpullsecret/generate_test.go +++ b/pkg/controllers/dynakube/dtpullsecret/generate_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/dtpullsecret/reconciler.go b/pkg/controllers/dynakube/dtpullsecret/reconciler.go index 4b2f16a13e..4b579c3131 100644 --- a/pkg/controllers/dynakube/dtpullsecret/reconciler.go +++ b/pkg/controllers/dynakube/dtpullsecret/reconciler.go @@ -4,7 +4,7 @@ import ( "context" "reflect" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" diff --git a/pkg/controllers/dynakube/dtpullsecret/reconciler_test.go b/pkg/controllers/dynakube/dtpullsecret/reconciler_test.go index 65734bc261..b053c5eff4 100644 --- a/pkg/controllers/dynakube/dtpullsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/dtpullsecret/reconciler_test.go @@ -7,8 +7,8 @@ import ( "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/dynatraceclient/builder.go b/pkg/controllers/dynakube/dynatraceclient/builder.go index 9eb33dcd46..ef212d172d 100644 --- a/pkg/controllers/dynakube/dynatraceclient/builder.go +++ b/pkg/controllers/dynakube/dynatraceclient/builder.go @@ -3,7 +3,7 @@ package dynatraceclient import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" diff --git a/pkg/controllers/dynakube/dynatraceclient/builder_test.go b/pkg/controllers/dynakube/dynatraceclient/builder_test.go index ca4a564919..fa0db46c91 100644 --- a/pkg/controllers/dynakube/dynatraceclient/builder_test.go +++ b/pkg/controllers/dynakube/dynatraceclient/builder_test.go @@ -5,7 +5,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/dynatraceclient/options.go b/pkg/controllers/dynakube/dynatraceclient/options.go index db0d08968e..97858cc577 100644 --- a/pkg/controllers/dynakube/dynatraceclient/options.go +++ b/pkg/controllers/dynakube/dynatraceclient/options.go @@ -3,7 +3,7 @@ package dynatraceclient import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" diff --git a/pkg/controllers/dynakube/dynatraceclient/options_test.go b/pkg/controllers/dynakube/dynatraceclient/options_test.go index afd549c940..e96a22967e 100644 --- a/pkg/controllers/dynakube/dynatraceclient/options_test.go +++ b/pkg/controllers/dynakube/dynatraceclient/options_test.go @@ -6,7 +6,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" diff --git a/pkg/controllers/dynakube/extension/eec/reconciler.go b/pkg/controllers/dynakube/extension/eec/reconciler.go index 13204691cf..8a4c4bd468 100644 --- a/pkg/controllers/dynakube/extension/eec/reconciler.go +++ b/pkg/controllers/dynakube/extension/eec/reconciler.go @@ -1,7 +1,7 @@ package eec import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/statefulset" diff --git a/pkg/controllers/dynakube/extension/eec/reconciler_test.go b/pkg/controllers/dynakube/extension/eec/reconciler_test.go index 08ae11b2e6..7052e708d8 100644 --- a/pkg/controllers/dynakube/extension/eec/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/eec/reconciler_test.go @@ -9,8 +9,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/consts" eecConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/extension/eec/statefulset.go b/pkg/controllers/dynakube/extension/eec/statefulset.go index 41f6c40844..22cab0a70c 100644 --- a/pkg/controllers/dynakube/extension/eec/statefulset.go +++ b/pkg/controllers/dynakube/extension/eec/statefulset.go @@ -4,7 +4,7 @@ import ( "strconv" "github.com/Dynatrace/dynatrace-operator/pkg/api" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" eecConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" diff --git a/pkg/controllers/dynakube/extension/reconciler.go b/pkg/controllers/dynakube/extension/reconciler.go index c873b7dd73..da29ab9a8f 100644 --- a/pkg/controllers/dynakube/extension/reconciler.go +++ b/pkg/controllers/dynakube/extension/reconciler.go @@ -3,7 +3,7 @@ package extension import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/eec" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/tls" diff --git a/pkg/controllers/dynakube/extension/reconciler_test.go b/pkg/controllers/dynakube/extension/reconciler_test.go index f312e4bd3a..a1e4c2e814 100644 --- a/pkg/controllers/dynakube/extension/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/reconciler_test.go @@ -6,8 +6,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/consts" eecConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/extension/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/extension/tls/reconciler.go b/pkg/controllers/dynakube/extension/tls/reconciler.go index 3903a9ea34..6ef8a57bf4 100644 --- a/pkg/controllers/dynakube/extension/tls/reconciler.go +++ b/pkg/controllers/dynakube/extension/tls/reconciler.go @@ -4,7 +4,7 @@ import ( "context" "crypto/x509" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/util/certificates" diff --git a/pkg/controllers/dynakube/extension/tls/reconciler_test.go b/pkg/controllers/dynakube/extension/tls/reconciler_test.go index 173ad74aba..0fd16d4e98 100644 --- a/pkg/controllers/dynakube/extension/tls/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/tls/reconciler_test.go @@ -8,8 +8,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/injection/reconciler.go b/pkg/controllers/dynakube/injection/reconciler.go index 1b5b2ba022..cdb4467072 100644 --- a/pkg/controllers/dynakube/injection/reconciler.go +++ b/pkg/controllers/dynakube/injection/reconciler.go @@ -5,7 +5,7 @@ import ( goerrors "errors" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" oaconnectioninfo "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo/oneagent" diff --git a/pkg/controllers/dynakube/injection/reconciler_test.go b/pkg/controllers/dynakube/injection/reconciler_test.go index 5a826c4a4e..1038388031 100644 --- a/pkg/controllers/dynakube/injection/reconciler_test.go +++ b/pkg/controllers/dynakube/injection/reconciler_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" diff --git a/pkg/controllers/dynakube/istio/reconciler.go b/pkg/controllers/dynakube/istio/reconciler.go index 2bbef178ac..4ca44c1ac1 100644 --- a/pkg/controllers/dynakube/istio/reconciler.go +++ b/pkg/controllers/dynakube/istio/reconciler.go @@ -6,7 +6,7 @@ import ( "net" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo/activegate" oaconnectioninfo "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo/oneagent" diff --git a/pkg/controllers/dynakube/istio/reconciler_test.go b/pkg/controllers/dynakube/istio/reconciler_test.go index 14ed772966..468a3a0e0a 100644 --- a/pkg/controllers/dynakube/istio/reconciler_test.go +++ b/pkg/controllers/dynakube/istio/reconciler_test.go @@ -7,9 +7,9 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/controllers/dynakube/kspm/daemonset/certs.go b/pkg/controllers/dynakube/kspm/daemonset/certs.go index 2211faca51..938409d740 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/certs.go +++ b/pkg/controllers/dynakube/kspm/daemonset/certs.go @@ -1,7 +1,7 @@ package daemonset import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" corev1 "k8s.io/api/core/v1" ) diff --git a/pkg/controllers/dynakube/kspm/daemonset/certs_test.go b/pkg/controllers/dynakube/kspm/daemonset/certs_test.go index ca1b012e2f..bbb6c5bfac 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/certs_test.go +++ b/pkg/controllers/dynakube/kspm/daemonset/certs_test.go @@ -3,8 +3,8 @@ package daemonset import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" ) func getDynaKubeWithCerts(t *testing.T) dynakube.DynaKube { diff --git a/pkg/controllers/dynakube/kspm/daemonset/container.go b/pkg/controllers/dynakube/kspm/daemonset/container.go index 3533c927e8..ef072c701a 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/container.go +++ b/pkg/controllers/dynakube/kspm/daemonset/container.go @@ -1,7 +1,7 @@ package daemonset import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/resources" corev1 "k8s.io/api/core/v1" "k8s.io/utils/ptr" diff --git a/pkg/controllers/dynakube/kspm/daemonset/container_test.go b/pkg/controllers/dynakube/kspm/daemonset/container_test.go index 8cf94e8d0f..b7e2197cd6 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/container_test.go +++ b/pkg/controllers/dynakube/kspm/daemonset/container_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/pkg/controllers/dynakube/kspm/daemonset/env.go b/pkg/controllers/dynakube/kspm/daemonset/env.go index 687cb8e995..a38a1112c2 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/env.go +++ b/pkg/controllers/dynakube/kspm/daemonset/env.go @@ -3,7 +3,7 @@ package daemonset import ( "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" agconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" corev1 "k8s.io/api/core/v1" diff --git a/pkg/controllers/dynakube/kspm/daemonset/env_test.go b/pkg/controllers/dynakube/kspm/daemonset/env_test.go index 40d6acc84a..63252b605f 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/env_test.go +++ b/pkg/controllers/dynakube/kspm/daemonset/env_test.go @@ -3,7 +3,7 @@ package daemonset import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" diff --git a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go index dea0fdfe9e..351eb11e92 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/kspm/daemonset/reconciler.go @@ -4,7 +4,7 @@ import ( "context" "maps" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/daemonset" diff --git a/pkg/controllers/dynakube/kspm/daemonset/reconciler_test.go b/pkg/controllers/dynakube/kspm/daemonset/reconciler_test.go index 0fe8bc65e6..b2d606be8b 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/reconciler_test.go +++ b/pkg/controllers/dynakube/kspm/daemonset/reconciler_test.go @@ -6,9 +6,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/kspm/daemonset/volumes.go b/pkg/controllers/dynakube/kspm/daemonset/volumes.go index 3616408abb..6a3f695521 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/volumes.go +++ b/pkg/controllers/dynakube/kspm/daemonset/volumes.go @@ -2,8 +2,8 @@ package daemonset import ( "github.com/Dynatrace/dynatrace-operator/pkg/api" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" corev1 "k8s.io/api/core/v1" ) diff --git a/pkg/controllers/dynakube/kspm/daemonset/volumes_test.go b/pkg/controllers/dynakube/kspm/daemonset/volumes_test.go index 864d7558ed..01255049ff 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/kspm/daemonset/volumes_test.go @@ -3,7 +3,7 @@ package daemonset import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/pkg/controllers/dynakube/kspm/reconciler.go b/pkg/controllers/dynakube/kspm/reconciler.go index a221adc340..8db939959f 100644 --- a/pkg/controllers/dynakube/kspm/reconciler.go +++ b/pkg/controllers/dynakube/kspm/reconciler.go @@ -3,7 +3,7 @@ package kspm import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/kspm/daemonset" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/kspm/token" diff --git a/pkg/controllers/dynakube/kspm/token/reconciler.go b/pkg/controllers/dynakube/kspm/token/reconciler.go index 0aeafc9458..bf076a7ac3 100644 --- a/pkg/controllers/dynakube/kspm/token/reconciler.go +++ b/pkg/controllers/dynakube/kspm/token/reconciler.go @@ -3,8 +3,8 @@ package token import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/dttoken" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" diff --git a/pkg/controllers/dynakube/kspm/token/reconciler_test.go b/pkg/controllers/dynakube/kspm/token/reconciler_test.go index 59010e66d2..0d47b8a275 100644 --- a/pkg/controllers/dynakube/kspm/token/reconciler_test.go +++ b/pkg/controllers/dynakube/kspm/token/reconciler_test.go @@ -6,8 +6,8 @@ import ( "testing" dtfake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go index ba95acda5c..65a8ac79d9 100644 --- a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" diff --git a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go index 4740896f6f..de57f24816 100644 --- a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go @@ -8,9 +8,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/args.go b/pkg/controllers/dynakube/logmonitoring/daemonset/args.go index 75606fda6f..eeb841cee6 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/args.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/args.go @@ -3,7 +3,7 @@ package daemonset import ( "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" ) func getInitArgs(dk dynakube.DynaKube) []string { diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/args_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/args_test.go index 2ef66ca8e9..8804d9f83f 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/args_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/args_test.go @@ -3,8 +3,8 @@ package daemonset import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" "github.com/stretchr/testify/assert" ) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go index 61970eefd0..d4f7d37d29 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go @@ -1,7 +1,7 @@ package daemonset import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" corev1 "k8s.io/api/core/v1" "k8s.io/utils/ptr" ) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go index 1a432fd966..71860734a4 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go @@ -4,8 +4,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/env.go b/pkg/controllers/dynakube/logmonitoring/daemonset/env.go index 655ce1a2b1..54f5d7404d 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/env.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/env.go @@ -1,7 +1,7 @@ package daemonset import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" corev1 "k8s.io/api/core/v1" ) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/env_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/env_test.go index df88721976..e05927cb84 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/env_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/env_test.go @@ -3,7 +3,7 @@ package daemonset import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go index 5a62ecdc1c..63ecdc1934 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go @@ -3,7 +3,7 @@ package daemonset import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/daemonset" diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go index 01c60cbe67..881ab6ac9a 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go @@ -6,9 +6,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go index 3cefb1f94e..f1b10b86b5 100644 --- a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go @@ -3,8 +3,8 @@ package logmonsettings import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/daemonset" diff --git a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler_test.go index cb90233c07..b6b0725f39 100644 --- a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler_test.go @@ -5,8 +5,8 @@ import ( "errors" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/stretchr/testify/mock" diff --git a/pkg/controllers/dynakube/logmonitoring/reconciler.go b/pkg/controllers/dynakube/logmonitoring/reconciler.go index 6c91997f11..8c8806e766 100644 --- a/pkg/controllers/dynakube/logmonitoring/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/reconciler.go @@ -3,7 +3,7 @@ package logmonitoring import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" oaconnectioninfo "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo/oneagent" diff --git a/pkg/controllers/dynakube/logmonitoring/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/reconciler_test.go index 4e95719e7d..5b9a850c9c 100644 --- a/pkg/controllers/dynakube/logmonitoring/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/reconciler_test.go @@ -5,8 +5,8 @@ import ( "errors" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" controllermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/controllers" diff --git a/pkg/controllers/dynakube/metadata/rules/reconciler.go b/pkg/controllers/dynakube/metadata/rules/reconciler.go index 8df4a7e208..d188dd4f2d 100644 --- a/pkg/controllers/dynakube/metadata/rules/reconciler.go +++ b/pkg/controllers/dynakube/metadata/rules/reconciler.go @@ -4,7 +4,7 @@ import ( "context" "errors" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/metadata/rules/reconciler_test.go b/pkg/controllers/dynakube/metadata/rules/reconciler_test.go index 3b56ea18b1..9be41c516f 100644 --- a/pkg/controllers/dynakube/metadata/rules/reconciler_test.go +++ b/pkg/controllers/dynakube/metadata/rules/reconciler_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" diff --git a/pkg/controllers/dynakube/monitoredentities/reconciler.go b/pkg/controllers/dynakube/monitoredentities/reconciler.go index 15c1a2ec17..11bdf3de58 100644 --- a/pkg/controllers/dynakube/monitoredentities/reconciler.go +++ b/pkg/controllers/dynakube/monitoredentities/reconciler.go @@ -3,7 +3,7 @@ package monitoredentities import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/monitoredentities/reconciler_test.go b/pkg/controllers/dynakube/monitoredentities/reconciler_test.go index ad76dfe185..bee91b643a 100644 --- a/pkg/controllers/dynakube/monitoredentities/reconciler_test.go +++ b/pkg/controllers/dynakube/monitoredentities/reconciler_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/stretchr/testify/mock" diff --git a/pkg/controllers/dynakube/oneagent/daemonset/affinity_test.go b/pkg/controllers/dynakube/oneagent/daemonset/affinity_test.go index 4019c068da..360497ac60 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/affinity_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/affinity_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" ) diff --git a/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go b/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go index 703e8c84a1..d992947683 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go @@ -6,9 +6,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go index d8564e96aa..3738a380b1 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go @@ -3,8 +3,8 @@ package daemonset import ( "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/Dynatrace/dynatrace-operator/pkg/util/dtversion" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go index 411797b8f2..86d50e066b 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go @@ -6,8 +6,8 @@ import ( "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/version" diff --git a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go index 09db67f88a..49958c8715 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go @@ -2,7 +2,7 @@ package daemonset import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" logmonitoring "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/daemonset" diff --git a/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go b/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go index 10d43fb9c6..7aa1aa08a4 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/env_vars_test.go @@ -5,9 +5,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" logmonitoringds "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/daemonset" diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go index 9dbd5421d8..fff4a391e8 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go @@ -1,7 +1,7 @@ package daemonset import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csivolumes "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver/volumes" hostvolumes "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver/volumes/host" diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go index 1e33d9e7b5..e268b4ba65 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go @@ -4,9 +4,9 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/controllers/dynakube/oneagent/oneagent_reconciler.go b/pkg/controllers/dynakube/oneagent/oneagent_reconciler.go index e5ff5a511d..bbf429d408 100644 --- a/pkg/controllers/dynakube/oneagent/oneagent_reconciler.go +++ b/pkg/controllers/dynakube/oneagent/oneagent_reconciler.go @@ -9,8 +9,8 @@ import ( "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" diff --git a/pkg/controllers/dynakube/oneagent/oneagent_reconciler_test.go b/pkg/controllers/dynakube/oneagent/oneagent_reconciler_test.go index 32ce05f6fb..85488261a3 100644 --- a/pkg/controllers/dynakube/oneagent/oneagent_reconciler_test.go +++ b/pkg/controllers/dynakube/oneagent/oneagent_reconciler_test.go @@ -6,8 +6,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" diff --git a/pkg/controllers/dynakube/otelc/configuration/reconciler.go b/pkg/controllers/dynakube/otelc/configuration/reconciler.go index 46627101df..6ff6404eb5 100644 --- a/pkg/controllers/dynakube/otelc/configuration/reconciler.go +++ b/pkg/controllers/dynakube/otelc/configuration/reconciler.go @@ -3,7 +3,7 @@ package configuration import ( "path/filepath" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" diff --git a/pkg/controllers/dynakube/otelc/configuration/reconciler_test.go b/pkg/controllers/dynakube/otelc/configuration/reconciler_test.go index 2e5bec38d2..d69315e765 100644 --- a/pkg/controllers/dynakube/otelc/configuration/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/configuration/reconciler_test.go @@ -4,8 +4,8 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/otelc/reconciler.go b/pkg/controllers/dynakube/otelc/reconciler.go index 7ae6a0b480..e5849d41b0 100644 --- a/pkg/controllers/dynakube/otelc/reconciler.go +++ b/pkg/controllers/dynakube/otelc/reconciler.go @@ -3,7 +3,7 @@ package otelc import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/configuration" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/secret" diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler.go b/pkg/controllers/dynakube/otelc/secret/reconciler.go index 0dba9a61c8..044a24eb9a 100644 --- a/pkg/controllers/dynakube/otelc/secret/reconciler.go +++ b/pkg/controllers/dynakube/otelc/secret/reconciler.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler_test.go b/pkg/controllers/dynakube/otelc/secret/reconciler_test.go index 2ced4814ee..bdc9c2915e 100644 --- a/pkg/controllers/dynakube/otelc/secret/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/secret/reconciler_test.go @@ -8,9 +8,9 @@ import ( schemeFake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/otelc/service/reconciler.go b/pkg/controllers/dynakube/otelc/service/reconciler.go index 50c20bf3aa..49404cbadb 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler.go @@ -1,7 +1,7 @@ package service import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" diff --git a/pkg/controllers/dynakube/otelc/service/reconciler_test.go b/pkg/controllers/dynakube/otelc/service/reconciler_test.go index e405f6bf81..7ae68876c8 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler_test.go @@ -4,8 +4,8 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/otelc/statefulset/container.go b/pkg/controllers/dynakube/otelc/statefulset/container.go index b3269861bb..cb44fcae7c 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/container.go +++ b/pkg/controllers/dynakube/otelc/statefulset/container.go @@ -3,7 +3,7 @@ package statefulset import ( "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" corev1 "k8s.io/api/core/v1" ) diff --git a/pkg/controllers/dynakube/otelc/statefulset/container_test.go b/pkg/controllers/dynakube/otelc/statefulset/container_test.go index aba058924d..7b71d68351 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/container_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/container_test.go @@ -3,7 +3,7 @@ package statefulset import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/stretchr/testify/assert" ) diff --git a/pkg/controllers/dynakube/otelc/statefulset/env.go b/pkg/controllers/dynakube/otelc/statefulset/env.go index f6e70413fb..9ab5ba611d 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env.go @@ -3,7 +3,7 @@ package statefulset import ( "strconv" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" otelcConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" diff --git a/pkg/controllers/dynakube/otelc/statefulset/env_test.go b/pkg/controllers/dynakube/otelc/statefulset/env_test.go index c459c57000..f0716af98d 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" otelcConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go index aa7550bf1b..88d8444bbe 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go @@ -4,7 +4,7 @@ import ( "context" "github.com/Dynatrace/dynatrace-operator/pkg/api" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/configuration" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go index 43e98a1851..f526c1c39a 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go @@ -6,7 +6,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" diff --git a/pkg/controllers/dynakube/otelc/statefulset/volumes.go b/pkg/controllers/dynakube/otelc/statefulset/volumes.go index 595fa6ccc9..a145905c0a 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/volumes.go +++ b/pkg/controllers/dynakube/otelc/statefulset/volumes.go @@ -1,7 +1,7 @@ package statefulset import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/configuration" otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" diff --git a/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go b/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go index 93449c7a19..82c9a5284c 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/volumes_test.go @@ -3,9 +3,9 @@ package statefulset import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/consts" otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/phase.go b/pkg/controllers/dynakube/phase.go index 96a3168739..3845883150 100644 --- a/pkg/controllers/dynakube/phase.go +++ b/pkg/controllers/dynakube/phase.go @@ -4,7 +4,7 @@ import ( "context" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" appsv1 "k8s.io/api/apps/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" diff --git a/pkg/controllers/dynakube/phase_test.go b/pkg/controllers/dynakube/phase_test.go index b36ff6ccac..380a600ba7 100644 --- a/pkg/controllers/dynakube/phase_test.go +++ b/pkg/controllers/dynakube/phase_test.go @@ -6,11 +6,11 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/kspm" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/kspm" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go index 3e02795b4e..99be3d6924 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go index 5f36b63019..1aecd8c014 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go @@ -8,8 +8,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/proxy/reconciler.go b/pkg/controllers/dynakube/proxy/reconciler.go index 8f70f98dc0..e44c16b206 100644 --- a/pkg/controllers/dynakube/proxy/reconciler.go +++ b/pkg/controllers/dynakube/proxy/reconciler.go @@ -5,7 +5,7 @@ import ( "net/url" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" diff --git a/pkg/controllers/dynakube/proxy/reconciler_test.go b/pkg/controllers/dynakube/proxy/reconciler_test.go index 1d9c005451..32a68dba51 100644 --- a/pkg/controllers/dynakube/proxy/reconciler_test.go +++ b/pkg/controllers/dynakube/proxy/reconciler_test.go @@ -6,8 +6,8 @@ import ( dtfake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/token/feature.go b/pkg/controllers/dynakube/token/feature.go index b2a22879e5..49588ee271 100644 --- a/pkg/controllers/dynakube/token/feature.go +++ b/pkg/controllers/dynakube/token/feature.go @@ -1,7 +1,7 @@ package token import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "golang.org/x/exp/slices" ) diff --git a/pkg/controllers/dynakube/token/feature_test.go b/pkg/controllers/dynakube/token/feature_test.go index e56777e824..65c89a68f7 100644 --- a/pkg/controllers/dynakube/token/feature_test.go +++ b/pkg/controllers/dynakube/token/feature_test.go @@ -3,7 +3,7 @@ package token import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/stretchr/testify/assert" ) diff --git a/pkg/controllers/dynakube/token/reader.go b/pkg/controllers/dynakube/token/reader.go index 9c69378a61..03dfa1a3b3 100644 --- a/pkg/controllers/dynakube/token/reader.go +++ b/pkg/controllers/dynakube/token/reader.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" diff --git a/pkg/controllers/dynakube/token/reader_test.go b/pkg/controllers/dynakube/token/reader_test.go index 25cc72dc59..a2a2b4d72f 100644 --- a/pkg/controllers/dynakube/token/reader_test.go +++ b/pkg/controllers/dynakube/token/reader_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/token/token.go b/pkg/controllers/dynakube/token/token.go index daafeb9367..bb5af68013 100644 --- a/pkg/controllers/dynakube/token/token.go +++ b/pkg/controllers/dynakube/token/token.go @@ -4,7 +4,7 @@ import ( "context" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/pkg/errors" ) diff --git a/pkg/controllers/dynakube/token/tokens.go b/pkg/controllers/dynakube/token/tokens.go index 87930c968e..1ee8333a52 100644 --- a/pkg/controllers/dynakube/token/tokens.go +++ b/pkg/controllers/dynakube/token/tokens.go @@ -4,7 +4,7 @@ import ( "context" "errors" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dynatraceapi" ) diff --git a/pkg/controllers/dynakube/token/tokens_test.go b/pkg/controllers/dynakube/token/tokens_test.go index f0f8075bb8..9d4926f92b 100644 --- a/pkg/controllers/dynakube/token/tokens_test.go +++ b/pkg/controllers/dynakube/token/tokens_test.go @@ -5,8 +5,8 @@ import ( "net/http" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/version/activegate.go b/pkg/controllers/dynakube/version/activegate.go index 4e9181285f..9662dea782 100644 --- a/pkg/controllers/dynakube/version/activegate.go +++ b/pkg/controllers/dynakube/version/activegate.go @@ -4,7 +4,7 @@ import ( "context" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/version/activegate_test.go b/pkg/controllers/dynakube/version/activegate_test.go index 79d1bedc8f..a90a4d9d35 100644 --- a/pkg/controllers/dynakube/version/activegate_test.go +++ b/pkg/controllers/dynakube/version/activegate_test.go @@ -6,8 +6,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" "github.com/stretchr/testify/assert" diff --git a/pkg/controllers/dynakube/version/codemodules.go b/pkg/controllers/dynakube/version/codemodules.go index b03178fc25..464e623a07 100644 --- a/pkg/controllers/dynakube/version/codemodules.go +++ b/pkg/controllers/dynakube/version/codemodules.go @@ -4,8 +4,8 @@ import ( "context" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "k8s.io/apimachinery/pkg/api/meta" diff --git a/pkg/controllers/dynakube/version/codemodules_test.go b/pkg/controllers/dynakube/version/codemodules_test.go index daf524a522..7081df283b 100644 --- a/pkg/controllers/dynakube/version/codemodules_test.go +++ b/pkg/controllers/dynakube/version/codemodules_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" diff --git a/pkg/controllers/dynakube/version/oneagent.go b/pkg/controllers/dynakube/version/oneagent.go index 17419b83ca..c556d3e0e7 100644 --- a/pkg/controllers/dynakube/version/oneagent.go +++ b/pkg/controllers/dynakube/version/oneagent.go @@ -4,7 +4,7 @@ import ( "context" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/pkg/errors" diff --git a/pkg/controllers/dynakube/version/oneagent_test.go b/pkg/controllers/dynakube/version/oneagent_test.go index 86dca3d3ba..d9451d2800 100644 --- a/pkg/controllers/dynakube/version/oneagent_test.go +++ b/pkg/controllers/dynakube/version/oneagent_test.go @@ -6,8 +6,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace" diff --git a/pkg/controllers/dynakube/version/reconciler.go b/pkg/controllers/dynakube/version/reconciler.go index 7d1187430a..10726bbcd2 100644 --- a/pkg/controllers/dynakube/version/reconciler.go +++ b/pkg/controllers/dynakube/version/reconciler.go @@ -5,7 +5,7 @@ import ( "strings" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "sigs.k8s.io/controller-runtime/pkg/client" diff --git a/pkg/controllers/dynakube/version/reconciler_test.go b/pkg/controllers/dynakube/version/reconciler_test.go index a91441e854..79c606647a 100644 --- a/pkg/controllers/dynakube/version/reconciler_test.go +++ b/pkg/controllers/dynakube/version/reconciler_test.go @@ -8,9 +8,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dtpullsecret" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" diff --git a/pkg/controllers/dynakube/version/updater_test.go b/pkg/controllers/dynakube/version/updater_test.go index eff001a5bd..2c0f8ef46c 100644 --- a/pkg/controllers/dynakube/version/updater_test.go +++ b/pkg/controllers/dynakube/version/updater_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" versionmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/controllers/dynakube/version" diff --git a/pkg/controllers/nodes/nodes_controller.go b/pkg/controllers/nodes/nodes_controller.go index 2e0bf8f554..97130c523a 100644 --- a/pkg/controllers/nodes/nodes_controller.go +++ b/pkg/controllers/nodes/nodes_controller.go @@ -6,7 +6,7 @@ import ( "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dynatraceclient" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" diff --git a/pkg/controllers/nodes/nodes_controller_test.go b/pkg/controllers/nodes/nodes_controller_test.go index 1bae2e478e..0ecdfb2bb1 100644 --- a/pkg/controllers/nodes/nodes_controller_test.go +++ b/pkg/controllers/nodes/nodes_controller_test.go @@ -6,8 +6,8 @@ import ( "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dynatraceclient" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token" diff --git a/pkg/controllers/nodes/oneagent_dao.go b/pkg/controllers/nodes/oneagent_dao.go index 067817bd68..45dbe52c1b 100644 --- a/pkg/controllers/nodes/oneagent_dao.go +++ b/pkg/controllers/nodes/oneagent_dao.go @@ -3,7 +3,7 @@ package nodes import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "sigs.k8s.io/controller-runtime/pkg/client" ) diff --git a/pkg/injection/codemodule/installer/image/installer.go b/pkg/injection/codemodule/installer/image/installer.go index 0a6ede3dc3..de2fb92ff3 100644 --- a/pkg/injection/codemodule/installer/image/installer.go +++ b/pkg/injection/codemodule/installer/image/installer.go @@ -6,7 +6,7 @@ import ( "os" "path/filepath" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/common" diff --git a/pkg/injection/codemodule/installer/image/installer_test.go b/pkg/injection/codemodule/installer/image/installer_test.go index 2d60753994..ea8bef6624 100644 --- a/pkg/injection/codemodule/installer/image/installer_test.go +++ b/pkg/injection/codemodule/installer/image/installer_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/zip" diff --git a/pkg/injection/codemodule/installer/job/bootstrapper_test.go b/pkg/injection/codemodule/installer/job/bootstrapper_test.go index 979983a3b0..98d002084a 100644 --- a/pkg/injection/codemodule/installer/job/bootstrapper_test.go +++ b/pkg/injection/codemodule/installer/job/bootstrapper_test.go @@ -5,7 +5,7 @@ import ( "slices" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/stretchr/testify/assert" diff --git a/pkg/injection/codemodule/installer/job/installer_test.go b/pkg/injection/codemodule/installer/job/installer_test.go index 4dcd39995d..28bb58b561 100644 --- a/pkg/injection/codemodule/installer/job/installer_test.go +++ b/pkg/injection/codemodule/installer/job/installer_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" "github.com/spf13/afero" "github.com/stretchr/testify/assert" diff --git a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go index 4e6a49edb8..47cfbfc9cf 100644 --- a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go +++ b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go @@ -8,7 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/ca" "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/curl" "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/pmc" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" diff --git a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go index 26d20f2a8d..d2d041f26b 100644 --- a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go +++ b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go @@ -9,8 +9,8 @@ import ( "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/curl" "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/pmc" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" diff --git a/pkg/injection/namespace/bootstrapperconfig/endpoints.go b/pkg/injection/namespace/bootstrapperconfig/endpoints.go index d9668dd7c4..ae76fefbb2 100644 --- a/pkg/injection/namespace/bootstrapperconfig/endpoints.go +++ b/pkg/injection/namespace/bootstrapperconfig/endpoints.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtingestendpoint "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/ingestendpoint" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" diff --git a/pkg/injection/namespace/bootstrapperconfig/pmc.go b/pkg/injection/namespace/bootstrapperconfig/pmc.go index 6460a6daaf..31cca645de 100644 --- a/pkg/injection/namespace/bootstrapperconfig/pmc.go +++ b/pkg/injection/namespace/bootstrapperconfig/pmc.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" diff --git a/pkg/injection/namespace/ingestendpoint/secret.go b/pkg/injection/namespace/ingestendpoint/secret.go index 179c535462..557d785ddb 100644 --- a/pkg/injection/namespace/ingestendpoint/secret.go +++ b/pkg/injection/namespace/ingestendpoint/secret.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" diff --git a/pkg/injection/namespace/ingestendpoint/secret_test.go b/pkg/injection/namespace/ingestendpoint/secret_test.go index 367f08a3d3..55d7bd1946 100644 --- a/pkg/injection/namespace/ingestendpoint/secret_test.go +++ b/pkg/injection/namespace/ingestendpoint/secret_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" diff --git a/pkg/injection/namespace/initgeneration/initgeneration.go b/pkg/injection/namespace/initgeneration/initgeneration.go index 1364a9855f..f60da86e01 100644 --- a/pkg/injection/namespace/initgeneration/initgeneration.go +++ b/pkg/injection/namespace/initgeneration/initgeneration.go @@ -5,7 +5,7 @@ import ( "encoding/json" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" diff --git a/pkg/injection/namespace/initgeneration/initgeneration_test.go b/pkg/injection/namespace/initgeneration/initgeneration_test.go index 2b725ec176..a15998555b 100644 --- a/pkg/injection/namespace/initgeneration/initgeneration_test.go +++ b/pkg/injection/namespace/initgeneration/initgeneration_test.go @@ -9,9 +9,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" diff --git a/pkg/injection/namespace/mapper/dynakubes.go b/pkg/injection/namespace/mapper/dynakubes.go index a846a9d8ac..01f38f7e8e 100644 --- a/pkg/injection/namespace/mapper/dynakubes.go +++ b/pkg/injection/namespace/mapper/dynakubes.go @@ -3,7 +3,7 @@ package mapper import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" diff --git a/pkg/injection/namespace/mapper/dynakubes_test.go b/pkg/injection/namespace/mapper/dynakubes_test.go index 49fe3a80f1..5c0c2dce9b 100644 --- a/pkg/injection/namespace/mapper/dynakubes_test.go +++ b/pkg/injection/namespace/mapper/dynakubes_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" diff --git a/pkg/injection/namespace/mapper/mapper.go b/pkg/injection/namespace/mapper/mapper.go index f81a2dc868..0c30d64db2 100644 --- a/pkg/injection/namespace/mapper/mapper.go +++ b/pkg/injection/namespace/mapper/mapper.go @@ -4,7 +4,7 @@ import ( "context" "regexp" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" diff --git a/pkg/injection/namespace/mapper/mapper_test.go b/pkg/injection/namespace/mapper/mapper_test.go index b170c421e0..d3933a3567 100644 --- a/pkg/injection/namespace/mapper/mapper_test.go +++ b/pkg/injection/namespace/mapper/mapper_test.go @@ -3,8 +3,8 @@ package mapper import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/injection/namespace/mapper/namespaces.go b/pkg/injection/namespace/mapper/namespaces.go index 841c04fa69..f23bbd37f4 100644 --- a/pkg/injection/namespace/mapper/namespaces.go +++ b/pkg/injection/namespace/mapper/namespaces.go @@ -3,7 +3,7 @@ package mapper import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" diff --git a/pkg/injection/namespace/mapper/namespaces_test.go b/pkg/injection/namespace/mapper/namespaces_test.go index e2ee633cae..b60dbeac9b 100644 --- a/pkg/injection/namespace/mapper/namespaces_test.go +++ b/pkg/injection/namespace/mapper/namespaces_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/oci/registry/client.go b/pkg/oci/registry/client.go index a646dbf86b..d08cc1e5ba 100644 --- a/pkg/oci/registry/client.go +++ b/pkg/oci/registry/client.go @@ -8,7 +8,7 @@ import ( "net/http" "net/url" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/arch" "github.com/Dynatrace/dynatrace-operator/pkg/oci/dockerkeychain" "github.com/google/go-containerregistry/pkg/authn" diff --git a/pkg/oci/registry/client_test.go b/pkg/oci/registry/client_test.go index 8c89263232..6ca1dedea9 100644 --- a/pkg/oci/registry/client_test.go +++ b/pkg/oci/registry/client_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/util/conditions/time.go b/pkg/util/conditions/time.go index 56af881ef6..e436ae3088 100644 --- a/pkg/util/conditions/time.go +++ b/pkg/util/conditions/time.go @@ -1,7 +1,7 @@ package conditions import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/util/conditions/time_test.go b/pkg/util/conditions/time_test.go index a0d90d4bb9..34668be349 100644 --- a/pkg/util/conditions/time_test.go +++ b/pkg/util/conditions/time_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "github.com/pkg/errors" "github.com/stretchr/testify/assert" diff --git a/pkg/util/kubeobjects/activegate/capability.go b/pkg/util/kubeobjects/activegate/capability.go index 554a755ce5..caa529be4f 100644 --- a/pkg/util/kubeobjects/activegate/capability.go +++ b/pkg/util/kubeobjects/activegate/capability.go @@ -1,8 +1,8 @@ package activegate import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" ) func SwitchCapability(dk *dynakube.DynaKube, capability activegate.Capability, wantEnabled bool) { diff --git a/pkg/webhook/mutation/namespace/webhook_test.go b/pkg/webhook/mutation/namespace/webhook_test.go index d4271c29c2..7038919ef1 100644 --- a/pkg/webhook/mutation/namespace/webhook_test.go +++ b/pkg/webhook/mutation/namespace/webhook_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" jsonpatch "github.com/evanphx/json-patch" "github.com/stretchr/testify/assert" diff --git a/pkg/webhook/mutation/pod/events.go b/pkg/webhook/mutation/pod/events.go index 72823d4b5f..176ee9dc79 100644 --- a/pkg/webhook/mutation/pod/events.go +++ b/pkg/webhook/mutation/pod/events.go @@ -1,7 +1,7 @@ package pod import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" diff --git a/pkg/webhook/mutation/pod/init_container.go b/pkg/webhook/mutation/pod/init_container.go index e88f61793c..f519ca7fb6 100644 --- a/pkg/webhook/mutation/pod/init_container.go +++ b/pkg/webhook/mutation/pod/init_container.go @@ -4,7 +4,7 @@ import ( "encoding/json" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" diff --git a/pkg/webhook/mutation/pod/init_container_test.go b/pkg/webhook/mutation/pod/init_container_test.go index f58424c55b..91150241ae 100644 --- a/pkg/webhook/mutation/pod/init_container_test.go +++ b/pkg/webhook/mutation/pod/init_container_test.go @@ -3,8 +3,8 @@ package pod import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" diff --git a/pkg/webhook/mutation/pod/metadata/annotations.go b/pkg/webhook/mutation/pod/metadata/annotations.go index 6b34b4403a..27c48c22f1 100644 --- a/pkg/webhook/mutation/pod/metadata/annotations.go +++ b/pkg/webhook/mutation/pod/metadata/annotations.go @@ -4,7 +4,7 @@ import ( "encoding/json" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" corev1 "k8s.io/api/core/v1" diff --git a/pkg/webhook/mutation/pod/metadata/annotations_test.go b/pkg/webhook/mutation/pod/metadata/annotations_test.go index 9ee377afc7..b60afa892c 100644 --- a/pkg/webhook/mutation/pod/metadata/annotations_test.go +++ b/pkg/webhook/mutation/pod/metadata/annotations_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/stretchr/testify/assert" diff --git a/pkg/webhook/mutation/pod/metadata/mutator_test.go b/pkg/webhook/mutation/pod/metadata/mutator_test.go index 20b04cab12..3b01433deb 100644 --- a/pkg/webhook/mutation/pod/metadata/mutator_test.go +++ b/pkg/webhook/mutation/pod/metadata/mutator_test.go @@ -6,9 +6,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" diff --git a/pkg/webhook/mutation/pod/oneagent/annotations.go b/pkg/webhook/mutation/pod/oneagent/annotations.go index 2c29e3672b..99316eb693 100644 --- a/pkg/webhook/mutation/pod/oneagent/annotations.go +++ b/pkg/webhook/mutation/pod/oneagent/annotations.go @@ -3,7 +3,7 @@ package oneagent import ( "net/url" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" corev1 "k8s.io/api/core/v1" diff --git a/pkg/webhook/mutation/pod/oneagent/containers_test.go b/pkg/webhook/mutation/pod/oneagent/containers_test.go index 324a8240d0..f4988db78f 100644 --- a/pkg/webhook/mutation/pod/oneagent/containers_test.go +++ b/pkg/webhook/mutation/pod/oneagent/containers_test.go @@ -4,7 +4,7 @@ import ( "maps" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/webhook/mutation/pod/oneagent/env.go b/pkg/webhook/mutation/pod/oneagent/env.go index 9bf9a32ec9..17a99e56e2 100644 --- a/pkg/webhook/mutation/pod/oneagent/env.go +++ b/pkg/webhook/mutation/pod/oneagent/env.go @@ -4,7 +4,7 @@ import ( "path/filepath" "strings" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" diff --git a/pkg/webhook/mutation/pod/oneagent/env_test.go b/pkg/webhook/mutation/pod/oneagent/env_test.go index d10c0c66e1..c6850be1c7 100644 --- a/pkg/webhook/mutation/pod/oneagent/env_test.go +++ b/pkg/webhook/mutation/pod/oneagent/env_test.go @@ -3,8 +3,8 @@ package oneagent import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/stretchr/testify/assert" diff --git a/pkg/webhook/mutation/pod/oneagent/mutator_test.go b/pkg/webhook/mutation/pod/oneagent/mutator_test.go index bb89ca7be8..c58cd9555f 100644 --- a/pkg/webhook/mutation/pod/oneagent/mutator_test.go +++ b/pkg/webhook/mutation/pod/oneagent/mutator_test.go @@ -8,9 +8,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" diff --git a/pkg/webhook/mutation/pod/oneagent/volumes.go b/pkg/webhook/mutation/pod/oneagent/volumes.go index dbe60aca44..aec44f69c1 100644 --- a/pkg/webhook/mutation/pod/oneagent/volumes.go +++ b/pkg/webhook/mutation/pod/oneagent/volumes.go @@ -4,7 +4,7 @@ import ( "fmt" "path/filepath" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csivolumes "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver/volumes" diff --git a/pkg/webhook/mutation/pod/oneagent/volumes_test.go b/pkg/webhook/mutation/pod/oneagent/volumes_test.go index 0cd42a4912..e29e76756a 100644 --- a/pkg/webhook/mutation/pod/oneagent/volumes_test.go +++ b/pkg/webhook/mutation/pod/oneagent/volumes_test.go @@ -4,8 +4,8 @@ import ( "path/filepath" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/volumes" diff --git a/pkg/webhook/mutation/pod/request.go b/pkg/webhook/mutation/pod/request.go index f8dd2f541f..45bf3b9806 100644 --- a/pkg/webhook/mutation/pod/request.go +++ b/pkg/webhook/mutation/pod/request.go @@ -3,7 +3,7 @@ package pod import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" diff --git a/pkg/webhook/mutation/pod/request_test.go b/pkg/webhook/mutation/pod/request_test.go index c8704c63fb..b7c7ed29a9 100644 --- a/pkg/webhook/mutation/pod/request_test.go +++ b/pkg/webhook/mutation/pod/request_test.go @@ -5,7 +5,7 @@ import ( "encoding/json" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/pkg/webhook/mutation/pod/webhook_test.go b/pkg/webhook/mutation/pod/webhook_test.go index 59fde68d04..4acd4f8989 100644 --- a/pkg/webhook/mutation/pod/webhook_test.go +++ b/pkg/webhook/mutation/pod/webhook_test.go @@ -7,8 +7,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" diff --git a/pkg/webhook/mutator.go b/pkg/webhook/mutator.go index 0cffc2dc32..abf8b3a3f1 100644 --- a/pkg/webhook/mutator.go +++ b/pkg/webhook/mutator.go @@ -3,7 +3,7 @@ package webhook import ( "context" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/pod" corev1 "k8s.io/api/core/v1" ) diff --git a/test/features/activegate/activegate.go b/test/features/activegate/activegate.go index 54ca51fe0f..4fbbe3066c 100644 --- a/test/features/activegate/activegate.go +++ b/test/features/activegate/activegate.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/activegate" diff --git a/test/features/activegate/curl.go b/test/features/activegate/curl.go index 7eedb99d4e..a8e16fd957 100644 --- a/test/features/activegate/curl.go +++ b/test/features/activegate/curl.go @@ -7,7 +7,7 @@ import ( "fmt" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/test/helpers/curl" diff --git a/test/features/applicationmonitoring/label_version_detection.go b/test/features/applicationmonitoring/label_version_detection.go index 7d3898c426..19ea969613 100644 --- a/test/features/applicationmonitoring/label_version_detection.go +++ b/test/features/applicationmonitoring/label_version_detection.go @@ -8,8 +8,8 @@ import ( "strings" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/namespace" diff --git a/test/features/applicationmonitoring/metadata_enrichment.go b/test/features/applicationmonitoring/metadata_enrichment.go index 9f7237939e..b07373a6db 100644 --- a/test/features/applicationmonitoring/metadata_enrichment.go +++ b/test/features/applicationmonitoring/metadata_enrichment.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" maputil "github.com/Dynatrace/dynatrace-operator/pkg/util/map" diff --git a/test/features/applicationmonitoring/read_only_csi_volume.go b/test/features/applicationmonitoring/read_only_csi_volume.go index 7473b6c991..6dc0f11161 100644 --- a/test/features/applicationmonitoring/read_only_csi_volume.go +++ b/test/features/applicationmonitoring/read_only_csi_volume.go @@ -7,8 +7,8 @@ import ( "fmt" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/codemodules" diff --git a/test/features/applicationmonitoring/without_csi.go b/test/features/applicationmonitoring/without_csi.go index 8129e8bd2c..5b1e0d4706 100644 --- a/test/features/applicationmonitoring/without_csi.go +++ b/test/features/applicationmonitoring/without_csi.go @@ -6,7 +6,7 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" diff --git a/test/features/classic/classic.go b/test/features/classic/classic.go index 3b467cd39d..39cad81f04 100644 --- a/test/features/classic/classic.go +++ b/test/features/classic/classic.go @@ -5,7 +5,7 @@ package classic import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" diff --git a/test/features/classic/switch_modes/switch_modes.go b/test/features/classic/switch_modes/switch_modes.go index 90b2b7c080..d2f5562258 100644 --- a/test/features/classic/switch_modes/switch_modes.go +++ b/test/features/classic/switch_modes/switch_modes.go @@ -5,7 +5,7 @@ package switch_modes import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" "github.com/Dynatrace/dynatrace-operator/test/helpers" diff --git a/test/features/cloudnative/codemodules/codemodules.go b/test/features/cloudnative/codemodules/codemodules.go index 1db3d830bc..1e2d4fdf21 100644 --- a/test/features/cloudnative/codemodules/codemodules.go +++ b/test/features/cloudnative/codemodules/codemodules.go @@ -14,8 +14,8 @@ import ( "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" diff --git a/test/features/cloudnative/container.go b/test/features/cloudnative/container.go index dd4b5b2d2c..57f3f84ea0 100644 --- a/test/features/cloudnative/container.go +++ b/test/features/cloudnative/container.go @@ -5,7 +5,7 @@ package cloudnative import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/activegate" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/pod" "github.com/Dynatrace/dynatrace-operator/test/helpers/sample" diff --git a/test/features/cloudnative/disabled_auto_injection/disabled_auto_injection.go b/test/features/cloudnative/disabled_auto_injection/disabled_auto_injection.go index 3b6bbd2e82..79b01c9217 100644 --- a/test/features/cloudnative/disabled_auto_injection/disabled_auto_injection.go +++ b/test/features/cloudnative/disabled_auto_injection/disabled_auto_injection.go @@ -5,7 +5,7 @@ package disabled_auto_injection import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" diff --git a/test/features/cloudnative/init_containers.go b/test/features/cloudnative/init_containers.go index a835330eb3..68a3abb96d 100644 --- a/test/features/cloudnative/init_containers.go +++ b/test/features/cloudnative/init_containers.go @@ -6,7 +6,7 @@ import ( "context" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/pod" "github.com/Dynatrace/dynatrace-operator/test/helpers/logs" diff --git a/test/features/cloudnative/switch_modes/switch_modes.go b/test/features/cloudnative/switch_modes/switch_modes.go index 7a894e7b11..73e0256686 100644 --- a/test/features/cloudnative/switch_modes/switch_modes.go +++ b/test/features/cloudnative/switch_modes/switch_modes.go @@ -5,7 +5,7 @@ package switch_modes import ( "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" diff --git a/test/features/cloudnative/upgrade/upgrade.go b/test/features/cloudnative/upgrade/upgrade.go index 1ee4ccc3f7..8dc4e881dc 100644 --- a/test/features/cloudnative/upgrade/upgrade.go +++ b/test/features/cloudnative/upgrade/upgrade.go @@ -5,7 +5,7 @@ package upgrade import ( "testing" - dynakubev1beta2 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta2/dynakube" //nolint:staticcheck + dynakubev1beta3 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" @@ -31,7 +31,7 @@ func Feature(t *testing.T) features.Feature { ) builder.Assess("create sample namespace", sampleApp.InstallNamespace()) - previousVersionDynakube := &dynakubev1beta2.DynaKube{} + previousVersionDynakube := &dynakubev1beta3.DynaKube{} previousVersionDynakube.ConvertFrom(&testDynakube) dynakube.InstallPreviousVersion(builder, helpers.LevelAssess, &secretConfig, *previousVersionDynakube) diff --git a/test/features/extensions/extensions.go b/test/features/extensions/extensions.go index adb14d63af..6cb602b612 100644 --- a/test/features/extensions/extensions.go +++ b/test/features/extensions/extensions.go @@ -8,7 +8,7 @@ import ( "path" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/test/features/consts" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/activegate" diff --git a/test/features/support_archive/files.go b/test/features/support_archive/files.go index 50821f8cc7..369546c111 100644 --- a/test/features/support_archive/files.go +++ b/test/features/support_archive/files.go @@ -10,7 +10,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/cmd/support_archive" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/functional" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/csi" diff --git a/test/features/support_archive/support_archive.go b/test/features/support_archive/support_archive.go index 4c2ad50a5f..af498ff9da 100644 --- a/test/features/support_archive/support_archive.go +++ b/test/features/support_archive/support_archive.go @@ -13,8 +13,8 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" agconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/functional" "github.com/Dynatrace/dynatrace-operator/test/features/consts" diff --git a/test/helpers/components/activegate/installation.go b/test/helpers/components/activegate/installation.go index c34226e711..50bd8f6110 100644 --- a/test/helpers/components/activegate/installation.go +++ b/test/helpers/components/activegate/installation.go @@ -7,7 +7,7 @@ import ( "fmt" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/statefulset" "github.com/Dynatrace/dynatrace-operator/test/helpers/logs" diff --git a/test/helpers/components/codemodules/codemodules.go b/test/helpers/components/codemodules/codemodules.go index c593c30720..902eae0aec 100644 --- a/test/helpers/components/codemodules/codemodules.go +++ b/test/helpers/components/codemodules/codemodules.go @@ -7,7 +7,7 @@ import ( "path/filepath" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/csi" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/daemonset" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/pod" diff --git a/test/helpers/components/dynakube/dynakube.go b/test/helpers/components/dynakube/dynakube.go index d03f878991..6d5137a802 100644 --- a/test/helpers/components/dynakube/dynakube.go +++ b/test/helpers/components/dynakube/dynakube.go @@ -9,8 +9,8 @@ import ( "time" "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - prevDynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta2/dynakube" //nolint:staticcheck - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + prevDynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" "github.com/stretchr/testify/require" @@ -62,8 +62,8 @@ func CreatePreviousVersion(builder *features.FeatureBuilder, level features.Leve } func VerifyStartupPreviousVersion(builder *features.FeatureBuilder, level features.Level, prevDk prevDynakube.DynaKube) { - if prevDk.NeedsOneAgent() { - builder.WithStep("oneagent started", level, oneagent.WaitForDaemonset(prevDk.OneAgentDaemonsetName(), prevDk.Namespace)) + if prevDk.OneAgent().IsDaemonsetRequired() { + builder.WithStep("oneagent started", level, oneagent.WaitForDaemonset(prevDk.OneAgent().GetDaemonsetName(), prevDk.Namespace)) } builder.WithStep( fmt.Sprintf("'%s' dynakube phase changes to 'Running'", prevDk.Name), diff --git a/test/helpers/components/dynakube/options.go b/test/helpers/components/dynakube/options.go index 9f62a73cc0..a6b51d74f5 100644 --- a/test/helpers/components/dynakube/options.go +++ b/test/helpers/components/dynakube/options.go @@ -5,9 +5,9 @@ package dynakube import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/image" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" diff --git a/test/helpers/components/oneagent/daemonset.go b/test/helpers/components/oneagent/daemonset.go index bf0d3cb0f4..efa48a56dc 100644 --- a/test/helpers/components/oneagent/daemonset.go +++ b/test/helpers/components/oneagent/daemonset.go @@ -5,7 +5,7 @@ package oneagent import ( "context" - dynakubev1beta3 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/daemonset" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/pod" @@ -23,7 +23,7 @@ func WaitForDaemonSetPodsDeletion(dsName, namespace string) features.Func { return pod.WaitForPodsDeletionWithOwner(dsName, namespace) } -func Get(ctx context.Context, resource *resources.Resources, dk dynakubev1beta3.DynaKube) (appsv1.DaemonSet, error) { +func Get(ctx context.Context, resource *resources.Resources, dk dynakube.DynaKube) (appsv1.DaemonSet, error) { return daemonset.NewQuery(ctx, resource, client.ObjectKey{ Name: dk.OneAgent().GetDaemonsetName(), Namespace: dk.Namespace, diff --git a/test/helpers/components/oneagent/uninstall.go b/test/helpers/components/oneagent/uninstall.go index 5092da8f17..45b25a2a3b 100644 --- a/test/helpers/components/oneagent/uninstall.go +++ b/test/helpers/components/oneagent/uninstall.go @@ -8,7 +8,7 @@ import ( "path" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/daemonset" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/manifests" diff --git a/test/helpers/curl/curl.go b/test/helpers/curl/curl.go index eada3b552b..d8f64f2fd6 100644 --- a/test/helpers/curl/curl.go +++ b/test/helpers/curl/curl.go @@ -7,7 +7,7 @@ import ( "io" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" diff --git a/test/helpers/istio/install.go b/test/helpers/istio/install.go index faeb9768e9..ccb74420f5 100644 --- a/test/helpers/istio/install.go +++ b/test/helpers/istio/install.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/istio" "github.com/Dynatrace/dynatrace-operator/test/helpers/platform" diff --git a/test/helpers/proxy/proxy.go b/test/helpers/proxy/proxy.go index 5d790fdecd..4428b80ce2 100644 --- a/test/helpers/proxy/proxy.go +++ b/test/helpers/proxy/proxy.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/common" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" diff --git a/test/helpers/scheme.go b/test/helpers/scheme.go index 69b3f85b74..c7acc87f92 100644 --- a/test/helpers/scheme.go +++ b/test/helpers/scheme.go @@ -15,11 +15,17 @@ import ( _ "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta2/dynakube" //nolint:staticcheck "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3" _ "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4" + _ "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "sigs.k8s.io/e2e-framework/pkg/envconf" ) func SetScheme(ctx context.Context, envConfig *envconf.Config) (context.Context, error) { - err := v1beta3.AddToScheme(envConfig.Client().Resources().GetScheme()) + err := v1beta4.AddToScheme(envConfig.Client().Resources().GetScheme()) + if err != nil { + return ctx, err + } + err = v1beta3.AddToScheme(envConfig.Client().Resources().GetScheme()) if err != nil { return ctx, err } diff --git a/test/mocks/pkg/clients/dynatrace/client.go b/test/mocks/pkg/clients/dynatrace/client.go index f251e81665..16d1b1b69a 100644 --- a/test/mocks/pkg/clients/dynatrace/client.go +++ b/test/mocks/pkg/clients/dynatrace/client.go @@ -8,7 +8,7 @@ import ( dynatrace "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" - logmonitoring "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/logmonitoring" + logmonitoring "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" mock "github.com/stretchr/testify/mock" ) diff --git a/test/mocks/pkg/controllers/dynakube/dynatraceclient/builder.go b/test/mocks/pkg/controllers/dynakube/dynatraceclient/builder.go index b14bff93b8..7956a95671 100644 --- a/test/mocks/pkg/controllers/dynakube/dynatraceclient/builder.go +++ b/test/mocks/pkg/controllers/dynakube/dynatraceclient/builder.go @@ -5,7 +5,7 @@ package mocks import ( context "context" - dynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + dynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dynatrace "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dynatraceclient "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/dynatraceclient" diff --git a/test/mocks/pkg/controllers/dynakube/istio/reconciler.go b/test/mocks/pkg/controllers/dynakube/istio/reconciler.go index 18d001080c..32b6069701 100644 --- a/test/mocks/pkg/controllers/dynakube/istio/reconciler.go +++ b/test/mocks/pkg/controllers/dynakube/istio/reconciler.go @@ -5,7 +5,7 @@ package mocks import ( context "context" - dynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + dynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" mock "github.com/stretchr/testify/mock" ) diff --git a/test/mocks/pkg/controllers/dynakube/version/reconciler.go b/test/mocks/pkg/controllers/dynakube/version/reconciler.go index d3ab34f29d..beb55e5707 100644 --- a/test/mocks/pkg/controllers/dynakube/version/reconciler.go +++ b/test/mocks/pkg/controllers/dynakube/version/reconciler.go @@ -5,7 +5,7 @@ package mocks import ( context "context" - dynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + dynakube "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" mock "github.com/stretchr/testify/mock" ) diff --git a/test/scenarios/release/release_test.go b/test/scenarios/release/release_test.go index 4b74884363..bc89973141 100644 --- a/test/scenarios/release/release_test.go +++ b/test/scenarios/release/release_test.go @@ -20,7 +20,7 @@ var ( cfg *envconf.Config ) -const releaseTag = "1.3.2" +const releaseTag = "1.4.1" func TestMain(m *testing.M) { cfg = environment.GetStandardKubeClusterEnvConfig() From 3932bbb747cf688f7e523ce94769a3ab57ad0926 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 15:12:40 +0100 Subject: [PATCH 302/426] chore(deps): update module github.com/golangci/golangci-lint to v1.64.7 (main) (#4578) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Andrii Soldatenko --- .github/workflows/ci.yaml | 2 +- .golangci.yml | 5 +++++ hack/make/prerequisites.mk | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 16f45c4eef..e8a56fc939 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -89,7 +89,7 @@ jobs: uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0 with: # renovate depName=github.com/golangci/golangci-lint - version: v1.64.6 + version: v1.64.7 args: --build-tags e2e --timeout 300s --out-${NO_FUTURE}format colored-line-number - name: Run deadcode id: deadcode diff --git a/.golangci.yml b/.golangci.yml index f640ff5373..2b25bac02c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -121,6 +121,11 @@ linters-settings: - "istio.io" - "k8s.io" - "sigs.k8s.io" + - "golang.org" + - "go.opentelemetry.io" + - "go.uber.org" + - "gopkg.in" + - "google.golang.org" # Approved packages. - "github.com/mattn/go-sqlite3" diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index f48ac66709..8ca31e740e 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -3,7 +3,7 @@ kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.2 # renovate depName=github.com/golangci/golangci-lint -golang_ci_cmd_version=v1.64.6 +golang_ci_cmd_version=v1.64.7 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools From 31f4cb83eb60a715144e663273b9db23d92bdcb1 Mon Sep 17 00:00:00 2001 From: Olivier Karasangabo Date: Wed, 12 Mar 2025 15:48:21 +0100 Subject: [PATCH 303/426] Store k8s events from the operator namespace in the support archive (#4533) --- cmd/support_archive/builder.go | 5 +++++ cmd/support_archive/resource_query.go | 16 ++++++++++++++++ cmd/support_archive/resource_query_test.go | 2 +- cmd/support_archive/resources_test.go | 2 +- test/features/support_archive/files.go | 19 +++++++++++++++++++ test/helpers/kubeobjects/event/list.go | 20 ++++++++++++++++++++ 6 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 test/helpers/kubeobjects/event/list.go diff --git a/cmd/support_archive/builder.go b/cmd/support_archive/builder.go index d505df8453..4678a28087 100644 --- a/cmd/support_archive/builder.go +++ b/cmd/support_archive/builder.go @@ -3,6 +3,7 @@ package support_archive import ( "bytes" "context" + "fmt" "io" "os" "time" @@ -36,7 +37,9 @@ const ( loadsimFileSizeFlagName = "loadsim-file-size" loadsimFilesFlagName = "loadsim-files" collectManagedLogsFlagName = "managed-logs" + numEventsFlagName = "num-events" defaultSimFileSize = 10 + defaultNumEvents = 300 ) const ( @@ -52,6 +55,7 @@ var ( loadsimFileSizeFlagValue int collectManagedLogsFlagValue bool delayFlagValue int + numEventsFlagValue int ) type CommandBuilder struct { @@ -90,6 +94,7 @@ func addFlags(cmd *cobra.Command) { cmd.PersistentFlags().IntVar(&loadsimFilesFlagValue, loadsimFilesFlagName, 0, "Number of simulated log files (default 0)") cmd.PersistentFlags().BoolVar(&collectManagedLogsFlagValue, collectManagedLogsFlagName, true, "Add logs from rolled out pods to the support archive.") cmd.PersistentFlags().IntVar(&delayFlagValue, delayFlagName, 0, "Delay start of support-archive collection. Useful for standalone execution with 'kubectl run'") + cmd.PersistentFlags().IntVar(&numEventsFlagValue, numEventsFlagName, defaultNumEvents, fmt.Sprintf("Number of events to be fetched (default %d)", defaultNumEvents)) } func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { diff --git a/cmd/support_archive/resource_query.go b/cmd/support_archive/resource_query.go index 6413ba4236..1a2be37e19 100644 --- a/cmd/support_archive/resource_query.go +++ b/cmd/support_archive/resource_query.go @@ -34,6 +34,7 @@ func getQueries(namespace string, appName string) []resourceQuery { allQueries = append(allQueries, getComponentsQueryGroup(namespace, appName, labels.AppManagedByLabel).getQueries()...) allQueries = append(allQueries, getCustomResourcesQueryGroup(namespace).getQueries()...) allQueries = append(allQueries, getConfigMapQueryGroup(namespace).getQueries()...) + allQueries = append(allQueries, getEventsQueryGroup(namespace).getQueries()...) return allQueries } @@ -106,6 +107,21 @@ func getConfigMapQueryGroup(namespace string) resourceQueryGroup { } } +func getEventsQueryGroup(namespace string) resourceQueryGroup { + return resourceQueryGroup{ + resources: []schema.GroupVersionKind{ + toGroupVersionKind(corev1.SchemeGroupVersion, corev1.Event{}), + }, + filters: []client.ListOption{ + client.InNamespace(namespace), + client.Limit(numEventsFlagValue), + &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector("type", corev1.EventTypeWarning), + }, + }, + } +} + func toGroupVersionKind(groupVersion schema.GroupVersion, resource any) schema.GroupVersionKind { typ := reflect.TypeOf(resource) typ.Name() diff --git a/cmd/support_archive/resource_query_test.go b/cmd/support_archive/resource_query_test.go index 27c6049227..a5c75edc17 100644 --- a/cmd/support_archive/resource_query_test.go +++ b/cmd/support_archive/resource_query_test.go @@ -10,7 +10,7 @@ const namespace = "dynatrace" func TestObjectQuerySyntax(t *testing.T) { queries := getQueries(namespace, defaultOperatorAppName) - assert.Len(t, queries, 17) + assert.Len(t, queries, 18) for _, query := range queries { assert.NotEmpty(t, query.groupVersionKind.Kind) diff --git a/cmd/support_archive/resources_test.go b/cmd/support_archive/resources_test.go index 7846385b46..5d45d31a42 100644 --- a/cmd/support_archive/resources_test.go +++ b/cmd/support_archive/resources_test.go @@ -199,7 +199,7 @@ func TestManifestCollector_PartialCollectionOnMissingResources(t *testing.T) { log := newSupportArchiveLogger(&logBuffer) queries := getQueries(testOperatorNamespace, defaultOperatorAppName) - require.Len(t, queries, 17) + require.Len(t, queries, 18) clt := fake.NewClientWithIndex( &appsv1.StatefulSet{ diff --git a/test/features/support_archive/files.go b/test/features/support_archive/files.go index 369546c111..7a993c7991 100644 --- a/test/features/support_archive/files.go +++ b/test/features/support_archive/files.go @@ -17,6 +17,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/test/helpers/components/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" e2ewebhook "github.com/Dynatrace/dynatrace-operator/test/helpers/components/webhook" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/event" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/pod" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/replicaset" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/service" @@ -71,6 +72,7 @@ func (r requiredFiles) collectRequiredFiles() []string { requiredFiles = append(requiredFiles, r.getRequiredWebhookConfigurationFiles()...) requiredFiles = append(requiredFiles, r.getRequiredCRDFiles()...) requiredFiles = append(requiredFiles, r.getRequiredConfigMapFiles()...) + requiredFiles = append(requiredFiles, r.getRequiredEventFiles()...) return requiredFiles } @@ -348,3 +350,20 @@ func (r requiredFiles) getRequiredConfigMapFiles() []string { return requiredFiles } + +func (r requiredFiles) getRequiredEventFiles() []string { + events := event.List(r.t, r.ctx, r.resources, r.dk.Namespace) + requiredFiles := make([]string, 0) + + for _, requiredEvent := range events.Items { + requiredFiles = append(requiredFiles, + fmt.Sprintf("%s/%s/%s/%s%s", + support_archive.ManifestsDirectoryName, + requiredEvent.Namespace, + "event", + requiredEvent.Name, + support_archive.ManifestsFileExtension)) + } + + return requiredFiles +} diff --git a/test/helpers/kubeobjects/event/list.go b/test/helpers/kubeobjects/event/list.go new file mode 100644 index 0000000000..22152ef3ab --- /dev/null +++ b/test/helpers/kubeobjects/event/list.go @@ -0,0 +1,20 @@ +//go:build e2e + +package event + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/e2e-framework/klient/k8s/resources" +) + +func List(t *testing.T, ctx context.Context, resource *resources.Resources, namespace string) corev1.EventList { + var events corev1.EventList + + require.NoError(t, resource.WithNamespace(namespace).List(ctx, &events)) + + return events +} From d9dda35720fbe04a2063804e724821dd578f72a7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 23:11:47 +0000 Subject: [PATCH 304/426] chore(deps): update golangci/golangci-lint-action action to v6.5.1 (main) (#4586) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e8a56fc939..ec9fd6b722 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,7 +86,7 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint - uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0 + uses: golangci/golangci-lint-action@4696ba8babb6127d732c3c6dde519db15edab9ea # v6.5.1 with: # renovate depName=github.com/golangci/golangci-lint version: v1.64.7 From 8444988128456ccf2864796a1fa33af6d1e1ecc2 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Thu, 13 Mar 2025 08:49:27 +0100 Subject: [PATCH 305/426] Update securityContext for node config collector container (#4584) --- pkg/controllers/dynakube/kspm/daemonset/container.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/controllers/dynakube/kspm/daemonset/container.go b/pkg/controllers/dynakube/kspm/daemonset/container.go index ef072c701a..f2c05546e9 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/container.go +++ b/pkg/controllers/dynakube/kspm/daemonset/container.go @@ -12,7 +12,7 @@ const ( defaultImageTag = "latest" containerName = "node-config-collector" - runAs int64 = 0 + runAs int64 = 65532 ) func getContainer(dk dynakube.DynaKube, tenantUUID string) corev1.Container { @@ -37,9 +37,9 @@ func getSecurityContext() corev1.SecurityContext { AllowPrivilegeEscalation: ptr.To(false), RunAsUser: ptr.To(runAs), RunAsGroup: ptr.To(runAs), - RunAsNonRoot: ptr.To(false), + RunAsNonRoot: ptr.To(true), ReadOnlyRootFilesystem: ptr.To(true), - Capabilities: &corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}, + Capabilities: &corev1.Capabilities{Add: []corev1.Capability{"DAC_OVERRIDE"}, Drop: []corev1.Capability{"ALL"}}, } return securityContext From 6b47038a642b73a3cd19cb9ac4145a3a086b82e9 Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:26:23 +0100 Subject: [PATCH 306/426] Use `.spec.telemetryIngest.serviceName` as name for telemetry ingest service (#4570) --- .../v1beta4/dynakube/telemetryingest/props.go | 19 ++- .../validation/dynakube/telemetryservice.go | 62 +++++++ .../dynakube/telemetryservice_test.go | 154 ++++++++++++++++++ pkg/api/validation/dynakube/validation.go | 2 + .../dynakube/otelc/service/reconciler.go | 57 ++++--- .../dynakube/otelc/service/reconciler_test.go | 114 +++++++++---- 6 files changed, 349 insertions(+), 59 deletions(-) diff --git a/pkg/api/v1beta4/dynakube/telemetryingest/props.go b/pkg/api/v1beta4/dynakube/telemetryingest/props.go index dd95cb9601..087865bbdc 100644 --- a/pkg/api/v1beta4/dynakube/telemetryingest/props.go +++ b/pkg/api/v1beta4/dynakube/telemetryingest/props.go @@ -3,7 +3,7 @@ package telemetryingest import "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" const ( - nameSuffix = "-telemetry-ingest" + ServiceNameSuffix = "-telemetry-ingest" ) func (spec *Spec) GetProtocols() otelcgen.Protocols { @@ -27,8 +27,21 @@ func (ts *TelemetryIngest) SetName(name string) { ts.name = name } -func (ts *TelemetryIngest) GetName() string { - return ts.name + nameSuffix +func (ts *TelemetryIngest) GetDefaultServiceName() string { + return ts.name + ServiceNameSuffix +} + +func (ts *TelemetryIngest) GetServiceName() string { + if ts.Spec == nil { + return ts.GetDefaultServiceName() + } + + serviceName := ts.Spec.ServiceName + if serviceName == "" { + serviceName = ts.GetDefaultServiceName() + } + + return serviceName } func (ts *TelemetryIngest) IsEnabled() bool { diff --git a/pkg/api/validation/dynakube/telemetryservice.go b/pkg/api/validation/dynakube/telemetryservice.go index bec02607f8..03656a69aa 100644 --- a/pkg/api/validation/dynakube/telemetryservice.go +++ b/pkg/api/validation/dynakube/telemetryservice.go @@ -7,8 +7,12 @@ import ( "strings" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + agconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" "k8s.io/apimachinery/pkg/util/validation" + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( @@ -18,6 +22,8 @@ const ( errorTelemetryIngestNoDNS1053Label = `DynaKube's specification enables the TelemetryIngest feature, the telemetry service name violates DNS-1035. [The length limit for the name is %d. Additionally a DNS-1035 name must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')] ` + errorTelemetryIngestServiceNameInUse = `The DynaKube's specification enables the TelemetryIngest feature, the telemetry service name is already used by other Dynakube.` + errorTelemetryIngestForbiddenServiceName = `The DynaKube's specification enables the TelemetryIngest feature, the telemetry service name is incorrect because of forbidden suffix.` ) func emptyTelemetryIngestProtocolsList(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { @@ -109,3 +115,59 @@ func invalidTelemetryIngestName(_ context.Context, _ *Validator, dk *dynakube.Dy func invalidTelemetryIngestNameErrorMessage() string { return fmt.Sprintf(errorTelemetryIngestNoDNS1053Label, validation.DNS1035LabelMaxLength) } + +func conflictingTelemetryIngestServiceNames(ctx context.Context, dv *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryIngest().IsEnabled() { + return "" + } + + dkList := &dynakube.DynaKubeList{} + if err := dv.apiReader.List(ctx, dkList, &client.ListOptions{Namespace: dk.Namespace}); err != nil { + log.Info("error occurred while listing dynakubes", "err", err.Error()) + + return "" + } + + dkServiceName := dk.TelemetryIngest().GetServiceName() + + for _, otherDk := range dkList.Items { + if otherDk.Name == dk.Name { + continue + } + + if !otherDk.TelemetryIngest().IsEnabled() { + continue + } + + otherDkServiceName := otherDk.TelemetryIngest().GetServiceName() + + if otherDkServiceName == dkServiceName { + log.Info(errorTelemetryIngestServiceNameInUse, "other dynakube name", otherDk.Name, "other telemetry service name", otherDkServiceName, "namespace", otherDk.Namespace) + + return fmt.Sprintf("%s Conflicting Dynakube: %s. Conflicting telemetry service name: %s", errorTelemetryIngestServiceNameInUse, otherDk.Name, otherDkServiceName) + } + } + + return "" +} + +func forbiddenTelemetryIngestServiceNameSuffix(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { + if !dk.TelemetryIngest().IsEnabled() { + return "" + } + + if dk.TelemetryIngest().ServiceName == "" { + return "" + } + + if strings.HasSuffix(dk.TelemetryIngest().ServiceName, consts.ExtensionsControllerSuffix) || + strings.HasSuffix(dk.TelemetryIngest().ServiceName, telemetryingest.ServiceNameSuffix) || + strings.HasSuffix(dk.TelemetryIngest().ServiceName, "-"+agconsts.MultiActiveGateName) || + strings.HasSuffix(dk.TelemetryIngest().ServiceName, "-webhook") { + log.Info(errorTelemetryIngestForbiddenServiceName, "telemetry service name", dk.TelemetryIngest().ServiceName) + + return fmt.Sprintf("%s Telemetry service name: %s", errorTelemetryIngestForbiddenServiceName, dk.TelemetryIngest().ServiceName) + } + + return "" +} diff --git a/pkg/api/validation/dynakube/telemetryservice_test.go b/pkg/api/validation/dynakube/telemetryservice_test.go index 383d7530af..db4a04009f 100644 --- a/pkg/api/validation/dynakube/telemetryservice_test.go +++ b/pkg/api/validation/dynakube/telemetryservice_test.go @@ -5,9 +5,23 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + agconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const ( + testOtherName = "test-other-name" + testServiceName = "test-service-name" + testOtherServiceName = "test-other-service-name" +) + +var otherDynakubeObjectMeta = metav1.ObjectMeta{ + Name: testOtherName, + Namespace: testNamespace, +} + func TestTelemetryIngestProtocols(t *testing.T) { t.Run(`no list of protocols`, func(t *testing.T) { assertAllowed(t, @@ -159,3 +173,143 @@ func TestTelemetryIngestProtocols(t *testing.T) { }) }) } + +func TestConflictingServiceNames(t *testing.T) { + t.Run(`no conflicts`, func(t *testing.T) { + assertAllowed(t, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{}, + }, + }, + &dynakube.DynaKube{ + ObjectMeta: otherDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{}, + }, + }) + }) + + t.Run(`custom service name vs custom service name`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryIngestServiceNameInUse}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{ + ServiceName: testServiceName, + }, + }, + }, + &dynakube.DynaKube{ + ObjectMeta: otherDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{ + ServiceName: testServiceName, + }, + }, + }) + }) + + t.Run(`custom service name vs default service name`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryIngestServiceNameInUse}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{ + ServiceName: testOtherName + "-telemetry-ingest", + }, + }, + }, + &dynakube.DynaKube{ + ObjectMeta: otherDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{}, + }, + }) + }) + + t.Run(`default service name vs custom service name`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryIngestServiceNameInUse}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{}, + }, + }, + &dynakube.DynaKube{ + ObjectMeta: otherDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{ + ServiceName: testName + "-telemetry-ingest", + }, + }, + }) + }) +} + +func TestForbiddenSuffix(t *testing.T) { + t.Run(`activegate`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryIngestForbiddenServiceName}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{ + ServiceName: "test" + "-" + agconsts.MultiActiveGateName, + }, + }, + }) + }) + t.Run(`extensions`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryIngestForbiddenServiceName}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{ + ServiceName: "test" + consts.ExtensionsControllerSuffix, + }, + }, + }) + }) + t.Run(`telemetry ingest`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryIngestForbiddenServiceName}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{ + ServiceName: "test" + telemetryingest.ServiceNameSuffix, + }, + }, + }) + }) + t.Run(`webhook`, func(t *testing.T) { + assertDenied(t, + []string{errorTelemetryIngestForbiddenServiceName}, + &dynakube.DynaKube{ + ObjectMeta: defaultDynakubeObjectMeta, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + TelemetryIngest: &telemetryingest.Spec{ + ServiceName: "test-webhook", + }, + }, + }) + }) +} diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index f972497391..1c926be932 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -60,6 +60,8 @@ var ( unknownTelemetryIngestProtocols, duplicatedTelemetryIngestProtocols, invalidTelemetryIngestName, + forbiddenTelemetryIngestServiceNameSuffix, + conflictingTelemetryIngestServiceNames, } validatorWarningFuncs = []validatorFunc{ missingActiveGateMemoryLimit, diff --git a/pkg/controllers/dynakube/otelc/service/reconciler.go b/pkg/controllers/dynakube/otelc/service/reconciler.go index 49404cbadb..cf07365027 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler.go @@ -42,37 +42,51 @@ func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.D func (r *Reconciler) Reconcile(ctx context.Context) error { if !r.dk.TelemetryIngest().IsEnabled() { - return r.removeServiceOnce(ctx) - } + r.removeServiceOnce(ctx) - if r.dk.TelemetryIngest().ServiceName != "" { - return r.removeServiceOnce(ctx) + return nil } + r.removeAllServicesExcept(ctx, r.dk.TelemetryIngest().GetServiceName()) + return r.createOrUpdateService(ctx) } -func (r *Reconciler) removeServiceOnce(ctx context.Context) error { +func (r *Reconciler) removeServiceOnce(ctx context.Context) { if meta.FindStatusCondition(*r.dk.Conditions(), serviceConditionType) == nil { - return nil + return } defer meta.RemoveStatusCondition(r.dk.Conditions(), serviceConditionType) - svc, err := r.buildService() - if err != nil { - log.Error(err, "could not build service during cleanup") + r.removeAllServicesExcept(ctx, "") +} - return err +func (r *Reconciler) removeAllServicesExcept(ctx context.Context, actualServiceName string) { + telemetryServiceList := &corev1.ServiceList{} + + listOps := []client.ListOption{ + client.InNamespace(r.dk.Namespace), + client.MatchingLabels{ + labels.AppComponentLabel: labels.OtelCComponentLabel, + labels.AppCreatedByLabel: r.dk.Name, + }, } - err = service.Query(r.client, r.apiReader, log).Delete(ctx, svc) - if err != nil { - log.Error(err, "failed to clean up extension service") + if err := r.apiReader.List(ctx, telemetryServiceList, listOps...); err != nil { + log.Info("failed to list telemetry services, skipping cleanup", "error", err) - return nil + return } - return nil + for _, service := range telemetryServiceList.Items { + if service.Name != actualServiceName { + if err := r.client.Delete(ctx, &service); err != nil { + log.Info("failed to clean up telemetry service", "service name", service.Name, "namespace", service.Namespace, "error", err) + } else { + log.Info("removed unused telemetry service", "service name", service.Name, "namespace", service.Namespace) + } + } + } } func (r *Reconciler) createOrUpdateService(ctx context.Context) error { @@ -85,13 +99,13 @@ func (r *Reconciler) createOrUpdateService(ctx context.Context) error { _, err = service.Query(r.client, r.apiReader, log).CreateOrUpdate(ctx, newService) if err != nil { - log.Info("failed to create/update otelc service") + log.Info("failed to create/update telemetry service") conditions.SetKubeApiError(r.dk.Conditions(), serviceConditionType, err) return err } - conditions.SetServiceCreated(r.dk.Conditions(), serviceConditionType, r.dk.TelemetryIngest().GetName()) + conditions.SetServiceCreated(r.dk.Conditions(), serviceConditionType, r.dk.TelemetryIngest().GetServiceName()) return nil } @@ -101,15 +115,10 @@ func (r *Reconciler) buildService() (*corev1.Service, error) { // TODO: add proper version later on appLabels := labels.NewAppLabels(labels.OtelCComponentLabel, r.dk.Name, labels.OtelCComponentLabel, "") - var svcPorts []corev1.ServicePort - if r.dk.TelemetryIngest().IsEnabled() && r.dk.Spec.TelemetryIngest.ServiceName == "" { - svcPorts = buildServicePortList(r.dk.TelemetryIngest().GetProtocols()) - } - return service.Build(r.dk, - r.dk.TelemetryIngest().GetName(), + r.dk.TelemetryIngest().GetServiceName(), appLabels.BuildMatchLabels(), - svcPorts, + buildServicePortList(r.dk.TelemetryIngest().GetProtocols()), service.SetLabels(coreLabels.BuildLabels()), service.SetType(corev1.ServiceTypeClusterIP), ) diff --git a/pkg/controllers/dynakube/otelc/service/reconciler_test.go b/pkg/controllers/dynakube/otelc/service/reconciler_test.go index 7ae68876c8..a606b25fdc 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/otelcgen" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -44,7 +45,7 @@ func TestService(t *testing.T) { require.NoError(t, err) service := &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetDefaultServiceName(), Namespace: dk.Namespace}, service) require.NoError(t, err) require.Len(t, service.Spec.Ports, 8) @@ -61,7 +62,31 @@ func TestService(t *testing.T) { assert.Equal(t, conditions.ServiceCreatedReason, dk.Status.Conditions[0].Reason) assert.Equal(t, metav1.ConditionTrue, dk.Status.Conditions[0].Status) }) - t.Run("remove service if it is not needed", func(t *testing.T) { + t.Run("create service for specified protocols", func(t *testing.T) { + mockK8sClient := fake.NewFakeClient() + dk := getTestDynakube(&telemetryingest.Spec{ + Protocols: []string{ + string(otelcgen.ZipkinProtocol), + string(otelcgen.StatsdProtocol), + }, + }) + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + service := &corev1.Service{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetDefaultServiceName(), Namespace: dk.Namespace}, service) + require.NoError(t, err) + + require.Len(t, service.Spec.Ports, 2) + assert.Equal(t, portNameZipkin, service.Spec.Ports[0].Name) + assert.Equal(t, portNameStatsd, service.Spec.Ports[1].Name) + + require.Len(t, dk.Status.Conditions, 1) + assert.Equal(t, serviceConditionType, dk.Status.Conditions[0].Type) + assert.Equal(t, conditions.ServiceCreatedReason, dk.Status.Conditions[0].Reason) + assert.Equal(t, metav1.ConditionTrue, dk.Status.Conditions[0].Status) + }) + t.Run("default service name, remove service if it is not needed", func(t *testing.T) { dk := getTestDynakube(nil) dk.Status.Conditions = []metav1.Condition{ { @@ -70,10 +95,14 @@ func TestService(t *testing.T) { } mockK8sClient := fake.NewFakeClient() - err := mockK8sClient.Create(context.Background(), &corev1.Secret{ + err := mockK8sClient.Create(context.Background(), &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: dk.TelemetryIngest().GetName(), + Name: dk.TelemetryIngest().GetDefaultServiceName(), Namespace: dk.Namespace, + Labels: map[string]string{ + labels.AppComponentLabel: labels.OtelCComponentLabel, + labels.AppCreatedByLabel: dk.Name, + }, }, }) require.NoError(t, err) @@ -82,59 +111,82 @@ func TestService(t *testing.T) { require.NoError(t, err) service := &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetDefaultServiceName(), Namespace: dk.Namespace}, service) require.Error(t, err) assert.True(t, k8serrors.IsNotFound(err)) require.Empty(t, dk.Status.Conditions) }) - t.Run("create service for specified protocols", func(t *testing.T) { + t.Run("custom service name, remove service if it is not needed", func(t *testing.T) { + dk := getTestDynakube(nil) + dk.Status.Conditions = []metav1.Condition{ + { + Type: serviceConditionType, + }, + } + mockK8sClient := fake.NewFakeClient() - dk := getTestDynakube(&telemetryingest.Spec{ - Protocols: []string{ - string(otelcgen.ZipkinProtocol), - string(otelcgen.StatsdProtocol), + err := mockK8sClient.Create(context.Background(), &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: testServiceName, + Namespace: dk.Namespace, + Labels: map[string]string{ + labels.AppComponentLabel: labels.OtelCComponentLabel, + labels.AppCreatedByLabel: dk.Name, + }, }, }) - err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + require.NoError(t, err) + + err = NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) service := &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetDefaultServiceName(), Namespace: dk.Namespace}, service) + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err)) + + require.Empty(t, dk.Status.Conditions) + }) + t.Run("update from default service to custom service", func(t *testing.T) { + mockK8sClient := fake.NewFakeClient() + dk := getTestDynakube(&telemetryingest.Spec{}) + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) - require.Len(t, service.Spec.Ports, 2) - assert.Equal(t, portNameZipkin, service.Spec.Ports[0].Name) - assert.Equal(t, portNameStatsd, service.Spec.Ports[1].Name) + service := &corev1.Service{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetDefaultServiceName(), Namespace: dk.Namespace}, service) + require.NoError(t, err) require.Len(t, dk.Status.Conditions, 1) assert.Equal(t, serviceConditionType, dk.Status.Conditions[0].Type) assert.Equal(t, conditions.ServiceCreatedReason, dk.Status.Conditions[0].Reason) assert.Equal(t, metav1.ConditionTrue, dk.Status.Conditions[0].Status) - }) - t.Run("custom service", func(t *testing.T) { - mockK8sClient := fake.NewFakeClient() - dk := getTestDynakube(&telemetryingest.Spec{ + + // update + dk.Spec.TelemetryIngest = &telemetryingest.Spec{ ServiceName: testServiceName, - }) - err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) + } + err = NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) - service := &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: testServiceName, Namespace: dk.Namespace}, service) + service = &corev1.Service{} + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetDefaultServiceName(), Namespace: dk.Namespace}, service) require.Error(t, err) assert.True(t, k8serrors.IsNotFound(err)) - assert.Empty(t, dk.Status.Conditions) + assert.NotEmpty(t, dk.Status.Conditions) }) - t.Run("update from default service to custom service", func(t *testing.T) { + t.Run("update from custom service to default service", func(t *testing.T) { mockK8sClient := fake.NewFakeClient() - dk := getTestDynakube(&telemetryingest.Spec{}) + dk := getTestDynakube(&telemetryingest.Spec{ + ServiceName: testServiceName, + }) err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) service := &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: testServiceName, Namespace: dk.Namespace}, service) require.NoError(t, err) require.Len(t, dk.Status.Conditions, 1) @@ -143,17 +195,15 @@ func TestService(t *testing.T) { assert.Equal(t, metav1.ConditionTrue, dk.Status.Conditions[0].Status) // update - dk.Spec.TelemetryIngest = &telemetryingest.Spec{ - ServiceName: testServiceName, - } + dk.Spec.TelemetryIngest = &telemetryingest.Spec{} err = NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) service = &corev1.Service{} - err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: dk.TelemetryIngest().GetName(), Namespace: dk.Namespace}, service) + err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: testServiceName, Namespace: dk.Namespace}, service) require.Error(t, err) assert.True(t, k8serrors.IsNotFound(err)) - assert.Empty(t, dk.Status.Conditions) + assert.NotEmpty(t, dk.Status.Conditions) }) } From bea32936d34b3718138e1ee81f6a8f9721e2dfce Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:05:23 +0000 Subject: [PATCH 307/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1741850090 (main) (#4587) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6f4dbf0b23..a25160923e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1741626669@sha256:91828a5ca154132e18072cf885f6bb41bb881e6158f30b793f4b424ec144b87d AS base -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1741600006@sha256:b88227436597e960f70db8eadcaf18ffa5b6d1a615888f709dcae3fba1540c61 AS dependency +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1741850090@sha256:8d53b60617e53e4dbd6c0d485c569801f48dbeb40b48c8424a67e33a07320968 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 08266f7a280fb03febeedbbe8cf0b86472bee259 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 13 Mar 2025 11:25:22 +0100 Subject: [PATCH 308/426] Restructure webhook packages, add bootstrapper-injection (#4576) Co-authored-by: Gabriel Krenn --- .mockery.yaml | 1 + .../Common/webhook/clusterrole-webhook.yaml | 1 + .../webhook/clusterrole-webhook_test.yaml | 1 + doc/api/feature-flags.md | 11 +- doc/e2e/features.md | 2 +- pkg/api/v1beta3/dynakube/dynakube_props.go | 4 - pkg/api/v1beta3/dynakube/feature_flags.go | 8 +- pkg/api/v1beta4/dynakube/dynakube_props.go | 2 +- pkg/api/v1beta4/dynakube/feature_flags.go | 12 +- pkg/api/v1beta4/dynakube/oneagent/props.go | 5 +- .../v1beta4/dynakube/oneagent/props_test.go | 10 +- pkg/api/v1beta4/dynakube/oneagent/spec.go | 1 + pkg/api/v1beta4/dynakube/oneagent_props.go | 4 +- pkg/consts/agent_injection.go | 1 + pkg/util/kubeobjects/mounts/volumes.go | 38 ++ pkg/util/kubeobjects/volumes/volumes.go | 19 +- pkg/webhook/config.go | 46 +- pkg/webhook/interface.go | 24 + .../pod/{ => common/events}/events.go | 29 +- .../pod/common/metadata/annotations.go | 56 ++ .../{ => common}/metadata/annotations_test.go | 131 ++-- .../mutation/pod/common/metadata/config.go | 19 + .../mutation/pod/common/metadata/mutator.go | 46 ++ .../pod/common/metadata/mutator_test.go | 47 ++ .../pod/{ => common}/metadata/workload.go | 20 +- .../{ => common}/metadata/workload_test.go | 31 +- .../mutation/pod/common/oneagent/config.go | 39 ++ .../mutation/pod/{ => common}/oneagent/env.go | 80 +-- .../pod/{ => common}/oneagent/env_test.go | 63 +- .../mutation/pod/common/oneagent/init.go | 17 + .../mutation/pod/common/oneagent/mutator.go | 45 ++ .../pod/{ => common}/oneagent/versionlabel.go | 14 +- .../pod/common/oneagent/versionlabel_test.go | 121 ++++ pkg/webhook/mutation/pod/config.go | 11 - .../mutation/pod/metadata/annotations.go | 83 --- .../mutation/pod/oneagent/annotations.go | 45 -- pkg/webhook/mutation/pod/register.go | 31 +- pkg/webhook/mutation/pod/request.go | 2 +- pkg/webhook/mutation/pod/request_test.go | 53 +- pkg/webhook/mutation/pod/v1/config.go | 9 + .../pod/{init_container.go => v1/init.go} | 31 +- .../init_test.go} | 17 +- .../mutation/pod/v1/metadata/annotations.go | 36 ++ .../pod/v1/metadata/annotations_test.go | 50 ++ .../mutation/pod/{ => v1}/metadata/config.go | 2 +- .../pod/{ => v1}/metadata/containers.go | 3 +- .../pod/{ => v1}/metadata/containers_test.go | 10 + .../mutation/pod/{ => v1}/metadata/env.go | 7 +- .../pod/{ => v1}/metadata/env_test.go | 0 .../mutation/pod/{ => v1}/metadata/mutator.go | 43 +- .../pod/{ => v1}/metadata/mutator_test.go | 45 +- .../mutation/pod/{ => v1}/metadata/volumes.go | 0 .../pod/{ => v1}/metadata/volumes_test.go | 0 .../mutation/pod/v1/oneagent/annotations.go | 28 + .../pod/{ => v1}/oneagent/annotations_test.go | 0 .../mutation/pod/{ => v1}/oneagent/config.go | 24 +- .../pod/{ => v1}/oneagent/containers.go | 11 +- .../pod/{ => v1}/oneagent/containers_test.go | 119 ---- pkg/webhook/mutation/pod/v1/oneagent/env.go | 17 + .../mutation/pod/v1/oneagent/env_test.go | 24 + .../mutation/pod/{ => v1}/oneagent/mutator.go | 56 +- .../pod/{ => v1}/oneagent/mutator_test.go | 65 +- .../mutation/pod/{ => v1}/oneagent/volumes.go | 0 .../pod/{ => v1}/oneagent/volumes_test.go | 6 +- pkg/webhook/mutation/pod/v1/webhook.go | 148 +++++ pkg/webhook/mutation/pod/v1/webhook_test.go | 494 +++++++++++++++ pkg/webhook/mutation/pod/v2/common/arg/arg.go | 21 + .../mutation/pod/v2/common/arg/arg_test.go | 36 ++ .../mutation/pod/v2/common/volumes/volumes.go | 94 +++ pkg/webhook/mutation/pod/v2/config.go | 13 + pkg/webhook/mutation/pod/v2/init.go | 91 +++ pkg/webhook/mutation/pod/v2/init_test.go | 207 ++++++ .../mutation/pod/v2/metadata/config.go | 9 + .../mutation/pod/v2/metadata/containers.go | 21 + .../mutation/pod/v2/oneagent/config.go | 9 + .../mutation/pod/v2/oneagent/containers.go | 68 ++ .../pod/v2/oneagent/containers_test.go | 210 ++++++ pkg/webhook/mutation/pod/v2/oneagent/init.go | 53 ++ .../mutation/pod/v2/oneagent/init_test.go | 66 ++ .../mutation/pod/v2/oneagent/volumes.go | 43 ++ .../mutation/pod/v2/oneagent/volumes_test.go | 46 ++ pkg/webhook/mutation/pod/v2/webhook.go | 147 +++++ pkg/webhook/mutation/pod/v2/webhook_test.go | 236 +++++++ pkg/webhook/mutation/pod/webhook.go | 142 +---- pkg/webhook/mutation/pod/webhook_test.go | 597 ++++++++---------- pkg/webhook/{mutator.go => request.go} | 83 +-- .../metadata_enrichment.go | 27 +- .../read_only_csi_volume.go | 2 +- .../cloudnative/codemodules/codemodules.go | 10 +- test/helpers/proxy/proxy.go | 2 +- test/mocks/pkg/webhook/pod_injector.go | 84 +++ 91 files changed, 3406 insertions(+), 1329 deletions(-) create mode 100644 pkg/util/kubeobjects/mounts/volumes.go create mode 100644 pkg/webhook/interface.go rename pkg/webhook/mutation/pod/{ => common/events}/events.go (60%) create mode 100644 pkg/webhook/mutation/pod/common/metadata/annotations.go rename pkg/webhook/mutation/pod/{ => common}/metadata/annotations_test.go (64%) create mode 100644 pkg/webhook/mutation/pod/common/metadata/config.go create mode 100644 pkg/webhook/mutation/pod/common/metadata/mutator.go create mode 100644 pkg/webhook/mutation/pod/common/metadata/mutator_test.go rename pkg/webhook/mutation/pod/{ => common}/metadata/workload.go (86%) rename pkg/webhook/mutation/pod/{ => common}/metadata/workload_test.go (89%) create mode 100644 pkg/webhook/mutation/pod/common/oneagent/config.go rename pkg/webhook/mutation/pod/{ => common}/oneagent/env.go (55%) rename pkg/webhook/mutation/pod/{ => common}/oneagent/env_test.go (70%) create mode 100644 pkg/webhook/mutation/pod/common/oneagent/init.go create mode 100644 pkg/webhook/mutation/pod/common/oneagent/mutator.go rename pkg/webhook/mutation/pod/{ => common}/oneagent/versionlabel.go (74%) create mode 100644 pkg/webhook/mutation/pod/common/oneagent/versionlabel_test.go delete mode 100644 pkg/webhook/mutation/pod/metadata/annotations.go delete mode 100644 pkg/webhook/mutation/pod/oneagent/annotations.go create mode 100644 pkg/webhook/mutation/pod/v1/config.go rename pkg/webhook/mutation/pod/{init_container.go => v1/init.go} (90%) rename pkg/webhook/mutation/pod/{init_container_test.go => v1/init_test.go} (93%) create mode 100644 pkg/webhook/mutation/pod/v1/metadata/annotations.go create mode 100644 pkg/webhook/mutation/pod/v1/metadata/annotations_test.go rename pkg/webhook/mutation/pod/{ => v1}/metadata/config.go (81%) rename pkg/webhook/mutation/pod/{ => v1}/metadata/containers.go (85%) rename pkg/webhook/mutation/pod/{ => v1}/metadata/containers_test.go (92%) rename pkg/webhook/mutation/pod/{ => v1}/metadata/env.go (83%) rename pkg/webhook/mutation/pod/{ => v1}/metadata/env_test.go (100%) rename pkg/webhook/mutation/pod/{ => v1}/metadata/mutator.go (66%) rename pkg/webhook/mutation/pod/{ => v1}/metadata/mutator_test.go (83%) rename pkg/webhook/mutation/pod/{ => v1}/metadata/volumes.go (100%) rename pkg/webhook/mutation/pod/{ => v1}/metadata/volumes_test.go (100%) create mode 100644 pkg/webhook/mutation/pod/v1/oneagent/annotations.go rename pkg/webhook/mutation/pod/{ => v1}/oneagent/annotations_test.go (100%) rename pkg/webhook/mutation/pod/{ => v1}/oneagent/config.go (58%) rename pkg/webhook/mutation/pod/{ => v1}/oneagent/containers.go (78%) rename pkg/webhook/mutation/pod/{ => v1}/oneagent/containers_test.go (63%) create mode 100644 pkg/webhook/mutation/pod/v1/oneagent/env.go create mode 100644 pkg/webhook/mutation/pod/v1/oneagent/env_test.go rename pkg/webhook/mutation/pod/{ => v1}/oneagent/mutator.go (62%) rename pkg/webhook/mutation/pod/{ => v1}/oneagent/mutator_test.go (89%) rename pkg/webhook/mutation/pod/{ => v1}/oneagent/volumes.go (100%) rename pkg/webhook/mutation/pod/{ => v1}/oneagent/volumes_test.go (95%) create mode 100644 pkg/webhook/mutation/pod/v1/webhook.go create mode 100644 pkg/webhook/mutation/pod/v1/webhook_test.go create mode 100644 pkg/webhook/mutation/pod/v2/common/arg/arg.go create mode 100644 pkg/webhook/mutation/pod/v2/common/arg/arg_test.go create mode 100644 pkg/webhook/mutation/pod/v2/common/volumes/volumes.go create mode 100644 pkg/webhook/mutation/pod/v2/config.go create mode 100644 pkg/webhook/mutation/pod/v2/init.go create mode 100644 pkg/webhook/mutation/pod/v2/init_test.go create mode 100644 pkg/webhook/mutation/pod/v2/metadata/config.go create mode 100644 pkg/webhook/mutation/pod/v2/metadata/containers.go create mode 100644 pkg/webhook/mutation/pod/v2/oneagent/config.go create mode 100644 pkg/webhook/mutation/pod/v2/oneagent/containers.go create mode 100644 pkg/webhook/mutation/pod/v2/oneagent/containers_test.go create mode 100644 pkg/webhook/mutation/pod/v2/oneagent/init.go create mode 100644 pkg/webhook/mutation/pod/v2/oneagent/init_test.go create mode 100644 pkg/webhook/mutation/pod/v2/oneagent/volumes.go create mode 100644 pkg/webhook/mutation/pod/v2/oneagent/volumes_test.go create mode 100644 pkg/webhook/mutation/pod/v2/webhook.go create mode 100644 pkg/webhook/mutation/pod/v2/webhook_test.go rename pkg/webhook/{mutator.go => request.go} (73%) create mode 100644 test/mocks/pkg/webhook/pod_injector.go diff --git a/.mockery.yaml b/.mockery.yaml index b1ac1510b8..a21124e478 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -58,6 +58,7 @@ packages: github.com/Dynatrace/dynatrace-operator/pkg/webhook: interfaces: PodMutator: + PodInjector: sigs.k8s.io/controller-runtime/pkg/manager: interfaces: Manager: diff --git a/config/helm/chart/default/templates/Common/webhook/clusterrole-webhook.yaml b/config/helm/chart/default/templates/Common/webhook/clusterrole-webhook.yaml index 953802aeb3..ab1e052b2a 100644 --- a/config/helm/chart/default/templates/Common/webhook/clusterrole-webhook.yaml +++ b/config/helm/chart/default/templates/Common/webhook/clusterrole-webhook.yaml @@ -39,6 +39,7 @@ rules: - secrets resourceNames: - dynatrace-dynakube-config + - dynatrace-bootstrapper-config - dynatrace-metadata-enrichment-endpoint verbs: - get diff --git a/config/helm/chart/default/tests/Common/webhook/clusterrole-webhook_test.yaml b/config/helm/chart/default/tests/Common/webhook/clusterrole-webhook_test.yaml index dc53e803eb..7a4f3422cc 100644 --- a/config/helm/chart/default/tests/Common/webhook/clusterrole-webhook_test.yaml +++ b/config/helm/chart/default/tests/Common/webhook/clusterrole-webhook_test.yaml @@ -40,6 +40,7 @@ tests: - "" resourceNames: - dynatrace-dynakube-config + - dynatrace-bootstrapper-config - dynatrace-metadata-enrichment-endpoint resources: - secrets diff --git a/doc/api/feature-flags.md b/doc/api/feature-flags.md index 3e0bf01dc3..0fc1253693 100644 --- a/doc/api/feature-flags.md +++ b/doc/api/feature-flags.md @@ -17,8 +17,7 @@ import "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/tmp" ```go const ( - AnnotationFeaturePrefix = "feature.dynatrace.com/" - AnnotationFeatureCodeModulesPrefix = "codemodules.oneagent.dynatrace.com/" + AnnotationFeaturePrefix = "feature.dynatrace.com/" // General. AnnotationFeaturePublicRegistry = AnnotationFeaturePrefix + "public-registry" @@ -59,7 +58,11 @@ const ( AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remote-image-download" + AnnotationFeatureRemoteImageDownload = AnnotationFeaturePrefix + "remote-image-download" + + // AnnotationTechnologies can be set on a Pod or DynaKube to configure which code module technologies to download. It's set to + // "all" if not set. + AnnotationTechnologies = "oneagent.dynatrace.com/technologies" ) ``` @@ -76,7 +79,7 @@ const ( -## func [MountAttemptsToTimeout]() +## func [MountAttemptsToTimeout]() ```go func MountAttemptsToTimeout(maxAttempts int) string diff --git a/doc/e2e/features.md b/doc/e2e/features.md index 0af2d44ded..9c40449062 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -53,7 +53,7 @@ Verification that build labels are created and set accordingly. The test checks: -## func [MetadataEnrichment]() +## func [MetadataEnrichment]() ```go func MetadataEnrichment(t *testing.T) features.Feature diff --git a/pkg/api/v1beta3/dynakube/dynakube_props.go b/pkg/api/v1beta3/dynakube/dynakube_props.go index 62597fe173..66b73ad319 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_props.go +++ b/pkg/api/v1beta3/dynakube/dynakube_props.go @@ -104,7 +104,3 @@ func (dk *DynaKube) ApiRequestThreshold() time.Duration { func (dk *DynaKube) IsTokenScopeVerificationAllowed(timeProvider *timeprovider.Provider) bool { return timeProvider.IsOutdated(&dk.Status.DynatraceApi.LastTokenScopeRequest, dk.ApiRequestThreshold()) } - -func (dk *DynaKube) FeatureBootstrapperInjection() bool { - return dk.FeatureRemoteImageDownload() && !dk.OneAgent().IsCSIAvailable() -} diff --git a/pkg/api/v1beta3/dynakube/feature_flags.go b/pkg/api/v1beta3/dynakube/feature_flags.go index 674b9fae8d..eb4b17d0f0 100644 --- a/pkg/api/v1beta3/dynakube/feature_flags.go +++ b/pkg/api/v1beta3/dynakube/feature_flags.go @@ -27,8 +27,7 @@ import ( ) const ( - AnnotationFeaturePrefix = "feature.dynatrace.com/" - AnnotationFeatureCodeModulesPrefix = "codemodules.oneagent.dynatrace.com/" + AnnotationFeaturePrefix = "feature.dynatrace.com/" // General. AnnotationFeaturePublicRegistry = AnnotationFeaturePrefix + "public-registry" @@ -75,7 +74,6 @@ const ( AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remote-image-download" falsePhrase = "false" truePhrase = "true" @@ -277,10 +275,6 @@ func (dk *DynaKube) FeatureReadOnlyCsiVolume() bool { return dk.getFeatureFlagRaw(AnnotationFeatureReadOnlyCsiVolume) == truePhrase } -func (dk *DynaKube) FeatureRemoteImageDownload() bool { - return dk.getFeatureFlagRaw(AnnotationFeatureRemoteImageDownload) == truePhrase -} - func (dk *DynaKube) FeatureInjectionFailurePolicy() string { if dk.getFeatureFlagRaw(AnnotationInjectionFailurePolicy) == failPhrase { return failPhrase diff --git a/pkg/api/v1beta4/dynakube/dynakube_props.go b/pkg/api/v1beta4/dynakube/dynakube_props.go index 62597fe173..4037e5a6fc 100644 --- a/pkg/api/v1beta4/dynakube/dynakube_props.go +++ b/pkg/api/v1beta4/dynakube/dynakube_props.go @@ -106,5 +106,5 @@ func (dk *DynaKube) IsTokenScopeVerificationAllowed(timeProvider *timeprovider.P } func (dk *DynaKube) FeatureBootstrapperInjection() bool { - return dk.FeatureRemoteImageDownload() && !dk.OneAgent().IsCSIAvailable() + return dk.OneAgent().IsApplicationMonitoringMode() && dk.FeatureRemoteImageDownload() && !dk.OneAgent().IsCSIAvailable() } diff --git a/pkg/api/v1beta4/dynakube/feature_flags.go b/pkg/api/v1beta4/dynakube/feature_flags.go index 674b9fae8d..daced741e8 100644 --- a/pkg/api/v1beta4/dynakube/feature_flags.go +++ b/pkg/api/v1beta4/dynakube/feature_flags.go @@ -27,8 +27,7 @@ import ( ) const ( - AnnotationFeaturePrefix = "feature.dynatrace.com/" - AnnotationFeatureCodeModulesPrefix = "codemodules.oneagent.dynatrace.com/" + AnnotationFeaturePrefix = "feature.dynatrace.com/" // General. AnnotationFeaturePublicRegistry = AnnotationFeaturePrefix + "public-registry" @@ -75,12 +74,16 @@ const ( AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureRemoteImageDownload = AnnotationFeatureCodeModulesPrefix + "remote-image-download" + AnnotationFeatureRemoteImageDownload = AnnotationFeaturePrefix + "remote-image-download" falsePhrase = "false" truePhrase = "true" silentPhrase = "silent" failPhrase = "fail" + + // AnnotationTechnologies can be set on a Pod or DynaKube to configure which code module technologies to download. It's set to + // "all" if not set. + AnnotationTechnologies = "oneagent.dynatrace.com/technologies" ) const ( @@ -281,6 +284,9 @@ func (dk *DynaKube) FeatureRemoteImageDownload() bool { return dk.getFeatureFlagRaw(AnnotationFeatureRemoteImageDownload) == truePhrase } +func (dk *DynaKube) FeatureRemoteImageDownloadTechnology() string { + return dk.getFeatureFlagRaw(AnnotationTechnologies) +} func (dk *DynaKube) FeatureInjectionFailurePolicy() string { if dk.getFeatureFlagRaw(AnnotationInjectionFailurePolicy) == failPhrase { return failPhrase diff --git a/pkg/api/v1beta4/dynakube/oneagent/props.go b/pkg/api/v1beta4/dynakube/oneagent/props.go index 3e65f767cd..7d0ca9adc6 100644 --- a/pkg/api/v1beta4/dynakube/oneagent/props.go +++ b/pkg/api/v1beta4/dynakube/oneagent/props.go @@ -20,7 +20,7 @@ const ( func NewOneAgent(spec *Spec, status *Status, codeModulesStatus *CodeModulesStatus, //nolint:revive name, apiUrlHost string, - featureOneAgentPrivileged, featureOneAgentSkipLivenessProbe bool) *OneAgent { + featureOneAgentPrivileged, featureOneAgentSkipLivenessProbe, featureBootstrapperInjection bool) *OneAgent { return &OneAgent{ Spec: spec, Status: status, @@ -31,6 +31,7 @@ func NewOneAgent(spec *Spec, status *Status, codeModulesStatus *CodeModulesStatu featureOneAgentPrivileged: featureOneAgentPrivileged, featureOneAgentSkipLivenessProbe: featureOneAgentSkipLivenessProbe, + featureBootstrapperInjection: featureBootstrapperInjection, } } @@ -286,7 +287,7 @@ func (oa *OneAgent) GetEndpoints() string { func (oa *OneAgent) GetCustomCodeModulesImage() string { if oa.IsCloudNativeFullstackMode() { return oa.CloudNativeFullStack.CodeModulesImage - } else if oa.IsApplicationMonitoringMode() && oa.IsCSIAvailable() { + } else if oa.IsApplicationMonitoringMode() && (oa.IsCSIAvailable() || oa.featureBootstrapperInjection) { return oa.ApplicationMonitoring.CodeModulesImage } diff --git a/pkg/api/v1beta4/dynakube/oneagent/props_test.go b/pkg/api/v1beta4/dynakube/oneagent/props_test.go index 00987176f8..71bc2c88c1 100644 --- a/pkg/api/v1beta4/dynakube/oneagent/props_test.go +++ b/pkg/api/v1beta4/dynakube/oneagent/props_test.go @@ -68,13 +68,13 @@ func TestDefaultOneAgentImage(t *testing.T) { t.Run("OneAgentImage adds raw postfix", func(t *testing.T) { hostUrl, _ := url.Parse(testAPIURL) - oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false) + oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false, false) assert.Equal(t, "test-endpoint/linux/oneagent:1.234.5-raw", oneAgent.GetDefaultImage("1.234.5")) }) t.Run("OneAgentImage doesn't add 'raw' postfix if present", func(t *testing.T) { hostUrl, _ := url.Parse(testAPIURL) - oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false) + oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false, false) assert.Equal(t, "test-endpoint/linux/oneagent:1.234.5-raw", oneAgent.GetDefaultImage("1.234.5-raw")) }) @@ -82,7 +82,7 @@ func TestDefaultOneAgentImage(t *testing.T) { version := "1.239.14.20220325-164521" expectedImage := "test-endpoint/linux/oneagent:1.239.14-raw" hostUrl, _ := url.Parse(testAPIURL) - oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false) + oneAgent := NewOneAgent(&Spec{}, &Status{}, &CodeModulesStatus{}, "", hostUrl.Host, false, false, false) assert.Equal(t, expectedImage, oneAgent.GetDefaultImage(version)) }) } @@ -110,7 +110,7 @@ func TestCodeModulesVersion(t *testing.T) { t.Run("use status", func(t *testing.T) { codeModulesStatus := &CodeModulesStatus{VersionStatus: status.VersionStatus{Version: testVersion}} - oneAgent := NewOneAgent(&Spec{}, &Status{}, codeModulesStatus, "", "", false, false) + oneAgent := NewOneAgent(&Spec{}, &Status{}, codeModulesStatus, "", "", false, false, false) version := oneAgent.GetCodeModulesVersion() assert.Equal(t, testVersion, version) }) @@ -118,7 +118,7 @@ func TestCodeModulesVersion(t *testing.T) { codeModulesStatus := &CodeModulesStatus{VersionStatus: status.VersionStatus{Version: "other"}} oneAgent := NewOneAgent(&Spec{ ApplicationMonitoring: &ApplicationMonitoringSpec{Version: testVersion}, - }, &Status{}, codeModulesStatus, "", "", false, false) + }, &Status{}, codeModulesStatus, "", "", false, false, false) version := oneAgent.GetCustomCodeModulesVersion() assert.Equal(t, testVersion, version) diff --git a/pkg/api/v1beta4/dynakube/oneagent/spec.go b/pkg/api/v1beta4/dynakube/oneagent/spec.go index eb2c78fe4c..a6bb62bedb 100644 --- a/pkg/api/v1beta4/dynakube/oneagent/spec.go +++ b/pkg/api/v1beta4/dynakube/oneagent/spec.go @@ -15,6 +15,7 @@ type OneAgent struct { apiUrlHost string featureOneAgentPrivileged bool + featureBootstrapperInjection bool featureOneAgentSkipLivenessProbe bool } diff --git a/pkg/api/v1beta4/dynakube/oneagent_props.go b/pkg/api/v1beta4/dynakube/oneagent_props.go index 6e5d3b21a5..09a8007c8e 100644 --- a/pkg/api/v1beta4/dynakube/oneagent_props.go +++ b/pkg/api/v1beta4/dynakube/oneagent_props.go @@ -12,7 +12,9 @@ func (dk *DynaKube) OneAgent() *oneagent.OneAgent { dk.Name, dk.ApiUrlHost(), dk.FeatureOneAgentPrivileged(), - dk.FeatureOneAgentSkipLivenessProbe()) + dk.FeatureOneAgentSkipLivenessProbe(), + dk.FeatureRemoteImageDownload(), + ) return oa } diff --git a/pkg/consts/agent_injection.go b/pkg/consts/agent_injection.go index 397fdad2df..8fb640d5bc 100644 --- a/pkg/consts/agent_injection.go +++ b/pkg/consts/agent_injection.go @@ -28,6 +28,7 @@ const ( AgentShareDirMount = "/mnt/share" AgentConfigDirMount = "/mnt/config" AgentConfInitDirMount = "/mnt/agent-conf" + AgentCodeModuleSource = "/opt/dynatrace/oneagent" TrustedCAsInitSecretField = "trustedcas" ActiveGateCAsInitSecretField = "agcerts" diff --git a/pkg/util/kubeobjects/mounts/volumes.go b/pkg/util/kubeobjects/mounts/volumes.go new file mode 100644 index 0000000000..27a9633368 --- /dev/null +++ b/pkg/util/kubeobjects/mounts/volumes.go @@ -0,0 +1,38 @@ +package mounts + +import ( + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" +) + +func GetByName(mounts []corev1.VolumeMount, volumeName string) (*corev1.VolumeMount, error) { + for _, mount := range mounts { + if mount.Name == volumeName { + return &mount, nil + } + } + + return nil, errors.Errorf(`Cannot find volume mount "%s" in the provided slice (len %d)`, + volumeName, len(mounts), + ) +} + +func IsIn(mounts []corev1.VolumeMount, volumeName string) bool { + for _, vm := range mounts { + if vm.Name == volumeName { + return true + } + } + + return false +} + +func IsPathIn(mounts []corev1.VolumeMount, path string) bool { + for _, vm := range mounts { + if vm.MountPath == path { + return true + } + } + + return false +} diff --git a/pkg/util/kubeobjects/volumes/volumes.go b/pkg/util/kubeobjects/volumes/volumes.go index 9ba6c8685c..54f3274715 100644 --- a/pkg/util/kubeobjects/volumes/volumes.go +++ b/pkg/util/kubeobjects/volumes/volumes.go @@ -1,25 +1,12 @@ package volumes import ( - "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" ) -func GetVolumeMountByName(mounts []corev1.VolumeMount, volumeName string) (*corev1.VolumeMount, error) { - for _, mount := range mounts { - if mount.Name == volumeName { - return &mount, nil - } - } - - return nil, errors.Errorf(`Cannot find volume mount "%s" in the provided slice (len %d)`, - volumeName, len(mounts), - ) -} - -func IsIn(mounts []corev1.VolumeMount, volumeName string) bool { - for _, vm := range mounts { - if vm.Name == volumeName { +func IsIn(vol []corev1.Volume, volumeName string) bool { + for _, v := range vol { + if v.Name == volumeName { return true } } diff --git a/pkg/webhook/config.go b/pkg/webhook/config.go index f590a16610..30bb46785e 100644 --- a/pkg/webhook/config.go +++ b/pkg/webhook/config.go @@ -4,48 +4,21 @@ const ( // InjectionInstanceLabel can be set in a Namespace and indicates the corresponding DynaKube object assigned to it. InjectionInstanceLabel = "dynakube.internal.dynatrace.com/instance" + // AnnotationFailurePolicy can be set on a Pod to control what the init container does on failures. When set to + // "fail", the init container will exit with error code 1. Defaults to "silent". + AnnotationFailurePolicy = "oneagent.dynatrace.com/failure-policy" + // AnnotationDynatraceInjected is set to "true" by the webhook to Pods to indicate that it has been injected. AnnotationDynatraceInjected = "dynakube.dynatrace.com/injected" + // AnnotationDynatraceReason is add to provide extra info why an injection didn't happen. + AnnotationDynatraceReason = "dynakube.dynatrace.com/reason" + // AnnotationDynatraceInject is set to "false" on the Pod to indicate that does not want any injection. AnnotationDynatraceInject = "dynatrace.com/inject" - OneAgentPrefix = "oneagent" - // AnnotationOneAgentInject can be set at pod level to enable/disable OneAgent injection. - AnnotationOneAgentInject = OneAgentPrefix + ".dynatrace.com/inject" - AnnotationOneAgentInjected = OneAgentPrefix + ".dynatrace.com/injected" - AnnotationOneAgentReason = OneAgentPrefix + ".dynatrace.com/reason" - - MetadataEnrichmentPrefix = "metadata-enrichment" - // AnnotationMetadataEnrichmentInject can be set at pod level to enable/disable metadata-enrichment injection. - AnnotationMetadataEnrichmentInject = MetadataEnrichmentPrefix + ".dynatrace.com/inject" - AnnotationMetadataEnrichmentInjected = MetadataEnrichmentPrefix + ".dynatrace.com/injected" - - // AnnotationFlavor can be set on a Pod to configure which code modules flavor to download. It's set to "default" - // if not set. - AnnotationFlavor = "oneagent.dynatrace.com/flavor" - - // AnnotationTechnologies can be set on a Pod to configure which code module technologies to download. It's set to - // "all" if not set. - AnnotationTechnologies = "oneagent.dynatrace.com/technologies" - - // AnnotationInstallPath can be set on a Pod to configure on which directory the OneAgent will be available from, - // defaults to DefaultInstallPath if not set. - AnnotationInstallPath = "oneagent.dynatrace.com/install-path" - - // AnnotationInstallerUrl can be set on a Pod to configure the installer url for downloading the agent - // defaults to the PaaS installer download url of your tenant - AnnotationInstallerUrl = "oneagent.dynatrace.com/installer-url" - - // AnnotationFailurePolicy can be set on a Pod to control what the init container does on failures. When set to - // "fail", the init container will exit with error code 1. Defaults to "silent". - AnnotationFailurePolicy = "oneagent.dynatrace.com/failure-policy" - AnnotationContainerInjection = "container.inject.dynatrace.com" - // DefaultInstallPath is the default directory to install the app-only OneAgent package. - DefaultInstallPath = "/opt/dynatrace/oneagent-paas" - // SecretCertsName is the name of the secret where the webhook certificates are stored. SecretCertsName = "dynatrace-webhook-certs" @@ -56,9 +29,4 @@ const ( // InstallContainerName is the name used for the install container InstallContainerName = "dynatrace-operator" - - // AnnotationWorkloadKind is added to any injected pods when the metadata-enrichment feature is enabled - AnnotationWorkloadKind = "metadata.dynatrace.com/k8s.workload.kind" - // AnnotationWorkloadName is added to any injected pods when the metadata-enrichment feature is enabled - AnnotationWorkloadName = "metadata.dynatrace.com/k8s.workload.name" ) diff --git a/pkg/webhook/interface.go b/pkg/webhook/interface.go new file mode 100644 index 0000000000..afc3af81f7 --- /dev/null +++ b/pkg/webhook/interface.go @@ -0,0 +1,24 @@ +package webhook + +import "context" + +type PodInjector interface { + Handle(context.Context, *MutationRequest) error +} + +type PodMutator interface { + // Enabled returns true if the mutator needs to be executed for the given request. + // This is used to filter out mutators that are not needed for the given request. + Enabled(request *BaseRequest) bool + + // Injected returns true if the mutator has already injected into the pod of the given request. + // This is used during reinvocation to prevent multiple injections. + Injected(request *BaseRequest) bool + + // Mutate mutates the elements of the given MutationRequest, specifically the pod and installContainer. + Mutate(ctx context.Context, request *MutationRequest) error + + // Reinvocation mutates the pod of the given ReinvocationRequest. + // It only mutates the parts of the pod that haven't been mutated yet. (example: another webhook mutated the pod after our webhook was executed) + Reinvoke(request *ReinvocationRequest) bool +} diff --git a/pkg/webhook/mutation/pod/events.go b/pkg/webhook/mutation/pod/common/events/events.go similarity index 60% rename from pkg/webhook/mutation/pod/events.go rename to pkg/webhook/mutation/pod/common/events/events.go index 176ee9dc79..f2d98e2c5d 100644 --- a/pkg/webhook/mutation/pod/events.go +++ b/pkg/webhook/mutation/pod/common/events/events.go @@ -1,37 +1,50 @@ -package pod +package events import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" ) -type eventRecorder struct { +const ( + injectEvent = "Inject" + updatePodEvent = "UpdatePod" + IncompatibleCRDEvent = "IncompatibleCRDPresent" + missingDynakubeEvent = "MissingDynakube" +) + +type EventRecorder struct { dk *dynakube.DynaKube pod *corev1.Pod recorder record.EventRecorder } -func newPodMutatorEventRecorder(recorder record.EventRecorder) eventRecorder { - return eventRecorder{recorder: recorder} +func NewRecorder(recorder record.EventRecorder) EventRecorder { + return EventRecorder{recorder: recorder} +} + +func (er *EventRecorder) Setup(mutationRequest *dtwebhook.MutationRequest) { + er.dk = &mutationRequest.DynaKube + er.pod = mutationRequest.Pod } -func (er *eventRecorder) sendPodInjectEvent() { +func (er *EventRecorder) SendPodInjectEvent() { er.recorder.Eventf(er.dk, corev1.EventTypeNormal, injectEvent, "Injecting the necessary info into pod %s in namespace %s", er.pod.GenerateName, er.pod.Namespace) } -func (er *eventRecorder) sendPodUpdateEvent() { +func (er *EventRecorder) SendPodUpdateEvent() { er.recorder.Eventf(er.dk, corev1.EventTypeNormal, updatePodEvent, "Updating pod %s in namespace %s with missing containers", er.pod.GenerateName, er.pod.Namespace) } -func (er *eventRecorder) sendMissingDynaKubeEvent(namespaceName, dynakubeName string) { +func (er *EventRecorder) SendMissingDynaKubeEvent(namespaceName, dynakubeName string) { template := "Namespace '%s' is assigned to DynaKube instance '%s' but this instance doesn't exist" er.recorder.Eventf( &dynakube.DynaKube{ObjectMeta: metav1.ObjectMeta{Name: dynakubeName, Namespace: namespaceName}}, @@ -40,7 +53,7 @@ func (er *eventRecorder) sendMissingDynaKubeEvent(namespaceName, dynakubeName st template, namespaceName, dynakubeName) } -func (er *eventRecorder) sendOneAgentAPMWarningEvent(webhookPod *corev1.Pod) { +func (er *EventRecorder) SendOneAgentAPMWarningEvent(webhookPod *corev1.Pod) { er.recorder.Event(webhookPod, corev1.EventTypeWarning, IncompatibleCRDEvent, diff --git a/pkg/webhook/mutation/pod/common/metadata/annotations.go b/pkg/webhook/mutation/pod/common/metadata/annotations.go new file mode 100644 index 0000000000..54325113bf --- /dev/null +++ b/pkg/webhook/mutation/pod/common/metadata/annotations.go @@ -0,0 +1,56 @@ +package metadata + +import ( + "strings" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + corev1 "k8s.io/api/core/v1" +) + +func CopyMetadataFromNamespace(pod *corev1.Pod, namespace corev1.Namespace, dk dynakube.DynaKube) { + copyAccordingToCustomRules(pod, namespace, dk) + copyAccordingToPrefix(pod, namespace) +} + +func copyAccordingToPrefix(pod *corev1.Pod, namespace corev1.Namespace) { + for key, value := range namespace.Annotations { + if strings.HasPrefix(key, dynakube.MetadataPrefix) { + setPodAnnotationIfNotExists(pod, key, value) + } + } +} + +func copyAccordingToCustomRules(pod *corev1.Pod, namespace corev1.Namespace, dk dynakube.DynaKube) { + for _, rule := range dk.Status.MetadataEnrichment.Rules { + if rule.Target == "" { + log.Info("rule without target set found, ignoring", "source", rule.Source, "type", rule.Type) + + continue + } + + var valueFromNamespace string + + var exists bool + + switch rule.Type { + case dynakube.EnrichmentLabelRule: + valueFromNamespace, exists = namespace.Labels[rule.Source] + case dynakube.EnrichmentAnnotationRule: + valueFromNamespace, exists = namespace.Annotations[rule.Source] + } + + if exists { + setPodAnnotationIfNotExists(pod, rule.ToAnnotationKey(), valueFromNamespace) + } + } +} + +func setPodAnnotationIfNotExists(pod *corev1.Pod, key, value string) { + if pod.Annotations == nil { + pod.Annotations = make(map[string]string) + } + + if _, ok := pod.Annotations[key]; !ok { + pod.Annotations[key] = value + } +} diff --git a/pkg/webhook/mutation/pod/metadata/annotations_test.go b/pkg/webhook/mutation/pod/common/metadata/annotations_test.go similarity index 64% rename from pkg/webhook/mutation/pod/metadata/annotations_test.go rename to pkg/webhook/mutation/pod/common/metadata/annotations_test.go index b60afa892c..4b16a92555 100644 --- a/pkg/webhook/mutation/pod/metadata/annotations_test.go +++ b/pkg/webhook/mutation/pod/common/metadata/annotations_test.go @@ -1,20 +1,19 @@ package metadata import ( - "encoding/json" + "context" "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" - "github.com/stretchr/testify/assert" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestCopyMetadataFromNamespace(t *testing.T) { t.Run("should copy annotations not labels with prefix from namespace to pod", func(t *testing.T) { - mutator := createTestPodMutator(nil) - request := createTestMutationRequest(nil, nil, false) + request := createTestMutationRequest(nil, nil) request.Namespace.Labels = map[string]string{ dynakube.MetadataPrefix + "nocopyoflabels": "nocopyoflabels", "test-label": "test-value", @@ -24,16 +23,14 @@ func TestCopyMetadataFromNamespace(t *testing.T) { "test-annotation": "test-value", } - require.False(t, mutator.Injected(request.BaseRequest)) - copyMetadataFromNamespace(request.Pod, request.Namespace, request.DynaKube) + CopyMetadataFromNamespace(request.Pod, request.Namespace, request.DynaKube) require.Len(t, request.Pod.Annotations, 1) require.Empty(t, request.Pod.Labels) require.Equal(t, "copyofannotations", request.Pod.Annotations[dynakube.MetadataPrefix+"copyofannotations"]) }) t.Run("should copy all labels and annotations defined without override", func(t *testing.T) { - mutator := createTestPodMutator(nil) - request := createTestMutationRequest(nil, nil, false) + request := createTestMutationRequest(nil, nil) request.Namespace.Labels = map[string]string{ dynakube.MetadataPrefix + "nocopyoflabels": "nocopyoflabels", dynakube.MetadataPrefix + "copyifruleexists": "copyifruleexists", @@ -70,8 +67,7 @@ func TestCopyMetadataFromNamespace(t *testing.T) { dynakube.MetadataPrefix + "copyofannotations": "do-not-overwrite", } - require.False(t, mutator.Injected(request.BaseRequest)) - copyMetadataFromNamespace(request.Pod, request.Namespace, request.DynaKube) + CopyMetadataFromNamespace(request.Pod, request.Namespace, request.DynaKube) require.Len(t, request.Pod.Annotations, 4) require.Empty(t, request.Pod.Labels) @@ -83,8 +79,7 @@ func TestCopyMetadataFromNamespace(t *testing.T) { }) t.Run("are custom rule types handled correctly", func(t *testing.T) { - mutator := createTestPodMutator(nil) - request := createTestMutationRequest(nil, nil, false) + request := createTestMutationRequest(nil, nil) request.Namespace.Labels = map[string]string{ "test": "test-label-value", "test2": "test-label-value2", @@ -114,8 +109,7 @@ func TestCopyMetadataFromNamespace(t *testing.T) { }, } - require.False(t, mutator.Injected(request.BaseRequest)) - copyMetadataFromNamespace(request.Pod, request.Namespace, request.DynaKube) + CopyMetadataFromNamespace(request.Pod, request.Namespace, request.DynaKube) require.Len(t, request.Pod.Annotations, 2) require.Empty(t, request.Pod.Labels) require.Equal(t, "test-label-value", request.Pod.Annotations[dynakube.MetadataPrefix+"dt.test-label"]) @@ -123,40 +117,77 @@ func TestCopyMetadataFromNamespace(t *testing.T) { }) } -func TestAddMetadataToInitEnv(t *testing.T) { - t.Run("should copy annotations not labels with prefix from pod to env", func(t *testing.T) { - expectedKeys := []string{ - "beep", - "boop", - "hello", - } - notExpectedKey := "no-prop" - request := createTestMutationRequest(nil, nil, false) - request.Pod.Labels = map[string]string{ - dynakube.MetadataPrefix + notExpectedKey: "beep-boop", - "test-label": "boom", - } - request.Pod.Annotations = map[string]string{ - "test-annotation": "boom", - } - - for _, key := range expectedKeys { - request.Pod.Annotations[dynakube.MetadataPrefix+key] = key + "-value" - } - - addMetadataToInitEnv(request.Pod, request.InstallContainer) - - annotationsEnv := env.FindEnvVar(request.InstallContainer.Env, consts.EnrichmentWorkloadAnnotationsEnv) - require.NotNil(t, annotationsEnv) +func createTestMutationRequest(dk *dynakube.DynaKube, annotations map[string]string) *dtwebhook.MutationRequest { + if dk == nil { + dk = &dynakube.DynaKube{} + } + + return dtwebhook.NewMutationRequest( + context.Background(), + *getTestNamespace(dk), + &corev1.Container{ + Name: dtwebhook.InstallContainerName, + }, + getTestPod(annotations), + *dk, + ) +} - propagatedAnnotations := map[string]string{} - err := json.Unmarshal([]byte(annotationsEnv.Value), &propagatedAnnotations) - require.NoError(t, err) +func getTestNamespace(dk *dynakube.DynaKube) *corev1.Namespace { + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-ns", + Labels: map[string]string{ + dtwebhook.InjectionInstanceLabel: dk.Name, + }, + }, + } +} - for _, key := range expectedKeys { - require.Contains(t, propagatedAnnotations, key) - assert.Equal(t, key+"-value", propagatedAnnotations[key]) - assert.NotContains(t, propagatedAnnotations, notExpectedKey) - } - }) +func getTestPod(annotations map[string]string) *corev1.Pod { + return &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod", + Namespace: "test-ns", + Annotations: annotations, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "container-1", + Image: "alpine-1", + VolumeMounts: []corev1.VolumeMount{ + { + Name: "volume", + MountPath: "/volume", + }, + }, + }, + { + Name: "container-2", + Image: "alpine-2", + VolumeMounts: []corev1.VolumeMount{ + { + Name: "volume", + MountPath: "/volume", + }, + }, + }, + }, + InitContainers: []corev1.Container{ + { + Name: "init-container", + Image: "alpine", + }, + }, + Volumes: []corev1.Volume{ + { + Name: "volume", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + }, + }, + } } diff --git a/pkg/webhook/mutation/pod/common/metadata/config.go b/pkg/webhook/mutation/pod/common/metadata/config.go new file mode 100644 index 0000000000..ebcdcb9cb0 --- /dev/null +++ b/pkg/webhook/mutation/pod/common/metadata/config.go @@ -0,0 +1,19 @@ +package metadata + +import "github.com/Dynatrace/dynatrace-operator/pkg/logd" + +const ( + AnnotationPrefix = "metadata-enrichment" + // AnnotationMetadataEnrichmentInject can be set at pod level to enable/disable metadata-enrichment injection. + AnnotationInject = AnnotationPrefix + ".dynatrace.com/inject" + AnnotationInjected = AnnotationPrefix + ".dynatrace.com/injected" + + // AnnotationWorkloadKind is added to any injected pods when the metadata-enrichment feature is enabled + AnnotationWorkloadKind = "metadata.dynatrace.com/k8s.workload.kind" + // AnnotationWorkloadName is added to any injected pods when the metadata-enrichment feature is enabled + AnnotationWorkloadName = "metadata.dynatrace.com/k8s.workload.name" +) + +var ( + log = logd.Get().WithName("metadata-enrichment-pod-common") +) diff --git a/pkg/webhook/mutation/pod/common/metadata/mutator.go b/pkg/webhook/mutation/pod/common/metadata/mutator.go new file mode 100644 index 0000000000..5574156757 --- /dev/null +++ b/pkg/webhook/mutation/pod/common/metadata/mutator.go @@ -0,0 +1,46 @@ +package metadata + +import ( + maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" +) + +func IsEnabled(request *dtwebhook.BaseRequest) bool { + enabledOnPod := maputils.GetFieldBool(request.Pod.Annotations, AnnotationInject, + request.DynaKube.FeatureAutomaticInjection()) + enabledOnDynakube := request.DynaKube.MetadataEnrichmentEnabled() + + matchesNamespace := true // if no namespace selector is configured, we just pass set this to true + + if request.DynaKube.MetadataEnrichmentNamespaceSelector().Size() > 0 { + selector, _ := metav1.LabelSelectorAsSelector(request.DynaKube.MetadataEnrichmentNamespaceSelector()) + + matchesNamespace = selector.Matches(labels.Set(request.Namespace.Labels)) + } + + return matchesNamespace && enabledOnPod && enabledOnDynakube +} + +func IsInjected(request *dtwebhook.BaseRequest) bool { + return maputils.GetFieldBool(request.Pod.Annotations, AnnotationInjected, false) +} + +func SetInjectedAnnotation(pod *corev1.Pod) { + if pod.Annotations == nil { + pod.Annotations = make(map[string]string) + } + + pod.Annotations[AnnotationInjected] = "true" +} + +func SetWorkloadAnnotations(pod *corev1.Pod, workload *WorkloadInfo) { + if pod.Annotations == nil { + pod.Annotations = make(map[string]string) + } + + pod.Annotations[AnnotationWorkloadKind] = workload.Kind + pod.Annotations[AnnotationWorkloadName] = workload.Name +} diff --git a/pkg/webhook/mutation/pod/common/metadata/mutator_test.go b/pkg/webhook/mutation/pod/common/metadata/mutator_test.go new file mode 100644 index 0000000000..2a67281c5a --- /dev/null +++ b/pkg/webhook/mutation/pod/common/metadata/mutator_test.go @@ -0,0 +1,47 @@ +package metadata + +import ( + "testing" + + maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestSetInjectedAnnotation(t *testing.T) { + t.Run("should add annotation to nil map", func(t *testing.T) { + request := createTestMutationRequest(nil, nil) + + require.False(t, IsInjected(request.BaseRequest)) + SetInjectedAnnotation(request.Pod) + require.Len(t, request.Pod.Annotations, 1) + require.True(t, IsInjected(request.BaseRequest)) + }) +} + +func TestWorkloadAnnotations(t *testing.T) { + workloadInfoName := "workload-name" + workloadInfoKind := "workload-kind" + + t.Run("should add annotation to nil map", func(t *testing.T) { + request := createTestMutationRequest(nil, nil) + + require.Equal(t, "not-found", maputils.GetField(request.Pod.Annotations, AnnotationWorkloadName, "not-found")) + SetWorkloadAnnotations(request.Pod, &WorkloadInfo{Name: workloadInfoName, Kind: workloadInfoKind}) + require.Len(t, request.Pod.Annotations, 2) + assert.Equal(t, workloadInfoName, maputils.GetField(request.Pod.Annotations, AnnotationWorkloadName, "not-found")) + assert.Equal(t, workloadInfoKind, maputils.GetField(request.Pod.Annotations, AnnotationWorkloadKind, "not-found")) + }) + t.Run("should lower case kind annotation", func(t *testing.T) { + request := createTestMutationRequest(nil, nil) + objectMeta := &metav1.PartialObjectMetadata{ + ObjectMeta: metav1.ObjectMeta{Name: workloadInfoName}, + TypeMeta: metav1.TypeMeta{Kind: "SuperWorkload"}, + } + + SetWorkloadAnnotations(request.Pod, newWorkloadInfo(objectMeta)) + assert.Contains(t, request.Pod.Annotations, AnnotationWorkloadKind) + assert.Equal(t, "superworkload", request.Pod.Annotations[AnnotationWorkloadKind]) + }) +} diff --git a/pkg/webhook/mutation/pod/metadata/workload.go b/pkg/webhook/mutation/pod/common/metadata/workload.go similarity index 86% rename from pkg/webhook/mutation/pod/metadata/workload.go rename to pkg/webhook/mutation/pod/common/metadata/workload.go index 13566404eb..4517d32255 100644 --- a/pkg/webhook/mutation/pod/metadata/workload.go +++ b/pkg/webhook/mutation/pod/common/metadata/workload.go @@ -12,23 +12,23 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -type workloadInfo struct { - name string - kind string +type WorkloadInfo struct { + Name string + Kind string } -func newWorkloadInfo(partialObjectMetadata *metav1.PartialObjectMetadata) *workloadInfo { - return &workloadInfo{ - name: partialObjectMetadata.ObjectMeta.Name, +func newWorkloadInfo(partialObjectMetadata *metav1.PartialObjectMetadata) *WorkloadInfo { + return &WorkloadInfo{ + Name: partialObjectMetadata.ObjectMeta.Name, // workload kind in lower case according to dt semantic-dictionary // https://docs.dynatrace.com/docs/discover-dynatrace/references/semantic-dictionary/fields#kubernetes - kind: strings.ToLower(partialObjectMetadata.Kind), + Kind: strings.ToLower(partialObjectMetadata.Kind), } } -func (mut *Mutator) retrieveWorkload(request *dtwebhook.MutationRequest) (*workloadInfo, error) { - workload, err := findRootOwnerOfPod(request.Context, mut.metaClient, request.Pod, request.Namespace.Name) +func RetrieveWorkload(metaClient client.Client, request *dtwebhook.MutationRequest) (*WorkloadInfo, error) { + workload, err := findRootOwnerOfPod(request.Context, metaClient, request.Pod, request.Namespace.Name) if err != nil { return nil, err } @@ -36,7 +36,7 @@ func (mut *Mutator) retrieveWorkload(request *dtwebhook.MutationRequest) (*workl return workload, nil } -func findRootOwnerOfPod(ctx context.Context, clt client.Client, pod *corev1.Pod, namespace string) (*workloadInfo, error) { +func findRootOwnerOfPod(ctx context.Context, clt client.Client, pod *corev1.Pod, namespace string) (*WorkloadInfo, error) { podPartialMetadata := &metav1.PartialObjectMetadata{ TypeMeta: metav1.TypeMeta{ APIVersion: pod.APIVersion, diff --git a/pkg/webhook/mutation/pod/metadata/workload_test.go b/pkg/webhook/mutation/pod/common/metadata/workload_test.go similarity index 89% rename from pkg/webhook/mutation/pod/metadata/workload_test.go rename to pkg/webhook/mutation/pod/common/metadata/workload_test.go index d44dd40ed1..420008dfc7 100644 --- a/pkg/webhook/mutation/pod/metadata/workload_test.go +++ b/pkg/webhook/mutation/pod/common/metadata/workload_test.go @@ -73,8 +73,8 @@ func TestFindRootOwnerOfPod(t *testing.T) { workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) - assert.Equal(t, resourceName, workloadInfo.name) - assert.Equal(t, "daemonset", workloadInfo.kind) + assert.Equal(t, resourceName, workloadInfo.Name) + assert.Equal(t, "daemonset", workloadInfo.Kind) }) t.Run("should return Pod if owner references are empty", func(t *testing.T) { @@ -90,8 +90,8 @@ func TestFindRootOwnerOfPod(t *testing.T) { client := fake.NewClient(&pod) workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) - assert.Equal(t, resourceName, workloadInfo.name) - assert.Equal(t, "pod", workloadInfo.kind) + assert.Equal(t, resourceName, workloadInfo.Name) + assert.Equal(t, "pod", workloadInfo.Kind) }) t.Run("should be pod if owner is not well known", func(t *testing.T) { @@ -120,8 +120,8 @@ func TestFindRootOwnerOfPod(t *testing.T) { client := fake.NewClient(&pod, &secret) workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) - assert.Equal(t, resourceName, workloadInfo.name) - assert.Equal(t, "pod", workloadInfo.kind) + assert.Equal(t, resourceName, workloadInfo.Name) + assert.Equal(t, "pod", workloadInfo.Kind) }) t.Run("should be pod if no controller is the owner", func(t *testing.T) { @@ -145,8 +145,8 @@ func TestFindRootOwnerOfPod(t *testing.T) { client := fake.NewClient(&pod) workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) - assert.Equal(t, namespaceName, workloadInfo.name) - assert.Equal(t, "pod", workloadInfo.kind) + assert.Equal(t, namespaceName, workloadInfo.Name) + assert.Equal(t, "pod", workloadInfo.Kind) }) t.Run("should find the root owner of the pod if the root owner is unknown", func(t *testing.T) { pod := corev1.Pod{ @@ -203,8 +203,8 @@ func TestFindRootOwnerOfPod(t *testing.T) { workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) - assert.Equal(t, resourceName, workloadInfo.name) - assert.Equal(t, "deployment", workloadInfo.kind) + assert.Equal(t, resourceName, workloadInfo.Name) + assert.Equal(t, "deployment", workloadInfo.Kind) }) t.Run("should not make an api-call if workload is not well known", func(t *testing.T) { pod := corev1.Pod{ @@ -226,19 +226,10 @@ func TestFindRootOwnerOfPod(t *testing.T) { workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName) require.NoError(t, err) - assert.Equal(t, resourceName, workloadInfo.name) + assert.Equal(t, resourceName, workloadInfo.Name) }) } -func createTestWorkloadInfo(t *testing.T) *workloadInfo { - t.Helper() - - return &workloadInfo{ - kind: "test", - name: "test", - } -} - func createFailK8sClient(t *testing.T) client.Client { t.Helper() diff --git a/pkg/webhook/mutation/pod/common/oneagent/config.go b/pkg/webhook/mutation/pod/common/oneagent/config.go new file mode 100644 index 0000000000..350e30102a --- /dev/null +++ b/pkg/webhook/mutation/pod/common/oneagent/config.go @@ -0,0 +1,39 @@ +package oneagent + +import "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + +const ( + AnnotationPrefix = "oneagent" + // AnnotationOneAgentInject can be set at pod level to enable/disable OneAgent injection. + AnnotationInject = AnnotationPrefix + ".dynatrace.com/inject" + AnnotationInjected = AnnotationPrefix + ".dynatrace.com/injected" + AnnotationReason = AnnotationPrefix + ".dynatrace.com/reason" + + // AnnotationTechnologies can be set on a Pod to configure which code module technologies to download. It's set to + // "all" if not set. + AnnotationTechnologies = dynakube.AnnotationTechnologies + + // AnnotationInstallPath can be set on a Pod to configure on which directory the OneAgent will be available from, + // defaults to DefaultInstallPath if not set. + AnnotationInstallPath = "oneagent.dynatrace.com/install-path" + + // DefaultInstallPath is the default directory to install the app-only OneAgent package. + DefaultInstallPath = "/opt/dynatrace/oneagent-paas" + + PreloadEnv = "LD_PRELOAD" + NetworkZoneEnv = "DT_NETWORK_ZONE" + DynatraceMetadataEnv = "DT_DEPLOYMENT_METADATA" + + ReleaseVersionEnv = "DT_RELEASE_VERSION" + ReleaseProductEnv = "DT_RELEASE_PRODUCT" + ReleaseStageEnv = "DT_RELEASE_STAGE" + ReleaseBuildVersionEnv = "DT_RELEASE_BUILD_VERSION" + + EmptyConnectionInfoReason = "EmptyConnectionInfo" + UnknownCodeModuleReason = "UnknownCodeModule" + EmptyTenantUUIDReason = "EmptyTenantUUID" + + DefaultUser int64 = 1001 + DefaultGroup int64 = 1001 + RootUserGroup int64 = 0 +) diff --git a/pkg/webhook/mutation/pod/oneagent/env.go b/pkg/webhook/mutation/pod/common/oneagent/env.go similarity index 55% rename from pkg/webhook/mutation/pod/oneagent/env.go rename to pkg/webhook/mutation/pod/common/oneagent/env.go index 17a99e56e2..9a98d7184d 100644 --- a/pkg/webhook/mutation/pod/oneagent/env.go +++ b/pkg/webhook/mutation/pod/common/oneagent/env.go @@ -11,43 +11,30 @@ import ( corev1 "k8s.io/api/core/v1" ) -func addPreloadEnv(container *corev1.Container, installPath string) { - preloadPath := filepath.Join(installPath, consts.LibAgentProcPath) - - ldPreloadEnv := env.FindEnvVar(container.Env, preloadEnv) - if ldPreloadEnv != nil { - if strings.Contains(ldPreloadEnv.Value, installPath) { - return - } - - ldPreloadEnv.Value = concatPreloadPaths(ldPreloadEnv.Value, preloadPath) - } else { - container.Env = append(container.Env, - corev1.EnvVar{ - Name: preloadEnv, - Value: preloadPath, - }) +func AddDeploymentMetadataEnv(container *corev1.Container, dk dynakube.DynaKube) { + if env.IsIn(container.Env, DynatraceMetadataEnv) { + return } -} -func concatPreloadPaths(originalPaths, additionalPath string) string { - if strings.Contains(originalPaths, " ") { - return originalPaths + " " + additionalPath - } else { - return originalPaths + ":" + additionalPath - } + deploymentMetadata := deploymentmetadata.NewDeploymentMetadata(dk.Status.KubeSystemUUID, deploymentmetadata.GetOneAgentDeploymentType(dk)) + container.Env = append(container.Env, + corev1.EnvVar{ + Name: DynatraceMetadataEnv, + Value: deploymentMetadata.AsString(), + }) } -func addNetworkZoneEnv(container *corev1.Container, networkZone string) { +func AddNetworkZoneEnv(container *corev1.Container, networkZone string) { container.Env = append(container.Env, corev1.EnvVar{ - Name: networkZoneEnv, + Name: NetworkZoneEnv, Value: networkZone, }, ) } -func addVersionDetectionEnvs(container *corev1.Container, labelMapping VersionLabelMapping) { +func AddVersionDetectionEnvs(container *corev1.Container, namespace corev1.Namespace) { + labelMapping := NewVersionLabelMapping(namespace) for envName, fieldPath := range labelMapping { if env.IsIn(container.Env, envName) { continue @@ -66,26 +53,29 @@ func addVersionDetectionEnvs(container *corev1.Container, labelMapping VersionLa } } -func addInstallerInitEnvs(initContainer *corev1.Container, installer installerInfo) { - initContainer.Env = append(initContainer.Env, - corev1.EnvVar{Name: consts.AgentInstallerFlavorEnv, Value: installer.flavor}, // TODO: is this needed - corev1.EnvVar{Name: consts.AgentInstallerTechEnv, Value: installer.technologies}, - corev1.EnvVar{Name: consts.AgentInstallPathEnv, Value: installer.installPath}, - corev1.EnvVar{Name: consts.AgentInstallerUrlEnv, Value: installer.installerURL}, - corev1.EnvVar{Name: consts.AgentInstallerVersionEnv, Value: installer.version}, - corev1.EnvVar{Name: consts.AgentInjectedEnv, Value: "true"}, - ) -} +func AddPreloadEnv(container *corev1.Container, installPath string) { + preloadPath := filepath.Join(installPath, consts.LibAgentProcPath) -func addDeploymentMetadataEnv(container *corev1.Container, dk dynakube.DynaKube, clusterID string) { - if env.IsIn(container.Env, dynatraceMetadataEnv) { - return + ldPreloadEnv := env.FindEnvVar(container.Env, PreloadEnv) + if ldPreloadEnv != nil { + if strings.Contains(ldPreloadEnv.Value, installPath) { + return + } + + ldPreloadEnv.Value = concatPreloadPaths(ldPreloadEnv.Value, preloadPath) + } else { + container.Env = append(container.Env, + corev1.EnvVar{ + Name: PreloadEnv, + Value: preloadPath, + }) } +} - deploymentMetadata := deploymentmetadata.NewDeploymentMetadata(clusterID, deploymentmetadata.GetOneAgentDeploymentType(dk)) - container.Env = append(container.Env, - corev1.EnvVar{ - Name: dynatraceMetadataEnv, - Value: deploymentMetadata.AsString(), - }) +func concatPreloadPaths(originalPaths, additionalPath string) string { + if strings.Contains(originalPaths, " ") { + return originalPaths + " " + additionalPath + } else { + return originalPaths + ":" + additionalPath + } } diff --git a/pkg/webhook/mutation/pod/oneagent/env_test.go b/pkg/webhook/mutation/pod/common/oneagent/env_test.go similarity index 70% rename from pkg/webhook/mutation/pod/oneagent/env_test.go rename to pkg/webhook/mutation/pod/common/oneagent/env_test.go index c6850be1c7..8fd5cb1808 100644 --- a/pkg/webhook/mutation/pod/oneagent/env_test.go +++ b/pkg/webhook/mutation/pod/common/oneagent/env_test.go @@ -18,7 +18,7 @@ func TestAddPreloadEnv(t *testing.T) { t.Run("Add preload env", func(t *testing.T) { container := createContainerWithPreloadEnv("") - addPreloadEnv(container, installPath) + AddPreloadEnv(container, installPath) verifyContainerWithPreloadEnv(t, container, installPath) }) @@ -26,7 +26,7 @@ func TestAddPreloadEnv(t *testing.T) { existingPath := "path/user" container := createContainerWithPreloadEnv(existingPath) - addPreloadEnv(container, installPath) + AddPreloadEnv(container, installPath) verifyContainerWithPreloadEnv(t, container, existingPath+":"+installPath) }) @@ -34,7 +34,7 @@ func TestAddPreloadEnv(t *testing.T) { existingPath := "path1/user path2/user" container := createContainerWithPreloadEnv(existingPath) - addPreloadEnv(container, installPath) + AddPreloadEnv(container, installPath) verifyContainerWithPreloadEnv(t, container, existingPath+" "+installPath) }) @@ -43,7 +43,7 @@ func TestAddPreloadEnv(t *testing.T) { existingPath += " " + installPath container := createContainerWithPreloadEnv(existingPath) - addPreloadEnv(container, installPath) + AddPreloadEnv(container, installPath) verifyContainerWithPreloadEnv(t, container, existingPath) }) @@ -60,7 +60,7 @@ func createContainerWithPreloadEnv(existingPath string) *corev1.Container { } if existingPath != "" { container.Env = append(container.Env, corev1.EnvVar{ - Name: preloadEnv, + Name: PreloadEnv, Value: existingPath, }) } @@ -70,7 +70,7 @@ func createContainerWithPreloadEnv(existingPath string) *corev1.Container { func verifyContainerWithPreloadEnv(t *testing.T, container *corev1.Container, expectedPath string) { require.NotEmpty(t, container.Env) - containerEnv := env.FindEnvVar(container.Env, preloadEnv) + containerEnv := env.FindEnvVar(container.Env, PreloadEnv) require.NotNil(t, containerEnv) assert.Contains(t, containerEnv.Value, expectedPath) } @@ -80,30 +80,17 @@ func TestAddNetworkZoneEnv(t *testing.T) { container := &corev1.Container{} networkZone := "testZone" - addNetworkZoneEnv(container, networkZone) + AddNetworkZoneEnv(container, networkZone) require.Len(t, container.Env, 1) - assert.Equal(t, networkZoneEnv, container.Env[0].Name) + assert.Equal(t, NetworkZoneEnv, container.Env[0].Name) assert.Equal(t, networkZone, container.Env[0].Value) }) } -func TestAddInstallerInitEnvs(t *testing.T) { - t.Run("Add installer init env", func(t *testing.T) { - container := &corev1.Container{} - installerInfo := getTestInstallerInfo() - addInstallerInitEnvs(container, installerInfo) - require.Len(t, container.Env, expectedBaseInitContainerEnvCount) - assert.Equal(t, installerInfo.flavor, container.Env[0].Value) - assert.Equal(t, installerInfo.technologies, container.Env[1].Value) - assert.Equal(t, installerInfo.installPath, container.Env[2].Value) - assert.Equal(t, installerInfo.installerURL, container.Env[3].Value) - assert.Equal(t, installerInfo.version, container.Env[4].Value) - assert.Equal(t, "true", container.Env[5].Value) - }) -} - func TestAddDeploymentMetadataEnv(t *testing.T) { + clusterID := "cluster-id" + t.Run("Add cloudNative deployment metadata env", func(t *testing.T) { container := &corev1.Container{} dk := dynakube.DynaKube{ @@ -112,10 +99,13 @@ func TestAddDeploymentMetadataEnv(t *testing.T) { CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, }, }, + Status: dynakube.DynaKubeStatus{ + KubeSystemUUID: clusterID, + }, } - addDeploymentMetadataEnv(container, dk, testClusterID) + AddDeploymentMetadataEnv(container, dk) require.Len(t, container.Env, 1) - assert.Contains(t, container.Env[0].Value, testClusterID) + assert.Contains(t, container.Env[0].Value, clusterID) assert.Contains(t, container.Env[0].Value, deploymentmetadata.CloudNativeDeploymentType) }) @@ -127,19 +117,22 @@ func TestAddDeploymentMetadataEnv(t *testing.T) { ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, }, }, + Status: dynakube.DynaKubeStatus{ + KubeSystemUUID: clusterID, + }, } - addDeploymentMetadataEnv(container, dk, testClusterID) + AddDeploymentMetadataEnv(container, dk) require.Len(t, container.Env, 1) - assert.Contains(t, container.Env[0].Value, testClusterID) + assert.Contains(t, container.Env[0].Value, clusterID) assert.Contains(t, container.Env[0].Value, deploymentmetadata.ApplicationMonitoringDeploymentType) }) } -func TestAddVersionDetectionEnvs(t *testing.T) { +func TestAddVersionDetection(t *testing.T) { t.Run("adds defaults", func(t *testing.T) { container := &corev1.Container{} - addVersionDetectionEnvs(container, defaultVersionLabelMapping) + AddVersionDetectionEnvs(container, getTestNamespace(defaultVersionLabelMapping)) require.Len(t, container.Env, len(defaultVersionLabelMapping)) @@ -153,12 +146,12 @@ func TestAddVersionDetectionEnvs(t *testing.T) { testProduct := "testy" container := &corev1.Container{ Env: []corev1.EnvVar{ - {Name: releaseVersionEnv, Value: testVersion}, - {Name: releaseProductEnv, Value: testProduct}, + {Name: ReleaseVersionEnv, Value: testVersion}, + {Name: ReleaseProductEnv, Value: testProduct}, }, } - addVersionDetectionEnvs(container, defaultVersionLabelMapping) + AddVersionDetectionEnvs(container, getTestNamespace(defaultVersionLabelMapping)) require.Len(t, container.Env, 2) assert.Equal(t, testVersion, container.Env[0].Value) @@ -169,14 +162,14 @@ func TestAddVersionDetectionEnvs(t *testing.T) { testVersion := "1.2.3" container := &corev1.Container{ Env: []corev1.EnvVar{ - {Name: releaseVersionEnv, Value: testVersion}, + {Name: ReleaseVersionEnv, Value: testVersion}, }, } - addVersionDetectionEnvs(container, defaultVersionLabelMapping) + AddVersionDetectionEnvs(container, getTestNamespace(defaultVersionLabelMapping)) require.Len(t, container.Env, 2) assert.Equal(t, testVersion, container.Env[0].Value) - assert.Equal(t, defaultVersionLabelMapping[releaseProductEnv], container.Env[1].ValueFrom.FieldRef.FieldPath) + assert.Equal(t, defaultVersionLabelMapping[ReleaseProductEnv], container.Env[1].ValueFrom.FieldRef.FieldPath) }) } diff --git a/pkg/webhook/mutation/pod/common/oneagent/init.go b/pkg/webhook/mutation/pod/common/oneagent/init.go new file mode 100644 index 0000000000..b4d18024b1 --- /dev/null +++ b/pkg/webhook/mutation/pod/common/oneagent/init.go @@ -0,0 +1,17 @@ +package oneagent + +import corev1 "k8s.io/api/core/v1" + +func HasPodUserSet(ctx *corev1.PodSecurityContext) bool { + return ctx != nil && ctx.RunAsUser != nil +} + +func HasPodGroupSet(ctx *corev1.PodSecurityContext) bool { + return ctx != nil && ctx.RunAsGroup != nil +} + +func IsNonRoot(ctx *corev1.SecurityContext) bool { + return ctx != nil && + (ctx.RunAsUser != nil && *ctx.RunAsUser != RootUserGroup) && + (ctx.RunAsGroup != nil && *ctx.RunAsGroup != RootUserGroup) +} diff --git a/pkg/webhook/mutation/pod/common/oneagent/mutator.go b/pkg/webhook/mutation/pod/common/oneagent/mutator.go new file mode 100644 index 0000000000..5eb8c9166c --- /dev/null +++ b/pkg/webhook/mutation/pod/common/oneagent/mutator.go @@ -0,0 +1,45 @@ +package oneagent + +import ( + maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" +) + +func IsEnabled(request *dtwebhook.BaseRequest) bool { + enabledOnPod := maputils.GetFieldBool(request.Pod.Annotations, AnnotationInject, request.DynaKube.FeatureAutomaticInjection()) + enabledOnDynakube := request.DynaKube.OneAgent().GetNamespaceSelector() != nil + + matchesNamespaceSelector := true // if no namespace selector is configured, we just pass set this to true + + if request.DynaKube.OneAgent().GetNamespaceSelector().Size() > 0 { + selector, _ := metav1.LabelSelectorAsSelector(request.DynaKube.OneAgent().GetNamespaceSelector()) + + matchesNamespaceSelector = selector.Matches(labels.Set(request.Namespace.Labels)) + } + + return matchesNamespaceSelector && enabledOnPod && enabledOnDynakube +} + +func IsInjected(request *dtwebhook.BaseRequest) bool { + return maputils.GetFieldBool(request.Pod.Annotations, AnnotationInjected, false) +} + +func SetInjectedAnnotation(pod *corev1.Pod) { + if pod.Annotations == nil { + pod.Annotations = make(map[string]string) + } + + pod.Annotations[AnnotationInjected] = "true" +} + +func SetNotInjectedAnnotations(pod *corev1.Pod, reason string) { + if pod.Annotations == nil { + pod.Annotations = make(map[string]string) + } + + pod.Annotations[AnnotationInjected] = "false" + pod.Annotations[AnnotationReason] = reason +} diff --git a/pkg/webhook/mutation/pod/oneagent/versionlabel.go b/pkg/webhook/mutation/pod/common/oneagent/versionlabel.go similarity index 74% rename from pkg/webhook/mutation/pod/oneagent/versionlabel.go rename to pkg/webhook/mutation/pod/common/oneagent/versionlabel.go index 094f31fb32..01ce69e5a8 100644 --- a/pkg/webhook/mutation/pod/oneagent/versionlabel.go +++ b/pkg/webhook/mutation/pod/common/oneagent/versionlabel.go @@ -14,23 +14,23 @@ const ( var ( defaultVersionLabelMapping = VersionLabelMapping{ - releaseVersionEnv: "metadata.labels['app.kubernetes.io/version']", - releaseProductEnv: "metadata.labels['app.kubernetes.io/part-of']", + ReleaseVersionEnv: "metadata.labels['app.kubernetes.io/version']", + ReleaseProductEnv: "metadata.labels['app.kubernetes.io/part-of']", } ) type VersionLabelMapping map[string]string -func newVersionLabelMapping(namespace corev1.Namespace) VersionLabelMapping { +func NewVersionLabelMapping(namespace corev1.Namespace) VersionLabelMapping { return mergeMappingWithDefault(getMappingFromNamespace(namespace)) } func getMappingFromNamespace(namespace corev1.Namespace) VersionLabelMapping { annotationLabelMap := map[string]string{ - versionMappingAnnotationName: releaseVersionEnv, - productMappingAnnotationName: releaseProductEnv, - stageMappingAnnotationName: releaseStageEnv, - buildVersionAnnotationName: releaseBuildVersionEnv, + versionMappingAnnotationName: ReleaseVersionEnv, + productMappingAnnotationName: ReleaseProductEnv, + stageMappingAnnotationName: ReleaseStageEnv, + buildVersionAnnotationName: ReleaseBuildVersionEnv, } versionLabelMapping := VersionLabelMapping{} diff --git a/pkg/webhook/mutation/pod/common/oneagent/versionlabel_test.go b/pkg/webhook/mutation/pod/common/oneagent/versionlabel_test.go new file mode 100644 index 0000000000..6d01594f3f --- /dev/null +++ b/pkg/webhook/mutation/pod/common/oneagent/versionlabel_test.go @@ -0,0 +1,121 @@ +package oneagent + +import ( + "testing" + + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestAddVersionDetectionEnvs(t *testing.T) { + const ( + customVersionValue = "my awesome custom version" + customProductValue = "my awesome custom product" + customReleaseStageValue = "my awesome custom stage" + customBuildVersionValue = "my awesome custom build version" + customVersionAnnotationName = "custom-version" + customProductAnnotationName = "custom-product" + customStageAnnotationName = "custom-stage" + customBuildVersionAnnotationName = "custom-build-version" + customVersionFieldPath = "metadata.podAnnotations['" + customVersionAnnotationName + "']" + customProductFieldPath = "metadata.podAnnotations['" + customProductAnnotationName + "']" + customStageFieldPath = "metadata.podAnnotations['" + customStageAnnotationName + "']" + customBuildVersionFieldPath = "metadata.podAnnotations['" + customBuildVersionAnnotationName + "']" + ) + + t.Run("version and product env vars are set using values referenced in namespace podAnnotations", func(t *testing.T) { + namespaceAnnotations := map[string]string{ + versionMappingAnnotationName: customVersionFieldPath, + productMappingAnnotationName: customProductFieldPath, + } + expectedMappings := map[string]string{ + ReleaseVersionEnv: customVersionFieldPath, + ReleaseProductEnv: customProductFieldPath, + } + unexpectedMappingsKeys := []string{ReleaseStageEnv, ReleaseBuildVersionEnv} + + doTestMappings(t, namespaceAnnotations, expectedMappings, unexpectedMappingsKeys) + }) + t.Run("only version env vars is set using value referenced in namespace podAnnotations, product is default", func(t *testing.T) { + namespaceAnnotations := map[string]string{ + versionMappingAnnotationName: customVersionFieldPath, + } + expectedMappings := map[string]string{ + ReleaseVersionEnv: customVersionFieldPath, + ReleaseProductEnv: defaultVersionLabelMapping[ReleaseProductEnv], + } + unexpectedMappingsKeys := []string{ReleaseStageEnv, ReleaseBuildVersionEnv} + + doTestMappings(t, namespaceAnnotations, expectedMappings, unexpectedMappingsKeys) + }) + t.Run("optional env vars (stage, build-version) are set using values referenced in namespace podAnnotations, default ones remain default", func(t *testing.T) { + namespaceAnnotations := map[string]string{ + stageMappingAnnotationName: customStageFieldPath, + buildVersionAnnotationName: customBuildVersionFieldPath, + } + expectedMappings := map[string]string{ + ReleaseVersionEnv: defaultVersionLabelMapping[ReleaseVersionEnv], + ReleaseProductEnv: defaultVersionLabelMapping[ReleaseProductEnv], + ReleaseStageEnv: customStageFieldPath, + ReleaseBuildVersionEnv: customBuildVersionFieldPath, + } + + doTestMappings(t, namespaceAnnotations, expectedMappings, nil) + }) + t.Run("all env vars are namespace-podAnnotations driven", func(t *testing.T) { + namespaceAnnotations := map[string]string{ + versionMappingAnnotationName: customVersionFieldPath, + productMappingAnnotationName: customProductFieldPath, + stageMappingAnnotationName: customStageFieldPath, + buildVersionAnnotationName: customBuildVersionFieldPath, + } + expectedMappings := map[string]string{ + ReleaseVersionEnv: customVersionFieldPath, + ReleaseProductEnv: customProductFieldPath, + ReleaseStageEnv: customStageFieldPath, + ReleaseBuildVersionEnv: customBuildVersionFieldPath, + } + + doTestMappings(t, namespaceAnnotations, expectedMappings, nil) + }) +} + +func doTestMappings(t *testing.T, namespaceAnnotations map[string]string, expectedMappings map[string]string, unexpectedMappingsKeys []string) { + container := corev1.Container{} + + AddVersionDetectionEnvs(&container, getTestNamespace(namespaceAnnotations)) + + assertContainsMappings(t, expectedMappings, container) + assertNotContainsMappings(t, unexpectedMappingsKeys, container) +} + +func assertContainsMappings(t *testing.T, expectedMappings map[string]string, container corev1.Container) { + for envName, fieldPath := range expectedMappings { + assert.Contains(t, container.Env, corev1.EnvVar{ + Name: envName, + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + APIVersion: "", + FieldPath: fieldPath, + }, + }, + }) + } +} + +func assertNotContainsMappings(t *testing.T, unexpectedMappingKeys []string, container corev1.Container) { + for _, env := range container.Env { + assert.NotContains(t, unexpectedMappingKeys, env.Name) + } +} + +func getTestNamespace(annotations map[string]string) corev1.Namespace { + return corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-ns", + Labels: map[string]string{}, + Annotations: annotations, + }, + } +} diff --git a/pkg/webhook/mutation/pod/config.go b/pkg/webhook/mutation/pod/config.go index 5559b1a80c..03bb685337 100644 --- a/pkg/webhook/mutation/pod/config.go +++ b/pkg/webhook/mutation/pod/config.go @@ -4,17 +4,6 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/logd" ) -const ( - injectEvent = "Inject" - updatePodEvent = "UpdatePod" - IncompatibleCRDEvent = "IncompatibleCRDPresent" - missingDynakubeEvent = "MissingDynakube" - - defaultUser int64 = 1001 - defaultGroup int64 = 1001 - rootUserGroup int64 = 0 -) - var ( log = logd.Get().WithName("pod-mutation") ) diff --git a/pkg/webhook/mutation/pod/metadata/annotations.go b/pkg/webhook/mutation/pod/metadata/annotations.go deleted file mode 100644 index 27c48c22f1..0000000000 --- a/pkg/webhook/mutation/pod/metadata/annotations.go +++ /dev/null @@ -1,83 +0,0 @@ -package metadata - -import ( - "encoding/json" - "strings" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/consts" - dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" - corev1 "k8s.io/api/core/v1" -) - -func propagateMetadataAnnotations(request *dtwebhook.MutationRequest) { - copyMetadataFromNamespace(request.Pod, request.Namespace, request.DynaKube) - addMetadataToInitEnv(request.Pod, request.InstallContainer) -} - -func copyMetadataFromNamespace(pod *corev1.Pod, namespace corev1.Namespace, dk dynakube.DynaKube) { - copyMetadataAccordingToCustomRules(pod, namespace, dk) - copyMetadataAccordingToPrefix(pod, namespace) -} - -func copyMetadataAccordingToPrefix(pod *corev1.Pod, namespace corev1.Namespace) { - for key, value := range namespace.Annotations { - if strings.HasPrefix(key, dynakube.MetadataPrefix) { - setPodAnnotationIfNotExists(pod, key, value) - } - } -} - -func copyMetadataAccordingToCustomRules(pod *corev1.Pod, namespace corev1.Namespace, dk dynakube.DynaKube) { - for _, rule := range dk.Status.MetadataEnrichment.Rules { - if rule.Target == "" { - log.Info("rule without target set found, ignoring", "source", rule.Source, "type", rule.Type) - - continue - } - - var valueFromNamespace string - - var exists bool - - switch rule.Type { - case dynakube.EnrichmentLabelRule: - valueFromNamespace, exists = namespace.Labels[rule.Source] - case dynakube.EnrichmentAnnotationRule: - valueFromNamespace, exists = namespace.Annotations[rule.Source] - } - - if exists { - setPodAnnotationIfNotExists(pod, rule.ToAnnotationKey(), valueFromNamespace) - } - } -} - -func setPodAnnotationIfNotExists(pod *corev1.Pod, key, value string) { - if pod.Annotations == nil { - pod.Annotations = make(map[string]string) - } - - if _, ok := pod.Annotations[key]; !ok { - pod.Annotations[key] = value - } -} - -func addMetadataToInitEnv(pod *corev1.Pod, installContainer *corev1.Container) { - metadataAnnotations := map[string]string{} - - for key, value := range pod.Annotations { - if !strings.HasPrefix(key, dynakube.MetadataPrefix) { - continue - } - - split := strings.Split(key, dynakube.MetadataPrefix) - metadataAnnotations[split[1]] = value - } - - workloadAnnotationsJson, _ := json.Marshal(metadataAnnotations) - installContainer.Env = append(installContainer.Env, - corev1.EnvVar{ - Name: consts.EnrichmentWorkloadAnnotationsEnv, Value: string(workloadAnnotationsJson)}, - ) -} diff --git a/pkg/webhook/mutation/pod/oneagent/annotations.go b/pkg/webhook/mutation/pod/oneagent/annotations.go deleted file mode 100644 index 99316eb693..0000000000 --- a/pkg/webhook/mutation/pod/oneagent/annotations.go +++ /dev/null @@ -1,45 +0,0 @@ -package oneagent - -import ( - "net/url" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" - maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" - dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" - corev1 "k8s.io/api/core/v1" -) - -type installerInfo struct { - flavor string - technologies string - installPath string - installerURL string - version string -} - -func setInjectedAnnotation(pod *corev1.Pod) { - if pod.Annotations == nil { - pod.Annotations = make(map[string]string) - } - - pod.Annotations[dtwebhook.AnnotationOneAgentInjected] = "true" -} - -func setNotInjectedAnnotations(pod *corev1.Pod, reason string) { - if pod.Annotations == nil { - pod.Annotations = make(map[string]string) - } - - pod.Annotations[dtwebhook.AnnotationOneAgentInjected] = "false" - pod.Annotations[dtwebhook.AnnotationOneAgentReason] = reason -} - -func getInstallerInfo(pod *corev1.Pod, dk dynakube.DynaKube) installerInfo { - return installerInfo{ - flavor: maputils.GetField(pod.Annotations, dtwebhook.AnnotationFlavor, ""), - technologies: url.QueryEscape(maputils.GetField(pod.Annotations, dtwebhook.AnnotationTechnologies, "all")), - installPath: maputils.GetField(pod.Annotations, dtwebhook.AnnotationInstallPath, dtwebhook.DefaultInstallPath), - installerURL: maputils.GetField(pod.Annotations, dtwebhook.AnnotationInstallerUrl, ""), - version: dk.OneAgent().GetCodeModulesVersion(), - } -} diff --git a/pkg/webhook/mutation/pod/register.go b/pkg/webhook/mutation/pod/register.go index bb045349ad..520a51ba4d 100644 --- a/pkg/webhook/mutation/pod/register.go +++ b/pkg/webhook/mutation/pod/register.go @@ -9,8 +9,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/util/kubesystem" "github.com/Dynatrace/dynatrace-operator/pkg/util/oneagentapm" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" - "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/metadata" - oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -20,7 +21,7 @@ import ( ) func registerInjectEndpoint(ctx context.Context, mgr manager.Manager, webhookNamespace string, webhookPodName string) error { - eventRecorder := newPodMutatorEventRecorder(mgr.GetEventRecorderFor("dynatrace-webhook")) + eventRecorder := events.NewRecorder(mgr.GetEventRecorderFor("dynatrace-webhook")) kubeConfig := mgr.GetConfig() kubeClient := mgr.GetClient() apiReader := mgr.GetAPIReader() @@ -36,7 +37,7 @@ func registerInjectEndpoint(ctx context.Context, mgr manager.Manager, webhookNam } if apmExists { - eventRecorder.sendOneAgentAPMWarningEvent(webhookPod) + eventRecorder.SendOneAgentAPMWarningEvent(webhookPod) return errors.New("OneAgentAPM object detected - the Dynatrace webhook will not inject until the deprecated OneAgent Operator has been fully uninstalled") } @@ -58,28 +59,12 @@ func registerInjectEndpoint(ctx context.Context, mgr manager.Manager, webhookNam } mgr.GetWebhookServer().Register("/inject", &webhooks.Admission{Handler: &webhook{ + v1: v1.NewInjector(apiReader, kubeClient, metaClient, eventRecorder, clusterID, webhookPodImage, webhookNamespace), + v2: v2.NewInjector(apiReader, metaClient, eventRecorder), apiReader: apiReader, webhookNamespace: webhookNamespace, - webhookImage: webhookPodImage, deployedViaOLM: kubesystem.IsDeployedViaOlm(*webhookPod), - clusterID: clusterID, - recorder: eventRecorder, - mutators: []dtwebhook.PodMutator{ - oamutation.NewMutator( - webhookPodImage, - clusterID, - webhookNamespace, - kubeClient, - apiReader, - ), - metadata.NewMutator( - webhookNamespace, - kubeClient, - apiReader, - metaClient, - ), - }, - decoder: admission.NewDecoder(mgr.GetScheme()), + decoder: admission.NewDecoder(mgr.GetScheme()), }}) log.Info("registered /inject endpoint") diff --git a/pkg/webhook/mutation/pod/request.go b/pkg/webhook/mutation/pod/request.go index 45bf3b9806..2b00b89809 100644 --- a/pkg/webhook/mutation/pod/request.go +++ b/pkg/webhook/mutation/pod/request.go @@ -83,7 +83,7 @@ func (wh *webhook) getDynakube(ctx context.Context, dynakubeName string) (*dynak err := wh.apiReader.Get(ctx, client.ObjectKey{Name: dynakubeName, Namespace: wh.webhookNamespace}, &dk) if k8serrors.IsNotFound(err) { - wh.recorder.sendMissingDynaKubeEvent(wh.webhookNamespace, dynakubeName) + wh.recorder.SendMissingDynaKubeEvent(wh.webhookNamespace, dynakubeName) return nil, err } else if err != nil { diff --git a/pkg/webhook/mutation/pod/request_test.go b/pkg/webhook/mutation/pod/request_test.go index b7c7ed29a9..01fbcfdcfc 100644 --- a/pkg/webhook/mutation/pod/request_test.go +++ b/pkg/webhook/mutation/pod/request_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + webhookmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" admissionv1 "k8s.io/api/admission/v1" @@ -31,7 +32,8 @@ func TestCreateMutationRequestBase(t *testing.T) { t.Run("should create a mutation request", func(t *testing.T) { dk := getTestDynakube() podWebhook := createTestWebhook( - []dtwebhook.PodMutator{}, + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), []client.Object{ getTestNamespace(), getTestPod(), @@ -53,7 +55,8 @@ func TestCreateMutationRequestBase(t *testing.T) { func TestGetPodFromRequest(t *testing.T) { t.Run("should return the pod struct", func(t *testing.T) { podWebhook := createTestWebhook( - []dtwebhook.PodMutator{}, + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), []client.Object{}, ) expected := getTestPod() @@ -68,7 +71,8 @@ func TestGetNamespaceFromRequest(t *testing.T) { t.Run("should return the namespace struct", func(t *testing.T) { expected := getTestNamespace() podWebhook := createTestWebhook( - []dtwebhook.PodMutator{}, + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), []client.Object{expected}, ) @@ -91,7 +95,8 @@ func TestGetDynakube(t *testing.T) { t.Run("should return the dynakube struct", func(t *testing.T) { expected := getTestDynakube() podWebhook := createTestWebhook( - []dtwebhook.PodMutator{}, + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), []client.Object{expected}, ) @@ -106,10 +111,6 @@ func createTestMutationRequest(dk *dynakube.DynaKube) *dtwebhook.MutationRequest return dtwebhook.NewMutationRequest(context.Background(), *getTestNamespace(), nil, getTestPod(), *dk) } -func createTestMutationRequestWithInjectedPod(dk *dynakube.DynaKube) *dtwebhook.MutationRequest { - return dtwebhook.NewMutationRequest(context.Background(), *getTestNamespace(), nil, getInjectedPod(), *dk) -} - func createTestAdmissionRequest(pod *corev1.Pod) *admission.Request { basePodBytes, _ := json.Marshal(pod) @@ -155,42 +156,6 @@ func getTestPod() *corev1.Pod { } } -func getInjectedPod() *corev1.Pod { - pod := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: testPodName, - Namespace: testNamespaceName, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "container", - Image: "alpine", - SecurityContext: getTestSecurityContext(), - }, - }, - InitContainers: []corev1.Container{ - { - Name: "init-container", - Image: "alpine", - }, - }, - Volumes: []corev1.Volume{ - { - Name: "volume", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - }, - } - installContainer := createInstallInitContainerBase("test", "test", pod, *getTestDynakube()) - pod.Spec.InitContainers = append(pod.Spec.InitContainers, *installContainer) - - return pod -} - func getTestNamespace() *corev1.Namespace { return &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/webhook/mutation/pod/v1/config.go b/pkg/webhook/mutation/pod/v1/config.go new file mode 100644 index 0000000000..5122e0713a --- /dev/null +++ b/pkg/webhook/mutation/pod/v1/config.go @@ -0,0 +1,9 @@ +package v1 + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/logd" +) + +var ( + log = logd.Get().WithName("v1-pod-mutation") +) diff --git a/pkg/webhook/mutation/pod/init_container.go b/pkg/webhook/mutation/pod/v1/init.go similarity index 90% rename from pkg/webhook/mutation/pod/init_container.go rename to pkg/webhook/mutation/pod/v1/init.go index f519ca7fb6..86dd859a45 100644 --- a/pkg/webhook/mutation/pod/init_container.go +++ b/pkg/webhook/mutation/pod/v1/init.go @@ -1,4 +1,4 @@ -package pod +package v1 import ( "encoding/json" @@ -12,8 +12,9 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/resources" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" - "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/metadata" - oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1/metadata" + oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1/oneagent" corev1 "k8s.io/api/core/v1" "k8s.io/utils/ptr" ) @@ -85,14 +86,14 @@ func combineSecurityContexts(baseSecurityCtx corev1.SecurityContext, pod corev1. containerSecurityCtx := pod.Spec.Containers[0].SecurityContext podSecurityCtx := pod.Spec.SecurityContext - baseSecurityCtx.RunAsUser = ptr.To(defaultUser) - baseSecurityCtx.RunAsGroup = ptr.To(defaultGroup) + baseSecurityCtx.RunAsUser = ptr.To(oacommon.DefaultUser) + baseSecurityCtx.RunAsGroup = ptr.To(oacommon.DefaultGroup) - if hasPodUserSet(podSecurityCtx) { + if oacommon.HasPodUserSet(podSecurityCtx) { baseSecurityCtx.RunAsUser = podSecurityCtx.RunAsUser } - if hasPodGroupSet(podSecurityCtx) { + if oacommon.HasPodGroupSet(podSecurityCtx) { baseSecurityCtx.RunAsGroup = podSecurityCtx.RunAsGroup } @@ -104,19 +105,11 @@ func combineSecurityContexts(baseSecurityCtx corev1.SecurityContext, pod corev1. baseSecurityCtx.RunAsGroup = containerSecurityCtx.RunAsGroup } - baseSecurityCtx.RunAsNonRoot = ptr.To(isNonRoot(&baseSecurityCtx)) + baseSecurityCtx.RunAsNonRoot = ptr.To(oacommon.IsNonRoot(&baseSecurityCtx)) return &baseSecurityCtx } -func hasPodUserSet(ctx *corev1.PodSecurityContext) bool { - return ctx != nil && ctx.RunAsUser != nil -} - -func hasPodGroupSet(ctx *corev1.PodSecurityContext) bool { - return ctx != nil && ctx.RunAsGroup != nil -} - func hasContainerUserSet(ctx *corev1.SecurityContext) bool { return ctx != nil && ctx.RunAsUser != nil } @@ -125,12 +118,6 @@ func hasContainerGroupSet(ctx *corev1.SecurityContext) bool { return ctx != nil && ctx.RunAsGroup != nil } -func isNonRoot(ctx *corev1.SecurityContext) bool { - return ctx != nil && - (ctx.RunAsUser != nil && *ctx.RunAsUser != rootUserGroup) && - (ctx.RunAsGroup != nil && *ctx.RunAsGroup != rootUserGroup) -} - func getBasePodName(pod *corev1.Pod) string { basePodName := k8spod.GetName(*pod) diff --git a/pkg/webhook/mutation/pod/init_container_test.go b/pkg/webhook/mutation/pod/v1/init_test.go similarity index 93% rename from pkg/webhook/mutation/pod/init_container_test.go rename to pkg/webhook/mutation/pod/v1/init_test.go index 91150241ae..2654bd93e6 100644 --- a/pkg/webhook/mutation/pod/init_container_test.go +++ b/pkg/webhook/mutation/pod/v1/init_test.go @@ -1,4 +1,4 @@ -package pod +package v1 import ( "testing" @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -42,10 +43,10 @@ func TestCreateInstallInitContainerBase(t *testing.T) { assert.True(t, *initContainer.SecurityContext.RunAsNonRoot) require.NotNil(t, initContainer.SecurityContext.RunAsUser) - assert.Equal(t, defaultUser, *initContainer.SecurityContext.RunAsUser) + assert.Equal(t, oacommon.DefaultUser, *initContainer.SecurityContext.RunAsUser) require.NotNil(t, initContainer.SecurityContext.RunAsGroup) - assert.Equal(t, defaultGroup, *initContainer.SecurityContext.RunAsGroup) + assert.Equal(t, oacommon.DefaultGroup, *initContainer.SecurityContext.RunAsGroup) assert.Nil(t, initContainer.SecurityContext.SeccompProfile) }) @@ -64,7 +65,7 @@ func TestCreateInstallInitContainerBase(t *testing.T) { assert.True(t, *initContainer.SecurityContext.RunAsNonRoot) require.NotNil(t, *initContainer.SecurityContext.RunAsUser) - assert.Equal(t, defaultUser, *initContainer.SecurityContext.RunAsUser) + assert.Equal(t, oacommon.DefaultUser, *initContainer.SecurityContext.RunAsUser) require.NotNil(t, *initContainer.SecurityContext.RunAsGroup) assert.Equal(t, *initContainer.SecurityContext.RunAsGroup, *testUser) @@ -117,8 +118,8 @@ func TestCreateInstallInitContainerBase(t *testing.T) { t.Run("should set RunAsNonRoot if root user is used", func(t *testing.T) { dk := getTestDynakube() pod := getTestPod() - pod.Spec.Containers[0].SecurityContext.RunAsUser = ptr.To(rootUserGroup) - pod.Spec.Containers[0].SecurityContext.RunAsGroup = ptr.To(rootUserGroup) + pod.Spec.Containers[0].SecurityContext.RunAsUser = ptr.To(oacommon.RootUserGroup) + pod.Spec.Containers[0].SecurityContext.RunAsGroup = ptr.To(oacommon.RootUserGroup) webhookImage := "test-image" clusterID := "id" @@ -128,10 +129,10 @@ func TestCreateInstallInitContainerBase(t *testing.T) { assert.False(t, *initContainer.SecurityContext.RunAsNonRoot) require.NotNil(t, *initContainer.SecurityContext.RunAsUser) - assert.Equal(t, rootUserGroup, *initContainer.SecurityContext.RunAsUser) + assert.Equal(t, oacommon.RootUserGroup, *initContainer.SecurityContext.RunAsUser) require.NotNil(t, *initContainer.SecurityContext.RunAsGroup) - assert.Equal(t, rootUserGroup, *initContainer.SecurityContext.RunAsGroup) + assert.Equal(t, oacommon.RootUserGroup, *initContainer.SecurityContext.RunAsGroup) }) t.Run("should handle failure policy feature flag correctly", func(t *testing.T) { dk := getTestDynakube() diff --git a/pkg/webhook/mutation/pod/v1/metadata/annotations.go b/pkg/webhook/mutation/pod/v1/metadata/annotations.go new file mode 100644 index 0000000000..7b26eed15e --- /dev/null +++ b/pkg/webhook/mutation/pod/v1/metadata/annotations.go @@ -0,0 +1,36 @@ +package metadata + +import ( + "encoding/json" + "strings" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" + corev1 "k8s.io/api/core/v1" +) + +func propagateMetadataAnnotations(request *dtwebhook.MutationRequest) { + metacommon.CopyMetadataFromNamespace(request.Pod, request.Namespace, request.DynaKube) + addMetadataToInitEnv(request.Pod, request.InstallContainer) +} + +func addMetadataToInitEnv(pod *corev1.Pod, installContainer *corev1.Container) { + metadataAnnotations := map[string]string{} + + for key, value := range pod.Annotations { + if !strings.HasPrefix(key, dynakube.MetadataPrefix) { + continue + } + + split := strings.Split(key, dynakube.MetadataPrefix) + metadataAnnotations[split[1]] = value + } + + workloadAnnotationsJson, _ := json.Marshal(metadataAnnotations) + installContainer.Env = append(installContainer.Env, + corev1.EnvVar{ + Name: consts.EnrichmentWorkloadAnnotationsEnv, Value: string(workloadAnnotationsJson)}, + ) +} diff --git a/pkg/webhook/mutation/pod/v1/metadata/annotations_test.go b/pkg/webhook/mutation/pod/v1/metadata/annotations_test.go new file mode 100644 index 0000000000..330af60f89 --- /dev/null +++ b/pkg/webhook/mutation/pod/v1/metadata/annotations_test.go @@ -0,0 +1,50 @@ +package metadata + +import ( + "encoding/json" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestAddMetadataToInitEnv(t *testing.T) { + t.Run("should copy annotations not labels with prefix from pod to env", func(t *testing.T) { + expectedKeys := []string{ + "beep", + "boop", + "hello", + } + notExpectedKey := "no-prop" + request := createTestMutationRequest(nil, nil, false) + request.Pod.Labels = map[string]string{ + dynakube.MetadataPrefix + notExpectedKey: "beep-boop", + "test-label": "boom", + } + request.Pod.Annotations = map[string]string{ + "test-annotation": "boom", + } + + for _, key := range expectedKeys { + request.Pod.Annotations[dynakube.MetadataPrefix+key] = key + "-value" + } + + addMetadataToInitEnv(request.Pod, request.InstallContainer) + + annotationsEnv := env.FindEnvVar(request.InstallContainer.Env, consts.EnrichmentWorkloadAnnotationsEnv) + require.NotNil(t, annotationsEnv) + + propagatedAnnotations := map[string]string{} + err := json.Unmarshal([]byte(annotationsEnv.Value), &propagatedAnnotations) + require.NoError(t, err) + + for _, key := range expectedKeys { + require.Contains(t, propagatedAnnotations, key) + assert.Equal(t, key+"-value", propagatedAnnotations[key]) + assert.NotContains(t, propagatedAnnotations, notExpectedKey) + } + }) +} diff --git a/pkg/webhook/mutation/pod/metadata/config.go b/pkg/webhook/mutation/pod/v1/metadata/config.go similarity index 81% rename from pkg/webhook/mutation/pod/metadata/config.go rename to pkg/webhook/mutation/pod/v1/metadata/config.go index f816935959..15d2801878 100644 --- a/pkg/webhook/mutation/pod/metadata/config.go +++ b/pkg/webhook/mutation/pod/v1/metadata/config.go @@ -11,5 +11,5 @@ const ( ) var ( - log = logd.Get().WithName("metadata-enrichment-pod-mutation") + log = logd.Get().WithName("metadata-enrichment-pod-v1-mutation") ) diff --git a/pkg/webhook/mutation/pod/metadata/containers.go b/pkg/webhook/mutation/pod/v1/metadata/containers.go similarity index 85% rename from pkg/webhook/mutation/pod/metadata/containers.go rename to pkg/webhook/mutation/pod/v1/metadata/containers.go index 07666e97d3..f76fd6b3fb 100644 --- a/pkg/webhook/mutation/pod/metadata/containers.go +++ b/pkg/webhook/mutation/pod/v1/metadata/containers.go @@ -2,6 +2,7 @@ package metadata import ( dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" corev1 "k8s.io/api/core/v1" ) @@ -32,7 +33,7 @@ func reinvokeUserContainers(request *dtwebhook.BaseRequest) bool { return updated } -func updateInstallContainer(installContainer *corev1.Container, workload *workloadInfo, entityID, clusterName string) { +func updateInstallContainer(installContainer *corev1.Container, workload *metacommon.WorkloadInfo, entityID, clusterName string) { addInjectedEnv(installContainer) addDTClusterEnvs(installContainer, entityID, clusterName) addWorkloadInfoEnvs(installContainer, workload) diff --git a/pkg/webhook/mutation/pod/metadata/containers_test.go b/pkg/webhook/mutation/pod/v1/metadata/containers_test.go similarity index 92% rename from pkg/webhook/mutation/pod/metadata/containers_test.go rename to pkg/webhook/mutation/pod/v1/metadata/containers_test.go index ff88b2e0db..7e9b273d51 100644 --- a/pkg/webhook/mutation/pod/metadata/containers_test.go +++ b/pkg/webhook/mutation/pod/v1/metadata/containers_test.go @@ -3,6 +3,7 @@ package metadata import ( "testing" + metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" ) @@ -93,3 +94,12 @@ func TestUpdateInstallContainer(t *testing.T) { require.Len(t, container.Env, 5) }) } + +func createTestWorkloadInfo(t *testing.T) *metacommon.WorkloadInfo { + t.Helper() + + return &metacommon.WorkloadInfo{ + Kind: "test", + Name: "test", + } +} diff --git a/pkg/webhook/mutation/pod/metadata/env.go b/pkg/webhook/mutation/pod/v1/metadata/env.go similarity index 83% rename from pkg/webhook/mutation/pod/metadata/env.go rename to pkg/webhook/mutation/pod/v1/metadata/env.go index 24794b1a7d..322d58e2f3 100644 --- a/pkg/webhook/mutation/pod/metadata/env.go +++ b/pkg/webhook/mutation/pod/v1/metadata/env.go @@ -2,6 +2,7 @@ package metadata import ( "github.com/Dynatrace/dynatrace-operator/pkg/consts" + metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" corev1 "k8s.io/api/core/v1" ) @@ -11,10 +12,10 @@ func addInjectedEnv(container *corev1.Container) { ) } -func addWorkloadInfoEnvs(container *corev1.Container, workload *workloadInfo) { +func addWorkloadInfoEnvs(container *corev1.Container, workload *metacommon.WorkloadInfo) { container.Env = append(container.Env, - corev1.EnvVar{Name: consts.EnrichmentWorkloadKindEnv, Value: workload.kind}, - corev1.EnvVar{Name: consts.EnrichmentWorkloadNameEnv, Value: workload.name}, + corev1.EnvVar{Name: consts.EnrichmentWorkloadKindEnv, Value: workload.Kind}, + corev1.EnvVar{Name: consts.EnrichmentWorkloadNameEnv, Value: workload.Name}, ) } diff --git a/pkg/webhook/mutation/pod/metadata/env_test.go b/pkg/webhook/mutation/pod/v1/metadata/env_test.go similarity index 100% rename from pkg/webhook/mutation/pod/metadata/env_test.go rename to pkg/webhook/mutation/pod/v1/metadata/env_test.go diff --git a/pkg/webhook/mutation/pod/metadata/mutator.go b/pkg/webhook/mutation/pod/v1/metadata/mutator.go similarity index 66% rename from pkg/webhook/mutation/pod/metadata/mutator.go rename to pkg/webhook/mutation/pod/v1/metadata/mutator.go index b3a6802bb9..ad7b7bbf3e 100644 --- a/pkg/webhook/mutation/pod/metadata/mutator.go +++ b/pkg/webhook/mutation/pod/v1/metadata/mutator.go @@ -5,12 +5,10 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/consts" dtingestendpoint "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/ingestendpoint" - maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -31,29 +29,17 @@ func NewMutator(webhookNamespace string, client client.Client, apiReader client. } func (mut *Mutator) Enabled(request *dtwebhook.BaseRequest) bool { - enabledOnPod := maputils.GetFieldBool(request.Pod.Annotations, dtwebhook.AnnotationMetadataEnrichmentInject, - request.DynaKube.FeatureAutomaticInjection()) - enabledOnDynakube := request.DynaKube.MetadataEnrichmentEnabled() - - matchesNamespace := true // if no namespace selector is configured, we just pass set this to true - - if request.DynaKube.MetadataEnrichmentNamespaceSelector().Size() > 0 { - selector, _ := metav1.LabelSelectorAsSelector(request.DynaKube.MetadataEnrichmentNamespaceSelector()) - - matchesNamespace = selector.Matches(labels.Set(request.Namespace.Labels)) - } - - return matchesNamespace && enabledOnPod && enabledOnDynakube + return metacommon.IsEnabled(request) } func (mut *Mutator) Injected(request *dtwebhook.BaseRequest) bool { - return maputils.GetFieldBool(request.Pod.Annotations, dtwebhook.AnnotationMetadataEnrichmentInjected, false) + return metacommon.IsInjected(request) } func (mut *Mutator) Mutate(ctx context.Context, request *dtwebhook.MutationRequest) error { log.Info("injecting metadata-enrichment into pod", "podName", request.PodName()) - workload, err := mut.retrieveWorkload(request) + workload, err := metacommon.RetrieveWorkload(mut.metaClient, request) if err != nil { return err } @@ -67,8 +53,8 @@ func (mut *Mutator) Mutate(ctx context.Context, request *dtwebhook.MutationReque mutateUserContainers(request.BaseRequest) updateInstallContainer(request.InstallContainer, workload, request.DynaKube.Status.KubernetesClusterName, request.DynaKube.Status.KubernetesClusterMEID) propagateMetadataAnnotations(request) - setInjectedAnnotation(request.Pod) - setWorkloadAnnotations(request.Pod, workload) + metacommon.SetInjectedAnnotation(request.Pod) + metacommon.SetWorkloadAnnotations(request.Pod, workload) return nil } @@ -113,23 +99,6 @@ func (mut *Mutator) ensureIngestEndpointSecret(request *dtwebhook.MutationReques return nil } -func setInjectedAnnotation(pod *corev1.Pod) { - if pod.Annotations == nil { - pod.Annotations = make(map[string]string) - } - - pod.Annotations[dtwebhook.AnnotationMetadataEnrichmentInjected] = "true" -} - -func setWorkloadAnnotations(pod *corev1.Pod, workload *workloadInfo) { - if pod.Annotations == nil { - pod.Annotations = make(map[string]string) - } - - pod.Annotations[dtwebhook.AnnotationWorkloadKind] = workload.kind - pod.Annotations[dtwebhook.AnnotationWorkloadName] = workload.name -} - func ContainerIsInjected(container corev1.Container) bool { for _, volumeMount := range container.VolumeMounts { if volumeMount.Name == workloadEnrichmentVolumeName || volumeMount.Name == ingestEndpointVolumeName { diff --git a/pkg/webhook/mutation/pod/metadata/mutator_test.go b/pkg/webhook/mutation/pod/v1/metadata/mutator_test.go similarity index 83% rename from pkg/webhook/mutation/pod/metadata/mutator_test.go rename to pkg/webhook/mutation/pod/v1/metadata/mutator_test.go index 3b01433deb..f88f96d388 100644 --- a/pkg/webhook/mutation/pod/metadata/mutator_test.go +++ b/pkg/webhook/mutation/pod/v1/metadata/mutator_test.go @@ -11,8 +11,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" - maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -36,7 +36,7 @@ const ( func TestEnabled(t *testing.T) { t.Run("turned off", func(t *testing.T) { mutator := createTestPodMutator(nil) - request := createTestMutationRequest(nil, map[string]string{dtwebhook.AnnotationMetadataEnrichmentInject: "false"}, false) + request := createTestMutationRequest(nil, map[string]string{metacommon.AnnotationInject: "false"}, false) enabled := mutator.Enabled(request.BaseRequest) @@ -113,7 +113,7 @@ func TestEnabled(t *testing.T) { func TestInjected(t *testing.T) { t.Run("already marked", func(t *testing.T) { mutator := createTestPodMutator(nil) - request := createTestMutationRequest(nil, map[string]string{dtwebhook.AnnotationMetadataEnrichmentInjected: "true"}, false) + request := createTestMutationRequest(nil, map[string]string{metacommon.AnnotationInjected: "true"}, false) enabled := mutator.Injected(request.BaseRequest) @@ -152,7 +152,7 @@ func TestMutate(t *testing.T) { func TestReinvoke(t *testing.T) { t.Run("should only mutate the containers in the pod", func(t *testing.T) { mutator := createTestPodMutator([]client.Object{getTestInitSecret()}) - request := createTestReinvocationRequest(getTestDynakube(), map[string]string{dtwebhook.AnnotationMetadataEnrichmentInjected: "true"}) + request := createTestReinvocationRequest(getTestDynakube(), map[string]string{metacommon.AnnotationInjected: "true"}) initialContainerVolumeMountsLen := len(request.Pod.Spec.Containers[0].VolumeMounts) @@ -168,7 +168,7 @@ func TestReinvoke(t *testing.T) { DynaKube: *getTestDynakube(), Pod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{dtwebhook.AnnotationMetadataEnrichmentInjected: "true"}, + Annotations: map[string]string{metacommon.AnnotationInjected: "true"}, }, }, }, @@ -200,41 +200,6 @@ func TestIngestEndpointSecret(t *testing.T) { }) } -func TestSetInjectedAnnotation(t *testing.T) { - t.Run("should add annotation to nil map", func(t *testing.T) { - request := createTestMutationRequest(nil, nil, false) - mutator := createTestPodMutator(nil) - - require.False(t, mutator.Injected(request.BaseRequest)) - setInjectedAnnotation(request.Pod) - require.Len(t, request.Pod.Annotations, 1) - require.True(t, mutator.Injected(request.BaseRequest)) - }) -} - -func TestWorkloadAnnotations(t *testing.T) { - t.Run("should add annotation to nil map", func(t *testing.T) { - request := createTestMutationRequest(nil, nil, false) - - require.Equal(t, "not-found", maputils.GetField(request.Pod.Annotations, dtwebhook.AnnotationWorkloadName, "not-found")) - setWorkloadAnnotations(request.Pod, &workloadInfo{name: testWorkloadInfoName, kind: testWorkloadInfoKind}) - require.Len(t, request.Pod.Annotations, 2) - assert.Equal(t, testWorkloadInfoName, maputils.GetField(request.Pod.Annotations, dtwebhook.AnnotationWorkloadName, "not-found")) - assert.Equal(t, testWorkloadInfoKind, maputils.GetField(request.Pod.Annotations, dtwebhook.AnnotationWorkloadKind, "not-found")) - }) - t.Run("should lower case kind annotation", func(t *testing.T) { - request := createTestMutationRequest(nil, nil, false) - objectMeta := &metav1.PartialObjectMetadata{ - ObjectMeta: metav1.ObjectMeta{Name: testWorkloadInfoName}, - TypeMeta: metav1.TypeMeta{Kind: "SuperWorkload"}, - } - - setWorkloadAnnotations(request.Pod, newWorkloadInfo(objectMeta)) - assert.Contains(t, request.Pod.Annotations, dtwebhook.AnnotationWorkloadKind) - assert.Equal(t, "superworkload", request.Pod.Annotations[dtwebhook.AnnotationWorkloadKind]) - }) -} - func TestContainerIsInjected(t *testing.T) { t.Run("is not injected", func(t *testing.T) { container := corev1.Container{} diff --git a/pkg/webhook/mutation/pod/metadata/volumes.go b/pkg/webhook/mutation/pod/v1/metadata/volumes.go similarity index 100% rename from pkg/webhook/mutation/pod/metadata/volumes.go rename to pkg/webhook/mutation/pod/v1/metadata/volumes.go diff --git a/pkg/webhook/mutation/pod/metadata/volumes_test.go b/pkg/webhook/mutation/pod/v1/metadata/volumes_test.go similarity index 100% rename from pkg/webhook/mutation/pod/metadata/volumes_test.go rename to pkg/webhook/mutation/pod/v1/metadata/volumes_test.go diff --git a/pkg/webhook/mutation/pod/v1/oneagent/annotations.go b/pkg/webhook/mutation/pod/v1/oneagent/annotations.go new file mode 100644 index 0000000000..de09616500 --- /dev/null +++ b/pkg/webhook/mutation/pod/v1/oneagent/annotations.go @@ -0,0 +1,28 @@ +package oneagent + +import ( + "net/url" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + corev1 "k8s.io/api/core/v1" +) + +type installerInfo struct { + flavor string + technologies string + installPath string + installerURL string + version string +} + +func getInstallerInfo(pod *corev1.Pod, dk dynakube.DynaKube) installerInfo { + return installerInfo{ + flavor: maputils.GetField(pod.Annotations, AnnotationFlavor, ""), + technologies: url.QueryEscape(maputils.GetField(pod.Annotations, oacommon.AnnotationTechnologies, "all")), + installPath: maputils.GetField(pod.Annotations, oacommon.AnnotationInstallPath, oacommon.DefaultInstallPath), + installerURL: maputils.GetField(pod.Annotations, AnnotationInstallerUrl, ""), + version: dk.OneAgent().GetCodeModulesVersion(), + } +} diff --git a/pkg/webhook/mutation/pod/oneagent/annotations_test.go b/pkg/webhook/mutation/pod/v1/oneagent/annotations_test.go similarity index 100% rename from pkg/webhook/mutation/pod/oneagent/annotations_test.go rename to pkg/webhook/mutation/pod/v1/oneagent/annotations_test.go diff --git a/pkg/webhook/mutation/pod/oneagent/config.go b/pkg/webhook/mutation/pod/v1/oneagent/config.go similarity index 58% rename from pkg/webhook/mutation/pod/oneagent/config.go rename to pkg/webhook/mutation/pod/v1/oneagent/config.go index 579693b53f..d82d22a0a0 100644 --- a/pkg/webhook/mutation/pod/oneagent/config.go +++ b/pkg/webhook/mutation/pod/v1/oneagent/config.go @@ -5,24 +5,10 @@ import ( ) var ( - log = logd.Get().WithName("oneagent-pod-mutation") + log = logd.Get().WithName("oneagent-pod-v1-mutation") ) const ( - preloadEnv = "LD_PRELOAD" - networkZoneEnv = "DT_NETWORK_ZONE" - dynatraceMetadataEnv = "DT_DEPLOYMENT_METADATA" - - releaseVersionEnv = "DT_RELEASE_VERSION" - releaseProductEnv = "DT_RELEASE_PRODUCT" - releaseStageEnv = "DT_RELEASE_STAGE" - releaseBuildVersionEnv = "DT_RELEASE_BUILD_VERSION" - - EmptyConnectionInfoReason = "EmptyConnectionInfo" - UnknownCodeModuleReason = "UnknownCodeModule" - NoBootstrapperConfigReason = "NoBootstrapperConfig" - EmptyTenantUUIDReason = "EmptyTenantUUID" - OneAgentBinVolumeName = "oneagent-bin" oneAgentShareVolumeName = "oneagent-share" injectionConfigVolumeName = "injection-config" @@ -41,4 +27,12 @@ const ( oneagentLogVolumeName = "oneagent-log" oneagentLogMountPath = "/opt/dynatrace/oneagent-paas/log" + + // AnnotationFlavor can be set on a Pod to configure which code modules flavor to download. It's set to "default" + // if not set. + AnnotationFlavor = "oneagent.dynatrace.com/flavor" + + // AnnotationInstallerUrl can be set on a Pod to configure the installer url for downloading the agent + // defaults to the PaaS installer download url of your tenant + AnnotationInstallerUrl = "oneagent.dynatrace.com/installer-url" ) diff --git a/pkg/webhook/mutation/pod/oneagent/containers.go b/pkg/webhook/mutation/pod/v1/oneagent/containers.go similarity index 78% rename from pkg/webhook/mutation/pod/oneagent/containers.go rename to pkg/webhook/mutation/pod/v1/oneagent/containers.go index ded821d38d..f9a218fc2e 100644 --- a/pkg/webhook/mutation/pod/oneagent/containers.go +++ b/pkg/webhook/mutation/pod/v1/oneagent/containers.go @@ -3,6 +3,7 @@ package oneagent import ( maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" corev1 "k8s.io/api/core/v1" ) @@ -38,13 +39,13 @@ func (mut *Mutator) reinvokeUserContainers(request *dtwebhook.ReinvocationReques func (mut *Mutator) addOneAgentToContainer(request *dtwebhook.ReinvocationRequest, container *corev1.Container) { log.Info("adding OneAgent to container", "name", container.Name) - installPath := maputils.GetField(request.Pod.Annotations, dtwebhook.AnnotationInstallPath, dtwebhook.DefaultInstallPath) + installPath := maputils.GetField(request.Pod.Annotations, oacommon.AnnotationInstallPath, oacommon.DefaultInstallPath) dk := request.DynaKube addOneAgentVolumeMounts(container, installPath) - addDeploymentMetadataEnv(container, dk, mut.clusterID) - addPreloadEnv(container, installPath) + oacommon.AddDeploymentMetadataEnv(container, dk) + oacommon.AddPreloadEnv(container, installPath) addCertVolumeMounts(container, dk) @@ -53,11 +54,11 @@ func (mut *Mutator) addOneAgentToContainer(request *dtwebhook.ReinvocationReques } if dk.Spec.NetworkZone != "" { - addNetworkZoneEnv(container, dk.Spec.NetworkZone) + oacommon.AddNetworkZoneEnv(container, dk.Spec.NetworkZone) } if dk.FeatureLabelVersionDetection() { - addVersionDetectionEnvs(container, newVersionLabelMapping(request.Namespace)) + oacommon.AddVersionDetectionEnvs(container, request.Namespace) } if dk.FeatureReadOnlyCsiVolume() { diff --git a/pkg/webhook/mutation/pod/oneagent/containers_test.go b/pkg/webhook/mutation/pod/v1/oneagent/containers_test.go similarity index 63% rename from pkg/webhook/mutation/pod/oneagent/containers_test.go rename to pkg/webhook/mutation/pod/v1/oneagent/containers_test.go index f4988db78f..3ffbdf5a48 100644 --- a/pkg/webhook/mutation/pod/oneagent/containers_test.go +++ b/pkg/webhook/mutation/pod/v1/oneagent/containers_test.go @@ -209,122 +209,3 @@ func TestContainerExclusion(t *testing.T) { }) } } - -func TestVersionDetectionMappingDrivenByNamespaceAnnotations(t *testing.T) { - const ( - customVersionValue = "my awesome custom version" - customProductValue = "my awesome custom product" - customReleaseStageValue = "my awesome custom stage" - customBuildVersionValue = "my awesome custom build version" - customVersionAnnotationName = "custom-version" - customProductAnnotationName = "custom-product" - customStageAnnotationName = "custom-stage" - customBuildVersionAnnotationName = "custom-build-version" - customVersionFieldPath = "metadata.podAnnotations['" + customVersionAnnotationName + "']" - customProductFieldPath = "metadata.podAnnotations['" + customProductAnnotationName + "']" - customStageFieldPath = "metadata.podAnnotations['" + customStageAnnotationName + "']" - customBuildVersionFieldPath = "metadata.podAnnotations['" + customBuildVersionAnnotationName + "']" - ) - - t.Run("version and product env vars are set using values referenced in namespace podAnnotations", func(t *testing.T) { - podAnnotations := map[string]string{ - customVersionAnnotationName: customVersionValue, - customProductAnnotationName: customProductValue, - } - namespaceAnnotations := map[string]string{ - versionMappingAnnotationName: customVersionFieldPath, - productMappingAnnotationName: customProductFieldPath, - } - expectedMappings := map[string]string{ - releaseVersionEnv: customVersionFieldPath, - releaseProductEnv: customProductFieldPath, - } - unexpectedMappingsKeys := []string{releaseStageEnv, releaseBuildVersionEnv} - - doTestMappings(t, podAnnotations, namespaceAnnotations, expectedMappings, unexpectedMappingsKeys) - }) - t.Run("only version env vars is set using value referenced in namespace podAnnotations, product is default", func(t *testing.T) { - podAnnotations := map[string]string{ - customVersionAnnotationName: customVersionValue, - } - namespaceAnnotations := map[string]string{ - versionMappingAnnotationName: customVersionFieldPath, - } - expectedMappings := map[string]string{ - releaseVersionEnv: customVersionFieldPath, - releaseProductEnv: defaultVersionLabelMapping[releaseProductEnv], - } - unexpectedMappingsKeys := []string{releaseStageEnv, releaseBuildVersionEnv} - - doTestMappings(t, podAnnotations, namespaceAnnotations, expectedMappings, unexpectedMappingsKeys) - }) - t.Run("optional env vars (stage, build-version) are set using values referenced in namespace podAnnotations, default ones remain default", func(t *testing.T) { - podAnnotations := map[string]string{ - customStageAnnotationName: customReleaseStageValue, - customBuildVersionAnnotationName: customBuildVersionValue, - } - namespaceAnnotations := map[string]string{ - stageMappingAnnotationName: customStageFieldPath, - buildVersionAnnotationName: customBuildVersionFieldPath, - } - expectedMappings := map[string]string{ - releaseVersionEnv: defaultVersionLabelMapping[releaseVersionEnv], - releaseProductEnv: defaultVersionLabelMapping[releaseProductEnv], - releaseStageEnv: customStageFieldPath, - releaseBuildVersionEnv: customBuildVersionFieldPath, - } - - doTestMappings(t, podAnnotations, namespaceAnnotations, expectedMappings, nil) - }) - t.Run("all env vars are namespace-podAnnotations driven", func(t *testing.T) { - podAnnotations := map[string]string{ - customVersionAnnotationName: customVersionValue, - customProductAnnotationName: customProductValue, - customStageAnnotationName: customReleaseStageValue, - customBuildVersionAnnotationName: customBuildVersionValue, - } - namespaceAnnotations := map[string]string{ - versionMappingAnnotationName: customVersionFieldPath, - productMappingAnnotationName: customProductFieldPath, - stageMappingAnnotationName: customStageFieldPath, - buildVersionAnnotationName: customBuildVersionFieldPath, - } - expectedMappings := map[string]string{ - releaseVersionEnv: customVersionFieldPath, - releaseProductEnv: customProductFieldPath, - releaseStageEnv: customStageFieldPath, - releaseBuildVersionEnv: customBuildVersionFieldPath, - } - - doTestMappings(t, podAnnotations, namespaceAnnotations, expectedMappings, nil) - }) -} - -func doTestMappings(t *testing.T, podAnnotations map[string]string, namespaceAnnotations map[string]string, expectedMappings map[string]string, unexpectedMappingsKeys []string) { - mutator := createTestPodMutator([]client.Object{getTestInitSecret()}) - request := createTestMutationRequest(getTestComplexDynakube(), podAnnotations, getTestNamespace(namespaceAnnotations)) - mutator.mutateUserContainers(request) - - assertContainsMappings(t, expectedMappings, request) - assertNotContainsMappings(t, unexpectedMappingsKeys, request) -} - -func assertContainsMappings(t *testing.T, expectedMappings map[string]string, request *dtwebhook.MutationRequest) { - for envName, fieldPath := range expectedMappings { - assert.Contains(t, request.Pod.Spec.Containers[0].Env, corev1.EnvVar{ - Name: envName, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: fieldPath, - }, - }, - }) - } -} - -func assertNotContainsMappings(t *testing.T, unexpectedMappingKeys []string, request *dtwebhook.MutationRequest) { - for _, env := range request.Pod.Spec.Containers[0].Env { - assert.NotContains(t, unexpectedMappingKeys, env.Name) - } -} diff --git a/pkg/webhook/mutation/pod/v1/oneagent/env.go b/pkg/webhook/mutation/pod/v1/oneagent/env.go new file mode 100644 index 0000000000..9109bdc616 --- /dev/null +++ b/pkg/webhook/mutation/pod/v1/oneagent/env.go @@ -0,0 +1,17 @@ +package oneagent + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + corev1 "k8s.io/api/core/v1" +) + +func addInstallerInitEnvs(initContainer *corev1.Container, installer installerInfo) { + initContainer.Env = append(initContainer.Env, + corev1.EnvVar{Name: consts.AgentInstallerFlavorEnv, Value: installer.flavor}, // TODO: is this needed + corev1.EnvVar{Name: consts.AgentInstallerTechEnv, Value: installer.technologies}, + corev1.EnvVar{Name: consts.AgentInstallPathEnv, Value: installer.installPath}, + corev1.EnvVar{Name: consts.AgentInstallerUrlEnv, Value: installer.installerURL}, + corev1.EnvVar{Name: consts.AgentInstallerVersionEnv, Value: installer.version}, + corev1.EnvVar{Name: consts.AgentInjectedEnv, Value: "true"}, + ) +} diff --git a/pkg/webhook/mutation/pod/v1/oneagent/env_test.go b/pkg/webhook/mutation/pod/v1/oneagent/env_test.go new file mode 100644 index 0000000000..3afa3ae553 --- /dev/null +++ b/pkg/webhook/mutation/pod/v1/oneagent/env_test.go @@ -0,0 +1,24 @@ +package oneagent + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" +) + +func TestAddInstallerInitEnvs(t *testing.T) { + t.Run("Add installer init env", func(t *testing.T) { + container := &corev1.Container{} + installerInfo := getTestInstallerInfo() + addInstallerInitEnvs(container, installerInfo) + require.Len(t, container.Env, expectedBaseInitContainerEnvCount) + assert.Equal(t, installerInfo.flavor, container.Env[0].Value) + assert.Equal(t, installerInfo.technologies, container.Env[1].Value) + assert.Equal(t, installerInfo.installPath, container.Env[2].Value) + assert.Equal(t, installerInfo.installerURL, container.Env[3].Value) + assert.Equal(t, installerInfo.version, container.Env[4].Value) + assert.Equal(t, "true", container.Env[5].Value) + }) +} diff --git a/pkg/webhook/mutation/pod/oneagent/mutator.go b/pkg/webhook/mutation/pod/v1/oneagent/mutator.go similarity index 62% rename from pkg/webhook/mutation/pod/oneagent/mutator.go rename to pkg/webhook/mutation/pod/v1/oneagent/mutator.go index 215c5e63aa..22e2a389ea 100644 --- a/pkg/webhook/mutation/pod/oneagent/mutator.go +++ b/pkg/webhook/mutation/pod/v1/oneagent/mutator.go @@ -7,30 +7,26 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/initgeneration" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/volumes" - maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/mounts" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" ) type Mutator struct { client client.Client apiReader client.Reader - image string clusterID string webhookNamespace string } var _ dtwebhook.PodMutator = &Mutator{} -func NewMutator(image, clusterID, webhookNamespace string, client client.Client, apiReader client.Reader) *Mutator { +func NewMutator(clusterID, webhookNamespace string, client client.Client, apiReader client.Reader) *Mutator { return &Mutator{ - image: image, clusterID: clusterID, webhookNamespace: webhookNamespace, client: client, @@ -39,27 +35,16 @@ func NewMutator(image, clusterID, webhookNamespace string, client client.Client, } func (mut *Mutator) Enabled(request *dtwebhook.BaseRequest) bool { - enabledOnPod := maputils.GetFieldBool(request.Pod.Annotations, dtwebhook.AnnotationOneAgentInject, request.DynaKube.FeatureAutomaticInjection()) - enabledOnDynakube := request.DynaKube.OneAgent().GetNamespaceSelector() != nil - - matchesNamespaceSelector := true // if no namespace selector is configured, we just pass set this to true - - if request.DynaKube.OneAgent().GetNamespaceSelector().Size() > 0 { - selector, _ := metav1.LabelSelectorAsSelector(request.DynaKube.OneAgent().GetNamespaceSelector()) - - matchesNamespaceSelector = selector.Matches(labels.Set(request.Namespace.Labels)) - } - - return matchesNamespaceSelector && enabledOnPod && enabledOnDynakube + return oacommon.IsEnabled(request) } func (mut *Mutator) Injected(request *dtwebhook.BaseRequest) bool { - return maputils.GetFieldBool(request.Pod.Annotations, dtwebhook.AnnotationOneAgentInjected, false) + return oacommon.IsInjected(request) } func (mut *Mutator) Mutate(ctx context.Context, request *dtwebhook.MutationRequest) error { if ok, reason := mut.isInjectionPossible(request); !ok { - setNotInjectedAnnotations(request.Pod, reason) + oacommon.SetNotInjectedAnnotations(request.Pod, reason) return nil } @@ -75,7 +60,7 @@ func (mut *Mutator) Mutate(ctx context.Context, request *dtwebhook.MutationReque mut.configureInitContainer(request, installerInfo) mut.mutateUserContainers(request) addInjectionConfigVolumeMount(request.InstallContainer) - setInjectedAnnotation(request.Pod) + oacommon.SetInjectedAnnotation(request.Pod) return nil } @@ -87,6 +72,8 @@ func (mut *Mutator) Reinvoke(request *dtwebhook.ReinvocationRequest) bool { log.Info("reinvoking", "podName", request.PodName()) + oacommon.SetInjectedAnnotation(request.Pod) + return mut.reinvokeUserContainers(request) } @@ -123,30 +110,19 @@ func (mut *Mutator) isInjectionPossible(request *dtwebhook.MutationRequest) (boo if err != nil { log.Info("tenant UUID is not available, OneAgent cannot be injected", "pod", request.PodName()) - reasons = append(reasons, EmptyTenantUUIDReason) + reasons = append(reasons, oacommon.EmptyTenantUUIDReason) } if !dk.OneAgent().IsCommunicationRouteClear() { log.Info("OneAgent communication route is not clear, OneAgent cannot be injected", "pod", request.PodName()) - reasons = append(reasons, EmptyConnectionInfoReason) + reasons = append(reasons, oacommon.EmptyConnectionInfoReason) } if dk.OneAgent().GetCodeModulesVersion() == "" && dk.OneAgent().GetCodeModulesImage() == "" { log.Info("information about the codemodules (version or image) is not available, OneAgent cannot be injected", "pod", request.PodName()) - reasons = append(reasons, UnknownCodeModuleReason) - } - - if dk.FeatureBootstrapperInjection() { - var initSecret corev1.Secret - - secretObjectKey := client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: request.Namespace.Name} - if err := mut.apiReader.Get(request.Context, secretObjectKey, &initSecret); k8serrors.IsNotFound(err) { - log.Info("dynatrace-bootstrapper-config is not available, OneAgent cannot be injected", "pod", request.PodName()) - - reasons = append(reasons, NoBootstrapperConfigReason) - } + reasons = append(reasons, oacommon.UnknownCodeModuleReason) } if len(reasons) > 0 { @@ -157,8 +133,8 @@ func (mut *Mutator) isInjectionPossible(request *dtwebhook.MutationRequest) (boo } func ContainerIsInjected(container corev1.Container) bool { - return env.IsIn(container.Env, dynatraceMetadataEnv) && - env.IsIn(container.Env, preloadEnv) && - volumes.IsIn(container.VolumeMounts, OneAgentBinVolumeName) && - volumes.IsIn(container.VolumeMounts, oneAgentShareVolumeName) + return env.IsIn(container.Env, oacommon.DynatraceMetadataEnv) && + env.IsIn(container.Env, oacommon.PreloadEnv) && + mounts.IsIn(container.VolumeMounts, OneAgentBinVolumeName) && + mounts.IsIn(container.VolumeMounts, oneAgentShareVolumeName) } diff --git a/pkg/webhook/mutation/pod/oneagent/mutator_test.go b/pkg/webhook/mutation/pod/v1/oneagent/mutator_test.go similarity index 89% rename from pkg/webhook/mutation/pod/oneagent/mutator_test.go rename to pkg/webhook/mutation/pod/v1/oneagent/mutator_test.go index c58cd9555f..6aa91082f2 100644 --- a/pkg/webhook/mutation/pod/oneagent/mutator_test.go +++ b/pkg/webhook/mutation/pod/v1/oneagent/mutator_test.go @@ -12,8 +12,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -35,7 +35,7 @@ const ( func TestEnabled(t *testing.T) { t.Run("turned off", func(t *testing.T) { mutator := createTestPodMutator(nil) - request := createTestMutationRequest(nil, map[string]string{dtwebhook.AnnotationOneAgentInject: "false"}, getTestNamespace(nil)) + request := createTestMutationRequest(nil, map[string]string{oacommon.AnnotationInject: "false"}, getTestNamespace(nil)) enabled := mutator.Enabled(request.BaseRequest) @@ -94,7 +94,7 @@ func TestEnabled(t *testing.T) { func TestInjected(t *testing.T) { t.Run("already marked", func(t *testing.T) { mutator := createTestPodMutator(nil) - request := createTestMutationRequest(nil, map[string]string{dtwebhook.AnnotationOneAgentInjected: "true"}, getTestNamespace(nil)) + request := createTestMutationRequest(nil, map[string]string{oacommon.AnnotationInjected: "true"}, getTestNamespace(nil)) enabled := mutator.Injected(request.BaseRequest) @@ -208,13 +208,13 @@ func TestNoInjectionMutate(t *testing.T) { assert.Equal(t, initialInitContainers, request.Pod.Spec.InitContainers) assert.Len(t, request.Pod.Annotations, initialAnnotationsLen+2) // +2 == injected-annotation, reason-annotation - require.Contains(t, request.Pod.Annotations, dtwebhook.AnnotationOneAgentInjected) - require.Contains(t, request.Pod.Annotations, dtwebhook.AnnotationOneAgentReason) + require.Contains(t, request.Pod.Annotations, oacommon.AnnotationInjected) + require.Contains(t, request.Pod.Annotations, oacommon.AnnotationReason) - assert.Equal(t, "false", request.Pod.Annotations[dtwebhook.AnnotationOneAgentInjected]) - assert.Contains(t, request.Pod.Annotations[dtwebhook.AnnotationOneAgentReason], EmptyConnectionInfoReason) - assert.Contains(t, request.Pod.Annotations[dtwebhook.AnnotationOneAgentReason], EmptyTenantUUIDReason) - assert.Contains(t, request.Pod.Annotations[dtwebhook.AnnotationOneAgentReason], UnknownCodeModuleReason) + assert.Equal(t, "false", request.Pod.Annotations[oacommon.AnnotationInjected]) + assert.Contains(t, request.Pod.Annotations[oacommon.AnnotationReason], oacommon.EmptyConnectionInfoReason) + assert.Contains(t, request.Pod.Annotations[oacommon.AnnotationReason], oacommon.EmptyTenantUUIDReason) + assert.Contains(t, request.Pod.Annotations[oacommon.AnnotationReason], oacommon.UnknownCodeModuleReason) assert.Empty(t, request.InstallContainer.Env) assert.Empty(t, request.InstallContainer.VolumeMounts) @@ -252,7 +252,7 @@ func TestReinvoke(t *testing.T) { for index, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { mutator := createTestPodMutator([]client.Object{getTestInitSecret()}) - request := createTestReinvocationRequest(&testCases[index].dk, map[string]string{dtwebhook.AnnotationOneAgentInjected: "true"}) + request := createTestReinvocationRequest(&testCases[index].dk, map[string]string{oacommon.AnnotationInjected: "true"}) initialNumberOfContainerEnvsLen := len(request.Pod.Spec.Containers[0].Env) initialNumberOfVolumesLen := len(request.Pod.Spec.Volumes) @@ -277,7 +277,7 @@ func TestReinvoke(t *testing.T) { DynaKube: *getTestDynakube(), Pod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{dtwebhook.AnnotationOneAgentInjected: "true"}, + Annotations: map[string]string{oacommon.AnnotationInjected: "true"}, }, }, }, @@ -294,7 +294,6 @@ func TestIsInjectionPossible(t *testing.T) { t.Run("not possible without communication route", injectionNotPossibleWithoutCommunicationRoute) t.Run("not possible without code modules version", injectionNotPossibleWithoutCodeModulesVersion) t.Run("not possible with multiple issues", injectionNotPossibleWithMultipleIssues) - t.Run("not possible with remote image download enabled and no csi driver", injectionNotPossibleWithRemoteImageDownloadEnabled) } func injectionPossibleWithValidTenantUUID(t *testing.T) { @@ -329,7 +328,7 @@ func injectionNotPossibleWithoutTenantUUID(t *testing.T) { ok, reason := mutator.isInjectionPossible(request) require.False(t, ok) - require.Contains(t, reason, EmptyTenantUUIDReason) + require.Contains(t, reason, oacommon.EmptyTenantUUIDReason) } func injectionNotPossibleWithoutCommunicationRoute(t *testing.T) { @@ -341,7 +340,7 @@ func injectionNotPossibleWithoutCommunicationRoute(t *testing.T) { ok, reason := mutator.isInjectionPossible(request) require.False(t, ok) - require.Contains(t, reason, EmptyConnectionInfoReason) + require.Contains(t, reason, oacommon.EmptyConnectionInfoReason) } func injectionNotPossibleWithoutCodeModulesVersion(t *testing.T) { @@ -353,7 +352,7 @@ func injectionNotPossibleWithoutCodeModulesVersion(t *testing.T) { ok, reason := mutator.isInjectionPossible(request) require.False(t, ok) - require.Contains(t, reason, UnknownCodeModuleReason) + require.Contains(t, reason, oacommon.UnknownCodeModuleReason) } func injectionNotPossibleWithMultipleIssues(t *testing.T) { @@ -367,29 +366,15 @@ func injectionNotPossibleWithMultipleIssues(t *testing.T) { ok, reason := mutator.isInjectionPossible(request) require.False(t, ok) - require.Contains(t, reason, EmptyTenantUUIDReason) - require.Contains(t, reason, EmptyConnectionInfoReason) - require.Contains(t, reason, UnknownCodeModuleReason) -} - -func injectionNotPossibleWithRemoteImageDownloadEnabled(t *testing.T) { - installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) - - mutator := createTestPodMutator(nil) - dk := getRemoteImageDownloadDynakube() - request := createTestMutationRequest(dk, nil, getTestNamespace(nil)) - - ok, reason := mutator.isInjectionPossible(request) - - require.False(t, ok) - require.Contains(t, reason, NoBootstrapperConfigReason) + require.Contains(t, reason, oacommon.EmptyTenantUUIDReason) + require.Contains(t, reason, oacommon.EmptyConnectionInfoReason) + require.Contains(t, reason, oacommon.UnknownCodeModuleReason) } func createTestPodMutator(objects []client.Object) *Mutator { return &Mutator{ client: fake.NewClient(objects...), apiReader: fake.NewClient(objects...), - image: testImage, clusterID: testClusterID, webhookNamespace: testNamespaceName, } @@ -451,22 +436,6 @@ func getTestCSIDynakube() *dynakube.DynaKube { } } -func getRemoteImageDownloadDynakube() *dynakube.DynaKube { - dk := &dynakube.DynaKube{ - ObjectMeta: getTestDynakubeMeta(), - Spec: dynakube.DynaKubeSpec{ - OneAgent: oneagent.Spec{ - ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, - }, - }, - Status: getTestDynakubeStatus(), - } - - dk.Annotations[dynakube.AnnotationFeatureRemoteImageDownload] = "true" - - return dk -} - func getTestReadOnlyCSIDynakube() *dynakube.DynaKube { dk := getTestCSIDynakube() dk.Annotations[dynakube.AnnotationFeatureReadOnlyCsiVolume] = "true" diff --git a/pkg/webhook/mutation/pod/oneagent/volumes.go b/pkg/webhook/mutation/pod/v1/oneagent/volumes.go similarity index 100% rename from pkg/webhook/mutation/pod/oneagent/volumes.go rename to pkg/webhook/mutation/pod/v1/oneagent/volumes.go diff --git a/pkg/webhook/mutation/pod/oneagent/volumes_test.go b/pkg/webhook/mutation/pod/v1/oneagent/volumes_test.go similarity index 95% rename from pkg/webhook/mutation/pod/oneagent/volumes_test.go rename to pkg/webhook/mutation/pod/v1/oneagent/volumes_test.go index e29e76756a..7e5a553ca6 100644 --- a/pkg/webhook/mutation/pod/oneagent/volumes_test.go +++ b/pkg/webhook/mutation/pod/v1/oneagent/volumes_test.go @@ -8,7 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/volumes" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/mounts" "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -39,7 +39,7 @@ func TestAddReadOnlyCSIVolumeMounts(t *testing.T) { require.Len(t, container.VolumeMounts, 3) for expectedVolumeName, expectedMountPath := range expectedMounts { - mount, err := volumes.GetVolumeMountByName(container.VolumeMounts, expectedVolumeName) + mount, err := mounts.GetByName(container.VolumeMounts, expectedVolumeName) require.NoError(t, err) require.NotNil(t, mount) assert.Equal(t, expectedMountPath, mount.MountPath) @@ -111,7 +111,7 @@ func TestAddInitVolumeMounts(t *testing.T) { addInitVolumeMounts(container, *getTestReadOnlyCSIDynakube()) require.Len(t, container.VolumeMounts, 3) - mount, err := volumes.GetVolumeMountByName(container.VolumeMounts, oneagentConfVolumeName) + mount, err := mounts.GetByName(container.VolumeMounts, oneagentConfVolumeName) require.NoError(t, err) assert.Equal(t, consts.AgentConfInitDirMount, mount.MountPath) }) diff --git a/pkg/webhook/mutation/pod/v1/webhook.go b/pkg/webhook/mutation/pod/v1/webhook.go new file mode 100644 index 0000000000..cd3b91512c --- /dev/null +++ b/pkg/webhook/mutation/pod/v1/webhook.go @@ -0,0 +1,148 @@ +package v1 + +import ( + "context" + + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1/metadata" + oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1/oneagent" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Injector struct { + recorder events.EventRecorder + isContainerInjected func(corev1.Container) bool + webhookImage string + clusterID string + + mutators []dtwebhook.PodMutator +} + +var _ dtwebhook.PodInjector = &Injector{} + +func NewInjector(apiReader client.Reader, kubeClient, metaClient client.Client, recorder events.EventRecorder, clusterID, webhookPodImage, webhookNamespace string) *Injector { //nolint:revive + return &Injector{ + webhookImage: webhookPodImage, + recorder: recorder, + clusterID: clusterID, + mutators: []dtwebhook.PodMutator{ + oamutation.NewMutator( + clusterID, + webhookNamespace, + kubeClient, + apiReader, + ), + metadata.NewMutator( + webhookNamespace, + kubeClient, + apiReader, + metaClient, + ), + }, + isContainerInjected: containerIsInjected, + } +} + +func (wh *Injector) Handle(ctx context.Context, mutationRequest *dtwebhook.MutationRequest) error { + wh.recorder.Setup(mutationRequest) + + if wh.isInjected(mutationRequest) { + if wh.handlePodReinvocation(mutationRequest) { + log.Info("reinvocation policy applied", "podName", mutationRequest.PodName()) + wh.recorder.SendPodUpdateEvent() + } + + log.Info("no change, all containers already injected", "podName", mutationRequest.PodName()) + } else { + if err := wh.handlePodMutation(ctx, mutationRequest); err != nil { + return err + } + } + + setDynatraceInjectedAnnotation(mutationRequest) + + log.Info("injection finished for pod", "podName", mutationRequest.PodName(), "namespace", mutationRequest.Namespace.Name) + + return nil +} + +func (wh *Injector) isInjected(mutationRequest *dtwebhook.MutationRequest) bool { + for _, mutator := range wh.mutators { + if mutator.Injected(mutationRequest.BaseRequest) { + return true + } + } + + installContainer := container.FindInitContainerInPodSpec(&mutationRequest.Pod.Spec, dtwebhook.InstallContainerName) + if installContainer != nil { + log.Info("Dynatrace init-container already present, skipping mutation, doing reinvocation", "containerName", dtwebhook.InstallContainerName) + + return true + } + + return false +} + +func (wh *Injector) handlePodMutation(ctx context.Context, mutationRequest *dtwebhook.MutationRequest) error { + mutationRequest.InstallContainer = createInstallInitContainerBase(wh.webhookImage, wh.clusterID, mutationRequest.Pod, mutationRequest.DynaKube) + + _ = updateContainerInfo(mutationRequest.BaseRequest, mutationRequest.InstallContainer) + + var isMutated bool + + for _, mutator := range wh.mutators { + if !mutator.Enabled(mutationRequest.BaseRequest) { + continue + } + + if err := mutator.Mutate(ctx, mutationRequest); err != nil { + return err + } + + isMutated = true + } + + if !isMutated { + log.Info("no mutation is enabled") + + return nil + } + + addInitContainerToPod(mutationRequest.Pod, mutationRequest.InstallContainer) + wh.recorder.SendPodInjectEvent() + + return nil +} + +func (wh *Injector) handlePodReinvocation(mutationRequest *dtwebhook.MutationRequest) bool { + var needsUpdate bool + + reinvocationRequest := mutationRequest.ToReinvocationRequest() + + isMutated := updateContainerInfo(reinvocationRequest.BaseRequest, nil) + + if !isMutated { // == no new containers were detected, we only mutate new containers during reinvoke + return false + } + + for _, mutator := range wh.mutators { + if mutator.Enabled(mutationRequest.BaseRequest) { + if update := mutator.Reinvoke(reinvocationRequest); update { + needsUpdate = true + } + } + } + + return needsUpdate +} + +func setDynatraceInjectedAnnotation(mutationRequest *dtwebhook.MutationRequest) { + if mutationRequest.Pod.Annotations == nil { + mutationRequest.Pod.Annotations = make(map[string]string) + } + + mutationRequest.Pod.Annotations[dtwebhook.AnnotationDynatraceInjected] = "true" +} diff --git a/pkg/webhook/mutation/pod/v1/webhook_test.go b/pkg/webhook/mutation/pod/v1/webhook_test.go new file mode 100644 index 0000000000..88262876b2 --- /dev/null +++ b/pkg/webhook/mutation/pod/v1/webhook_test.go @@ -0,0 +1,494 @@ +package v1 + +import ( + "context" + "encoding/json" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1/metadata" + oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1/oneagent" + webhookmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/webhook" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/record" + "k8s.io/utils/ptr" +) + +const ( + testImage = "test-image" + testNamespaceName = "test-namespace" + testClusterID = "test-cluster-id" + testPodName = "test-pod" + testDynakubeName = "test-dynakube" +) + +var testResourceRequirements = corev1.ResourceRequirements{ + Limits: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("100Mi"), + }, +} + +func TestInjector(t *testing.T) { + t.Run("not yet injected => mutate", func(t *testing.T) { + ctx := context.Background() + + injector := createTestInjector([]dtwebhook.PodMutator{createSimplePodMutatorMock(t), createSimplePodMutatorMock(t)}, false) + request := createTestMutationRequest(getTestDynakube()) + + err := injector.Handle(ctx, request) + require.NoError(t, err) + + for _, mutator := range injector.mutators { + assertMutateCalls(t, mutator, 1) + } + }) + + t.Run("fail => error", func(t *testing.T) { + ctx := context.Background() + + injector := createTestInjector([]dtwebhook.PodMutator{createFailPodMutatorMock(t)}, false) + request := createTestMutationRequest(getTestDynakube()) + + err := injector.Handle(ctx, request) + require.Error(t, err) + + for _, mutator := range injector.mutators { + assertMutateCalls(t, mutator, 1) + } + }) + + t.Run("already injected => reinvoke", func(t *testing.T) { + ctx := context.Background() + + injector := createTestInjector([]dtwebhook.PodMutator{createAlreadyInjectedPodMutatorMock(t), createAlreadyInjectedPodMutatorMock(t)}, true) + request := createTestMutationRequestWithInjectedPod(getTestDynakube()) + + err := injector.Handle(ctx, request) + require.NoError(t, err) + + for _, mutator := range injector.mutators { + assertReinvokeCalls(t, mutator, 1) + } + }) +} + +func TestHandlePodMutation(t *testing.T) { + t.Run("should call both mutators, initContainer and annotation added, no error", func(t *testing.T) { + mutator1 := createSimplePodMutatorMock(t) + mutator2 := createSimplePodMutatorMock(t) + dk := getTestDynakube() + podWebhook := createTestInjector([]dtwebhook.PodMutator{mutator1, mutator2}, false) + mutationRequest := createTestMutationRequest(dk) + podWebhook.recorder.Setup(mutationRequest) + + err := podWebhook.handlePodMutation(context.Background(), mutationRequest) + require.NoError(t, err) + assert.NotNil(t, mutationRequest.InstallContainer) + + require.Len(t, mutationRequest.Pod.Spec.InitContainers, 2) + + assertContainersInfo(t, mutationRequest.ToReinvocationRequest(), &mutationRequest.Pod.Spec.InitContainers[1]) + + initSecurityContext := mutationRequest.Pod.Spec.InitContainers[1].SecurityContext + require.NotNil(t, initSecurityContext) + + require.NotNil(t, initSecurityContext.Privileged) + assert.False(t, *initSecurityContext.Privileged) + + require.NotNil(t, initSecurityContext.AllowPrivilegeEscalation) + assert.False(t, *initSecurityContext.AllowPrivilegeEscalation) + + require.NotNil(t, initSecurityContext.ReadOnlyRootFilesystem) + assert.True(t, *initSecurityContext.ReadOnlyRootFilesystem) + + assert.NotNil(t, initSecurityContext.RunAsNonRoot) + assert.True(t, *initSecurityContext.RunAsNonRoot) + + assert.Equal(t, mutationRequest.Pod.Spec.InitContainers[1].Resources, testResourceRequirements) + mutator1.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) + mutator1.AssertCalled(t, "Mutate", mock.Anything, mutationRequest) + mutator2.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) + mutator2.AssertCalled(t, "Mutate", mock.Anything, mutationRequest) + }) + t.Run("should call 1 webhook, 1 error, no initContainer and annotation", func(t *testing.T) { + sadMutator := createFailPodMutatorMock(t) + emptyMutator := webhookmock.NewPodMutator(t) + dk := getTestDynakube() + podWebhook := createTestInjector([]dtwebhook.PodMutator{sadMutator, emptyMutator}, false) + mutationRequest := createTestMutationRequest(dk) + podWebhook.recorder.Setup(mutationRequest) + + err := podWebhook.handlePodMutation(context.Background(), mutationRequest) + require.Error(t, err) + assert.NotNil(t, mutationRequest.InstallContainer) + assert.Len(t, mutationRequest.Pod.Spec.InitContainers, 1) + sadMutator.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) + sadMutator.AssertCalled(t, "Mutate", mock.Anything, mutationRequest) + }) +} + +func TestHandlePodReinvocation(t *testing.T) { + t.Run("should call both mutators, updated == true", func(t *testing.T) { + mutator1 := createAlreadyInjectedPodMutatorMock(t) + mutator2 := createAlreadyInjectedPodMutatorMock(t) + dk := getTestDynakube() + podWebhook := createTestInjector([]dtwebhook.PodMutator{mutator1, mutator2}, true) + mutationRequest := createTestMutationRequestWithInjectedPod(dk) + podWebhook.recorder.Setup(mutationRequest) + + updated := podWebhook.handlePodReinvocation(mutationRequest) + require.True(t, updated) + + require.Len(t, mutationRequest.Pod.Spec.InitContainers, 2) + assertContainersInfo(t, mutationRequest.ToReinvocationRequest(), &mutationRequest.Pod.Spec.InitContainers[1]) + + mutator1.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) + mutator1.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) + mutator2.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) + mutator2.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) + }) + t.Run("should call both webhook, only 1 update, updated == true", func(t *testing.T) { + noUpdateMutator := createNoUpdatePodMutatorMock(t) + workingMutator := createAlreadyInjectedPodMutatorMock(t) + dk := getTestDynakube() + podWebhook := createTestInjector([]dtwebhook.PodMutator{noUpdateMutator, workingMutator}, true) + mutationRequest := createTestMutationRequestWithInjectedPod(dk) + podWebhook.recorder.Setup(mutationRequest) + + updated := podWebhook.handlePodReinvocation(mutationRequest) + require.True(t, updated) + noUpdateMutator.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) + noUpdateMutator.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) + workingMutator.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) + workingMutator.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) + }) + t.Run("should call webhook, no update", func(t *testing.T) { + noUpdateMutator := createNoUpdatePodMutatorMock(t) + dk := getTestDynakube() + podWebhook := createTestInjector([]dtwebhook.PodMutator{noUpdateMutator}, true) + mutationRequest := createTestMutationRequestWithInjectedPod(dk) + podWebhook.recorder.Setup(mutationRequest) + + updated := podWebhook.handlePodReinvocation(mutationRequest) + require.False(t, updated) + noUpdateMutator.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) + noUpdateMutator.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) + }) +} + +func assertContainersInfo(t *testing.T, request *dtwebhook.ReinvocationRequest, installContainer *corev1.Container) { + rawContainerInfo := env.FindEnvVar(installContainer.Env, consts.ContainerInfoEnv) + require.NotNil(t, rawContainerInfo) + + var containerInfo []startup.ContainerInfo + err := json.Unmarshal([]byte(rawContainerInfo.Value), &containerInfo) + require.NoError(t, err) + + for _, container := range request.Pod.Spec.Containers { + found := false + + for _, info := range containerInfo { + if container.Name == info.Name { + assert.Equal(t, container.Image, info.Image) + + found = true + + break + } + } + + require.True(t, found) + } +} + +func assertMutateCalls(t *testing.T, mutator dtwebhook.PodMutator, expectedCalls int) { + mock, ok := mutator.(*webhookmock.PodMutator) + if !ok { + t.Fatalf("assertPodMutatorCalls: webhook is not a mock") + } + + mock.AssertNumberOfCalls(t, "Mutate", expectedCalls) +} + +func assertReinvokeCalls(t *testing.T, mutator dtwebhook.PodMutator, expectedCalls int) { + mock, ok := mutator.(*webhookmock.PodMutator) + if !ok { + t.Fatalf("assertPodMutatorCalls: webhook is not a mock") + } + + mock.AssertNumberOfCalls(t, "Reinvoke", expectedCalls) +} + +func createTestInjector(mutators []dtwebhook.PodMutator, isContainerInjected bool) *Injector { + return &Injector{ + recorder: events.NewRecorder(record.NewFakeRecorder(10)), + webhookImage: testImage, + clusterID: testClusterID, + mutators: mutators, + isContainerInjected: func(c corev1.Container) bool { return isContainerInjected }, + } +} + +func createSimplePodMutatorMock(t *testing.T) *webhookmock.PodMutator { + t.Helper() + + mutator := webhookmock.NewPodMutator(t) + mutator.On("Injected", mock.Anything).Return(false).Maybe() // It is a Maybe, because it is only checked at the very beginning + mutator.On("Enabled", mock.Anything).Return(true) + mutator.On("Mutate", mock.Anything, mock.Anything).Return(nil) + + return mutator +} + +func createAlreadyInjectedPodMutatorMock(t *testing.T) *webhookmock.PodMutator { + t.Helper() + + mutator := webhookmock.NewPodMutator(t) + mutator.On("Injected", mock.Anything).Return(true).Maybe() // It is a Maybe, because if there are multiple mutators, the first "Injected" that returns true will break the loop -> Reinvoke + mutator.On("Enabled", mock.Anything).Return(true) + mutator.On("Reinvoke", mock.Anything).Return(true) + + return mutator +} + +func createNoUpdatePodMutatorMock(t *testing.T) *webhookmock.PodMutator { + t.Helper() + + mutator := webhookmock.NewPodMutator(t) + mutator.On("Injected", mock.Anything).Return(true).Maybe() // It is a Maybe, because if there are multiple mutators, the first "Injected" that returns true will break the loop -> Reinvoke + mutator.On("Enabled", mock.Anything).Return(true) + mutator.On("Reinvoke", mock.Anything).Return(false) + + return mutator +} + +func createFailPodMutatorMock(t *testing.T) *webhookmock.PodMutator { + t.Helper() + + mutator := webhookmock.NewPodMutator(t) + mutator.On("Injected", mock.Anything).Return(false).Maybe() // It is a Maybe, because it is only checked at the very beginning + mutator.On("Enabled", mock.Anything).Return(true) + mutator.On("Mutate", mock.Anything, mock.Anything).Return(errors.New("BOOM")) + + return mutator +} + +func getTestDynakube() *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: getTestDynakubeMeta(), + Spec: dynakube.DynaKubeSpec{ + OneAgent: getCloudNativeSpec(&testResourceRequirements), + }, + } +} + +func getTestDynakubeNoInitLimits() *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: getTestDynakubeMeta(), + Spec: dynakube.DynaKubeSpec{ + OneAgent: getCloudNativeSpec(nil), + }, + } +} + +func getTestDynakubeDefaultAppMon() *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: getTestDynakubeMeta(), + Spec: dynakube.DynaKubeSpec{ + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, + }, + }, + } +} + +func getTestDynakubeMeta() metav1.ObjectMeta { + return metav1.ObjectMeta{ + Name: testDynakubeName, + Namespace: testNamespaceName, + } +} + +func getCloudNativeSpec(initResources *corev1.ResourceRequirements) oneagent.Spec { + return oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ + InitResources: initResources, + }, + }, + } +} + +func getTestPod() *corev1.Pod { + return &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPodName, + Namespace: testNamespaceName, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "container", + Image: "alpine", + SecurityContext: getTestSecurityContext(), + }, + }, + InitContainers: []corev1.Container{ + { + Name: "init-container", + Image: "alpine", + }, + }, + Volumes: []corev1.Volume{ + { + Name: "volume", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + }, + }, + } +} + +const testUser int64 = 420 + +func getTestSecurityContext() *corev1.SecurityContext { + return &corev1.SecurityContext{ + RunAsUser: ptr.To(testUser), + RunAsGroup: ptr.To(testUser), + } +} + +func createTestMutationRequest(dk *dynakube.DynaKube) *dtwebhook.MutationRequest { + return dtwebhook.NewMutationRequest(context.Background(), *getTestNamespace(), nil, getTestPod(), *dk) +} + +func createTestMutationRequestWithInjectedPod(dk *dynakube.DynaKube) *dtwebhook.MutationRequest { + return dtwebhook.NewMutationRequest(context.Background(), *getTestNamespace(), nil, getInjectedPod(), *dk) +} + +func getInjectedPod() *corev1.Pod { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPodName, + Namespace: testNamespaceName, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "container", + Image: "alpine", + SecurityContext: getTestSecurityContext(), + }, + }, + InitContainers: []corev1.Container{ + { + Name: "init-container", + Image: "alpine", + }, + }, + Volumes: []corev1.Volume{ + { + Name: "volume", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + }, + }, + } + installContainer := createInstallInitContainerBase("test", "test", pod, *getTestDynakube()) + pod.Spec.InitContainers = append(pod.Spec.InitContainers, *installContainer) + + return pod +} + +func getTestNamespace() *corev1.Namespace { + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: testNamespaceName, + Labels: map[string]string{ + dtwebhook.InjectionInstanceLabel: testDynakubeName, + }, + }, + } +} + +// TestDoubleInjection is special test case for making sure that we do not inject the init-container 2 times incase 1 of the mutators are skipped. +// The mutators are intentionally NOT mocked, as to mock them properly for this scenario you would need to basically reimplement them in the mock. +// This test is necessary as the current interface is not ready to handle the scenario properly. +// Scenario: OneAgent mutation is Enabled however needs to be skipped due to not meeting the requirements, so it needs to annotate but not fully inject +func TestDoubleInjection(t *testing.T) { + noCommunicationHostDK := getTestDynakube() + fakeClient := fake.NewClient(noCommunicationHostDK, getTestNamespace()) + podWebhook := &Injector{ + recorder: events.NewRecorder(record.NewFakeRecorder(10)), + webhookImage: testImage, + clusterID: testClusterID, + mutators: []dtwebhook.PodMutator{ + oamutation.NewMutator( + testImage, + testClusterID, + fakeClient, + fakeClient, + ), + metadata.NewMutator( + testNamespaceName, + fakeClient, + fakeClient, + fakeClient, + ), + }, + } + + pod := getTestPod() + + request := createTestMutationRequest(noCommunicationHostDK) + request.Pod = pod + + // simulate initial mutation, annotations + init-container <== skip in case on communication hosts + err := podWebhook.Handle(context.Background(), request) + require.NoError(t, err) + require.NotNil(t, findInstallContainer(pod.Spec.InitContainers)) + + // adding communicationHost to the dynakube to make the scenario more complicated + // it shouldn't try to mutate the pod because now it could be enabled, that is just asking for trouble. + communicationHostDK := getTestDynakube() + communicationHostDK.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{{Host: "test"}} + fakeClient = fake.NewClient(communicationHostDK, getTestNamespace()) + podWebhook.mutators = []dtwebhook.PodMutator{ + oamutation.NewMutator( + testImage, + testClusterID, + fakeClient, + fakeClient, + ), + metadata.NewMutator( + testNamespaceName, + fakeClient, + fakeClient, + fakeClient, + ), + } + + // simulate a Reinvocation + request = createTestMutationRequest(noCommunicationHostDK) + request.Pod = pod + err = podWebhook.Handle(context.Background(), request) + require.NoError(t, err) +} diff --git a/pkg/webhook/mutation/pod/v2/common/arg/arg.go b/pkg/webhook/mutation/pod/v2/common/arg/arg.go new file mode 100644 index 0000000000..d91f12361b --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/common/arg/arg.go @@ -0,0 +1,21 @@ +package arg + +import "fmt" + +type Arg struct { + Name string + Value string +} + +func (a Arg) String() string { + return fmt.Sprintf("--%s=%s", a.Name, a.Value) +} + +func ConvertArgsToStrings(args []Arg) []string { + convertedArgs := make([]string, len(args)) + for i, arg := range args { + convertedArgs[i] = arg.String() + } + + return convertedArgs +} diff --git a/pkg/webhook/mutation/pod/v2/common/arg/arg_test.go b/pkg/webhook/mutation/pod/v2/common/arg/arg_test.go new file mode 100644 index 0000000000..e1c7a7c05b --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/common/arg/arg_test.go @@ -0,0 +1,36 @@ +package arg + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestArgFunctions(t *testing.T) { + t.Run("ArgStringFormat", func(t *testing.T) { + arg := Arg{Name: "key", Value: "value"} + expected := "--key=value" + assert.Equal(t, expected, arg.String()) + }) + + t.Run("ConvertArgsToStringsEmpty", func(t *testing.T) { + args := []Arg{} + expected := []string{} + assert.Equal(t, expected, ConvertArgsToStrings(args)) + }) + + t.Run("ConvertArgsToStringsSingleArg", func(t *testing.T) { + args := []Arg{{Name: "key", Value: "value"}} + expected := []string{"--key=value"} + assert.Equal(t, expected, ConvertArgsToStrings(args)) + }) + + t.Run("ConvertArgsToStringsMultipleArgs", func(t *testing.T) { + args := []Arg{ + {Name: "key1", Value: "value1"}, + {Name: "key2", Value: "value2"}, + } + expected := []string{"--key1=value1", "--key2=value2"} + assert.Equal(t, expected, ConvertArgsToStrings(args)) + }) +} diff --git a/pkg/webhook/mutation/pod/v2/common/volumes/volumes.go b/pkg/webhook/mutation/pod/v2/common/volumes/volumes.go new file mode 100644 index 0000000000..d48643385d --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/common/volumes/volumes.go @@ -0,0 +1,94 @@ +package volumes + +import ( + "path/filepath" + + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/mounts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/volumes" + corev1 "k8s.io/api/core/v1" +) + +const ( + ConfigVolumeName = "dynatrace-config" + InitConfigMountPath = "/mnt/config" + InitConfigSubPath = "config" + ConfigMountPath = "var/lib/dynatrace" + + InputVolumeName = "dynatrace-input" + InitInputMountPath = "/mnt/input" +) + +func AddConfigVolume(pod *corev1.Pod) { + if volumes.IsIn(pod.Spec.Volumes, ConfigVolumeName) { + return + } + + pod.Spec.Volumes = append(pod.Spec.Volumes, + corev1.Volume{ + Name: ConfigVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + ) +} + +func AddConfigVolumeMount(container *corev1.Container) { + if mounts.IsPathIn(container.VolumeMounts, ConfigMountPath) { + return + } + + container.VolumeMounts = append(container.VolumeMounts, + corev1.VolumeMount{ + Name: ConfigVolumeName, + MountPath: ConfigMountPath, + SubPath: filepath.Join(InitConfigSubPath, container.Name), + }, + ) +} + +func AddInitConfigVolumeMount(container *corev1.Container) { + if mounts.IsPathIn(container.VolumeMounts, InitConfigMountPath) { + return + } + + container.VolumeMounts = append(container.VolumeMounts, + corev1.VolumeMount{ + Name: ConfigVolumeName, + MountPath: InitConfigMountPath, + SubPath: InitConfigSubPath, + }, + ) +} + +func AddInputVolume(pod *corev1.Pod) { + if volumes.IsIn(pod.Spec.Volumes, InputVolumeName) { + return + } + + pod.Spec.Volumes = append(pod.Spec.Volumes, + corev1.Volume{ + Name: InputVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: consts.BootstrapperInitSecretName, + }, + }, + }, + ) +} + +func AddInitInputVolumeMount(container *corev1.Container) { + if mounts.IsPathIn(container.VolumeMounts, InitInputMountPath) { + return + } + + container.VolumeMounts = append(container.VolumeMounts, + corev1.VolumeMount{ + Name: InputVolumeName, + MountPath: InitInputMountPath, + ReadOnly: true, + }, + ) +} diff --git a/pkg/webhook/mutation/pod/v2/config.go b/pkg/webhook/mutation/pod/v2/config.go new file mode 100644 index 0000000000..467e240ed8 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/config.go @@ -0,0 +1,13 @@ +package v2 + +import "github.com/Dynatrace/dynatrace-operator/pkg/logd" + +var ( + log = logd.Get().WithName("v2-pod-mutation") +) + +const ( + NoBootstrapperConfigReason = "NoBootstrapperConfig" + NoCodeModulesImageReason = "NoCodeModulesImage" + NoMutationNeededReason = "NoMutationNeeded" +) diff --git a/pkg/webhook/mutation/pod/v2/init.go b/pkg/webhook/mutation/pod/v2/init.go new file mode 100644 index 0000000000..1f440500c5 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/init.go @@ -0,0 +1,91 @@ +package v2 + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/volumes" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" +) + +func createInitContainerBase(pod *corev1.Pod, dk dynakube.DynaKube) *corev1.Container { + initContainer := &corev1.Container{ + Name: dtwebhook.InstallContainerName, + Image: dk.OneAgent().GetCustomCodeModulesImage(), + ImagePullPolicy: corev1.PullIfNotPresent, + SecurityContext: securityContextForInitContainer(pod, dk), + Resources: initContainerResources(dk), + } + + if areErrorsSuppressed(pod, dk) { + initContainer.Args = append(initContainer.Args, "--suppress-errors") // TODO: import arg from bootstrapper package + } + + // TODO: Add all `--attribute` args to init-container + + return initContainer +} + +func areErrorsSuppressed(pod *corev1.Pod, dk dynakube.DynaKube) bool { + return maputils.GetField(pod.Annotations, dtwebhook.AnnotationFailurePolicy, dk.FeatureInjectionFailurePolicy()) != "fail" // safer than == silent +} + +func addInitContainerToPod(pod *corev1.Pod, initContainer *corev1.Container) { + volumes.AddInitConfigVolumeMount(initContainer) + volumes.AddInitInputVolumeMount(initContainer) + volumes.AddInputVolume(pod) + volumes.AddConfigVolume(pod) + pod.Spec.InitContainers = append(pod.Spec.InitContainers, *initContainer) +} + +func initContainerResources(dk dynakube.DynaKube) corev1.ResourceRequirements { + customInitResources := dk.OneAgent().GetInitResources() + if customInitResources != nil { + return *customInitResources + } + + return corev1.ResourceRequirements{} +} + +func securityContextForInitContainer(pod *corev1.Pod, dk dynakube.DynaKube) *corev1.SecurityContext { + initSecurityCtx := corev1.SecurityContext{ + ReadOnlyRootFilesystem: ptr.To(true), + AllowPrivilegeEscalation: ptr.To(false), + Privileged: ptr.To(false), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{ + "ALL", + }, + }, + RunAsUser: ptr.To(oacommon.DefaultUser), + RunAsGroup: ptr.To(oacommon.DefaultGroup), + } + + addSeccompProfile(&initSecurityCtx, dk) + + return combineSecurityContexts(initSecurityCtx, *pod) +} + +func combineSecurityContexts(baseSecurityCtx corev1.SecurityContext, pod corev1.Pod) *corev1.SecurityContext { + podSecurityCtx := pod.Spec.SecurityContext + + if oacommon.HasPodUserSet(podSecurityCtx) { + baseSecurityCtx.RunAsUser = podSecurityCtx.RunAsUser + } + + if oacommon.HasPodGroupSet(podSecurityCtx) { + baseSecurityCtx.RunAsGroup = podSecurityCtx.RunAsGroup + } + + baseSecurityCtx.RunAsNonRoot = ptr.To(oacommon.IsNonRoot(&baseSecurityCtx)) + + return &baseSecurityCtx +} + +func addSeccompProfile(ctx *corev1.SecurityContext, dk dynakube.DynaKube) { + if dk.FeatureInitContainerSeccomp() { + ctx.SeccompProfile = &corev1.SeccompProfile{Type: corev1.SeccompProfileTypeRuntimeDefault} + } +} diff --git a/pkg/webhook/mutation/pod/v2/init_test.go b/pkg/webhook/mutation/pod/v2/init_test.go new file mode 100644 index 0000000000..854e9dce6b --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/init_test.go @@ -0,0 +1,207 @@ +package v2 + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/mounts" + volumeutils "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/volumes" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/volumes" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" +) + +func TestCreateInitContainerBase(t *testing.T) { + t.Run("should create the init container with set container sec ctx but without user and group", func(t *testing.T) { + dk := getTestDynakubeNoInitLimits() + pod := getTestPod() + pod.Spec.Containers[0].SecurityContext.RunAsUser = nil + pod.Spec.Containers[0].SecurityContext.RunAsGroup = nil + + initContainer := createInitContainerBase(pod, *dk) + + require.NotNil(t, initContainer) + assert.Equal(t, dtwebhook.InstallContainerName, initContainer.Name) + assert.Equal(t, customImage, initContainer.Image) + assert.Empty(t, initContainer.Resources) + + require.NotNil(t, initContainer.SecurityContext.AllowPrivilegeEscalation) + assert.False(t, *initContainer.SecurityContext.AllowPrivilegeEscalation) + + require.NotNil(t, initContainer.SecurityContext.Privileged) + assert.False(t, *initContainer.SecurityContext.Privileged) + + require.NotNil(t, initContainer.SecurityContext.ReadOnlyRootFilesystem) + assert.True(t, *initContainer.SecurityContext.ReadOnlyRootFilesystem) + + require.NotNil(t, initContainer.SecurityContext.RunAsNonRoot) + assert.True(t, *initContainer.SecurityContext.RunAsNonRoot) + + require.NotNil(t, initContainer.SecurityContext.RunAsUser) + assert.Equal(t, oacommon.DefaultUser, *initContainer.SecurityContext.RunAsUser) + + require.NotNil(t, initContainer.SecurityContext.RunAsGroup) + assert.Equal(t, oacommon.DefaultGroup, *initContainer.SecurityContext.RunAsGroup) + + assert.Nil(t, initContainer.SecurityContext.SeccompProfile) + }) + t.Run("do not take security context from user container", func(t *testing.T) { + dk := getTestDynakube() + pod := getTestPod() + testUser := ptr.To(int64(420)) + pod.Spec.Containers[0].SecurityContext.RunAsUser = testUser + pod.Spec.Containers[0].SecurityContext.RunAsGroup = testUser + + initContainer := createInitContainerBase(pod, *dk) + + require.NotNil(t, initContainer.SecurityContext.RunAsNonRoot) + assert.True(t, *initContainer.SecurityContext.RunAsNonRoot) + + require.NotNil(t, *initContainer.SecurityContext.RunAsUser) + assert.Equal(t, oacommon.DefaultUser, *initContainer.SecurityContext.RunAsUser) + + require.NotNil(t, *initContainer.SecurityContext.RunAsGroup) + assert.Equal(t, oacommon.DefaultGroup, *initContainer.SecurityContext.RunAsGroup) + }) + t.Run("PodSecurityContext overrules defaults", func(t *testing.T) { + dk := getTestDynakube() + testUser := ptr.To(int64(420)) + pod := getTestPod() + pod.Spec.Containers[0].SecurityContext = nil + pod.Spec.SecurityContext = &corev1.PodSecurityContext{} + pod.Spec.SecurityContext.RunAsUser = testUser + pod.Spec.SecurityContext.RunAsGroup = testUser + + initContainer := createInitContainerBase(pod, *dk) + + require.NotNil(t, initContainer.SecurityContext.RunAsNonRoot) + assert.True(t, *initContainer.SecurityContext.RunAsNonRoot) + + require.NotNil(t, initContainer.SecurityContext.RunAsUser) + assert.Equal(t, *testUser, *initContainer.SecurityContext.RunAsUser) + + require.NotNil(t, initContainer.SecurityContext.RunAsGroup) + assert.Equal(t, *testUser, *initContainer.SecurityContext.RunAsGroup) + }) + t.Run("should set RunAsNonRoot if root user is used", func(t *testing.T) { + dk := getTestDynakube() + pod := getTestPod() + pod.Spec.SecurityContext = &corev1.PodSecurityContext{} + pod.Spec.SecurityContext.RunAsUser = ptr.To(oacommon.RootUserGroup) + pod.Spec.SecurityContext.RunAsGroup = ptr.To(oacommon.RootUserGroup) + + initContainer := createInitContainerBase(pod, *dk) + + assert.NotNil(t, initContainer.SecurityContext.RunAsNonRoot) + assert.False(t, *initContainer.SecurityContext.RunAsNonRoot) + + require.NotNil(t, *initContainer.SecurityContext.RunAsUser) + assert.Equal(t, oacommon.RootUserGroup, *initContainer.SecurityContext.RunAsUser) + + require.NotNil(t, *initContainer.SecurityContext.RunAsGroup) + assert.Equal(t, oacommon.RootUserGroup, *initContainer.SecurityContext.RunAsGroup) + }) + t.Run("should set seccomp profile if feature flag is enabled", func(t *testing.T) { + dk := getTestDynakube() + dk.Annotations = map[string]string{dynakube.AnnotationFeatureInitContainerSeccomp: "true"} + pod := getTestPod() + pod.Annotations = map[string]string{} + + initContainer := createInitContainerBase(pod, *dk) + + assert.Equal(t, corev1.SeccompProfileTypeRuntimeDefault, initContainer.SecurityContext.SeccompProfile.Type) + }) + + t.Run("should not set suppress-errors arg - according to dk", func(t *testing.T) { + dk := getTestDynakube() + dk.Annotations = map[string]string{dynakube.AnnotationInjectionFailurePolicy: "fail"} + pod := getTestPod() + pod.Annotations = map[string]string{} + + initContainer := createInitContainerBase(pod, *dk) + + assert.NotContains(t, initContainer.Args, "--suppress-errors") + }) + + t.Run("should not set suppress-errors arg - according to pod", func(t *testing.T) { + dk := getTestDynakube() + dk.Annotations = map[string]string{dynakube.AnnotationInjectionFailurePolicy: "silent"} + pod := getTestPod() + pod.Annotations = map[string]string{dtwebhook.AnnotationFailurePolicy: "fail"} + + initContainer := createInitContainerBase(pod, *dk) + + assert.NotContains(t, initContainer.Args, "--suppress-errors") + }) + + t.Run("should set suppress-errors arg - default", func(t *testing.T) { + dk := getTestDynakube() + dk.Annotations = map[string]string{} + pod := getTestPod() + pod.Annotations = map[string]string{} + + initContainer := createInitContainerBase(pod, *dk) + + assert.Contains(t, initContainer.Args, "--suppress-errors") + }) + + t.Run("should set suppress-errors arg - unknown value", func(t *testing.T) { + dk := getTestDynakube() + dk.Annotations = map[string]string{dynakube.AnnotationInjectionFailurePolicy: "asd"} + pod := getTestPod() + pod.Annotations = map[string]string{} + + initContainer := createInitContainerBase(pod, *dk) + + assert.Contains(t, initContainer.Args, "--suppress-errors") + + dk = getTestDynakube() + dk.Annotations = map[string]string{} + pod = getTestPod() + pod.Annotations = map[string]string{dtwebhook.AnnotationFailurePolicy: "asd"} + + initContainer = createInitContainerBase(pod, *dk) + + assert.Contains(t, initContainer.Args, "--suppress-errors") + }) +} + +func TestAddInitContainerToPod(t *testing.T) { + t.Run("adds common volumes/mounts", func(t *testing.T) { + pod := corev1.Pod{} + initContainer := corev1.Container{} + + addInitContainerToPod(&pod, &initContainer) + + assert.Contains(t, pod.Spec.InitContainers, initContainer) + require.Len(t, pod.Spec.Volumes, 2) + assert.True(t, volumeutils.IsIn(pod.Spec.Volumes, volumes.ConfigVolumeName)) + assert.True(t, volumeutils.IsIn(pod.Spec.Volumes, volumes.InputVolumeName)) + require.Len(t, initContainer.VolumeMounts, 2) + assert.True(t, mounts.IsPathIn(initContainer.VolumeMounts, volumes.InitConfigMountPath)) + assert.True(t, mounts.IsPathIn(initContainer.VolumeMounts, volumes.InitInputMountPath)) + }) +} + +func TestInitContainerResources(t *testing.T) { + t.Run("should return nothing per default", func(t *testing.T) { + dk := getTestDynakubeNoInitLimits() + + initResources := initContainerResources(*dk) + + require.Empty(t, initResources) + }) + + t.Run("should return custom if set in dynakube", func(t *testing.T) { + dk := getTestDynakube() + + initResources := initContainerResources(*dk) + + require.NotNil(t, initResources) + assert.Equal(t, testResourceRequirements, initResources) + }) +} diff --git a/pkg/webhook/mutation/pod/v2/metadata/config.go b/pkg/webhook/mutation/pod/v2/metadata/config.go new file mode 100644 index 0000000000..11e7fcedff --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/metadata/config.go @@ -0,0 +1,9 @@ +package metadata + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/logd" +) + +var ( + log = logd.Get().WithName("metadata-enrichment-pod-v2-mutation") +) diff --git a/pkg/webhook/mutation/pod/v2/metadata/containers.go b/pkg/webhook/mutation/pod/v2/metadata/containers.go new file mode 100644 index 0000000000..2ce40b8030 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/metadata/containers.go @@ -0,0 +1,21 @@ +package metadata + +import ( + "context" + + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func Mutate(context context.Context, metaClient client.Client, request *dtwebhook.MutationRequest) bool { + if !metacommon.IsEnabled(request.BaseRequest) { + return false + } + + log.Info("adding metadata-enrichment to pod", "name", request.PodName()) + + // TODO: probably will only modify the iniContainer and pod, not the containers + + return true +} diff --git a/pkg/webhook/mutation/pod/v2/oneagent/config.go b/pkg/webhook/mutation/pod/v2/oneagent/config.go new file mode 100644 index 0000000000..85905db2ad --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/oneagent/config.go @@ -0,0 +1,9 @@ +package oneagent + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/logd" +) + +var ( + log = logd.Get().WithName("v2-pod-mutation-oneagent") +) diff --git a/pkg/webhook/mutation/pod/v2/oneagent/containers.go b/pkg/webhook/mutation/pod/v2/oneagent/containers.go new file mode 100644 index 0000000000..5020f5be19 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/oneagent/containers.go @@ -0,0 +1,68 @@ +package oneagent + +import ( + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + corev1 "k8s.io/api/core/v1" +) + +const ( + isInjectedEnv = "DT_CM_INJECTED" +) + +func Mutate(request *dtwebhook.MutationRequest) bool { + installPath := maputils.GetField(request.Pod.Annotations, oacommon.AnnotationInstallPath, oacommon.DefaultInstallPath) + mutateInitContainer(request, installPath) + + return mutateUserContainers(request.BaseRequest, installPath) +} + +func Reinvoke(request *dtwebhook.BaseRequest) bool { + installPath := maputils.GetField(request.Pod.Annotations, oacommon.AnnotationInstallPath, oacommon.DefaultInstallPath) + + return mutateUserContainers(request, installPath) +} + +func containerIsInjected(container corev1.Container) bool { + return env.IsIn(container.Env, isInjectedEnv) +} + +func mutateUserContainers(request *dtwebhook.BaseRequest, installPath string) bool { + newContainers := request.NewContainers(containerIsInjected) + for i := range newContainers { + container := newContainers[i] + addOneAgentToContainer(request.DynaKube, container, request.Namespace, installPath) + } + + return len(newContainers) > 0 +} + +func addOneAgentToContainer(dk dynakube.DynaKube, container *corev1.Container, namespace corev1.Namespace, installPath string) { + log.Info("adding OneAgent to container", "name", container.Name) + + addVolumeMounts(container, installPath) + oacommon.AddDeploymentMetadataEnv(container, dk) + oacommon.AddPreloadEnv(container, installPath) + + if dk.Spec.NetworkZone != "" { + oacommon.AddNetworkZoneEnv(container, dk.Spec.NetworkZone) + } + + if dk.FeatureLabelVersionDetection() { + oacommon.AddVersionDetectionEnvs(container, namespace) + } + + setIsInjectedEnv(container) +} + +func setIsInjectedEnv(container *corev1.Container) { + container.Env = append(container.Env, + corev1.EnvVar{ + Name: isInjectedEnv, + Value: "true", + }, + ) +} diff --git a/pkg/webhook/mutation/pod/v2/oneagent/containers_test.go b/pkg/webhook/mutation/pod/v2/oneagent/containers_test.go new file mode 100644 index 0000000000..856ceaf954 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/oneagent/containers_test.go @@ -0,0 +1,210 @@ +package oneagent + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" +) + +func TestContainerIsInjected(t *testing.T) { + t.Run("is injected", func(t *testing.T) { + request := createTestMutationRequestWithoutInjectedContainers() + + for _, c := range request.Pod.Spec.Containers { + container := &c + assert.False(t, containerIsInjected(*container)) + setIsInjectedEnv(container) + assert.True(t, containerIsInjected(*container)) + } + }) +} + +func TestMutate(t *testing.T) { + t.Run("success", func(t *testing.T) { + request := createTestMutationRequestWithoutInjectedContainers() + + original := createTestMutationRequestWithoutInjectedContainers() + updated := Mutate(request) + require.True(t, updated) + // update install container + assert.NotEqual(t, original.InstallContainer, request.InstallContainer) + + for i := range request.Pod.Spec.Containers { + // update each container + assert.NotEqual(t, original.Pod.Spec.Containers[i], request.Pod.Spec.Containers[i]) + + assert.True(t, containerIsInjected(request.Pod.Spec.Containers[i])) + } + }) + t.Run("install-path respected", func(t *testing.T) { + expectedInstallPath := "my-install" + request := createTestMutationRequestWithoutInjectedContainers() + request.Pod.Annotations = map[string]string{ + oacommon.AnnotationInstallPath: expectedInstallPath, + } + + updated := Mutate(request) + require.True(t, updated) + + assert.Contains(t, request.InstallContainer.Args, "--"+configure.InstallPathFlag+"="+expectedInstallPath) + + for _, c := range request.Pod.Spec.Containers { + preload := env.FindEnvVar(c.Env, oacommon.PreloadEnv) + require.NotNil(t, preload) + assert.Contains(t, preload.Value, expectedInstallPath) + } + }) + t.Run("no change => no update", func(t *testing.T) { + request := createTestMutationRequestWithoutInjectedContainers() + updateContainer := []corev1.Container{} + + for _, c := range request.Pod.Spec.Containers { + container := &c + setIsInjectedEnv(container) + updateContainer = append(updateContainer, *container) + } + + request.Pod.Spec.Containers = updateContainer + + updated := Mutate(request) + require.False(t, updated) + }) +} + +func TestReinvoke(t *testing.T) { + t.Run("success", func(t *testing.T) { + request := createTestMutationRequestWithInjectedContainers() + + original := createTestMutationRequestWithInjectedContainers() + updated := Reinvoke(request.BaseRequest) + require.True(t, updated) + + // no update to install container + assert.Equal(t, original.InstallContainer, request.InstallContainer) + + for i := range request.Pod.Spec.Containers { + // only update not-injected + if containerIsInjected(original.Pod.Spec.Containers[i]) { + assert.Equal(t, original.Pod.Spec.Containers[i], request.Pod.Spec.Containers[i]) + } else { + assert.NotEqual(t, original.Pod.Spec.Containers[i], request.Pod.Spec.Containers[i]) + } + + assert.True(t, containerIsInjected(request.Pod.Spec.Containers[i])) + } + }) + + t.Run("install-path respected", func(t *testing.T) { + expectedInstallPath := "my-install" + request := createTestMutationRequestWithoutInjectedContainers() + request.Pod.Annotations = map[string]string{ + oacommon.AnnotationInstallPath: expectedInstallPath, + } + + updated := Reinvoke(request.BaseRequest) + require.True(t, updated) + + for _, c := range request.Pod.Spec.Containers { + preload := env.FindEnvVar(c.Env, oacommon.PreloadEnv) + require.NotNil(t, preload) + assert.Contains(t, preload.Value, expectedInstallPath) + } + }) + + t.Run("no change => no update", func(t *testing.T) { + request := createTestMutationRequestWithoutInjectedContainers() + updateContainer := []corev1.Container{} + + for _, c := range request.Pod.Spec.Containers { + container := &c + setIsInjectedEnv(container) + updateContainer = append(updateContainer, *container) + } + + request.Pod.Spec.Containers = updateContainer + + updated := Reinvoke(request.BaseRequest) + require.False(t, updated) + }) +} + +func TestAddOneAgentToContainer(t *testing.T) { + kubeSystemUUID := "my uuid" + networkZone := "my zone" + installPath := "install/path" + + t.Run("add everything", func(t *testing.T) { + container := corev1.Container{} + dk := dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + OneAgent: oneagent.Spec{ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}}, + NetworkZone: networkZone, + }, + Status: dynakube.DynaKubeStatus{ + KubeSystemUUID: kubeSystemUUID, + }, + } + + addOneAgentToContainer(dk, &container, corev1.Namespace{}, installPath) + + assert.Len(t, container.VolumeMounts, 3) // preload,bin,config + + dtMetaEnv := env.FindEnvVar(container.Env, oacommon.DynatraceMetadataEnv) + require.NotNil(t, dtMetaEnv) + assert.Contains(t, dtMetaEnv.Value, kubeSystemUUID) + + dtZoneEnv := env.FindEnvVar(container.Env, oacommon.NetworkZoneEnv) + require.NotNil(t, dtZoneEnv) + assert.Equal(t, networkZone, dtZoneEnv.Value) + + preload := env.FindEnvVar(container.Env, oacommon.PreloadEnv) + require.NotNil(t, preload) + assert.Contains(t, preload.Value, installPath) + + assert.True(t, containerIsInjected(container)) + }) +} + +func createTestMutationRequestWithoutInjectedContainers() *dtwebhook.MutationRequest { + return &dtwebhook.MutationRequest{ + InstallContainer: &corev1.Container{ + Name: dtwebhook.InstallContainerName, + }, + BaseRequest: &dtwebhook.BaseRequest{ + Pod: &corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "sample-container-1", + Image: "sample-image-1", + }, + { + Name: "sample-container-2", + Image: "sample-image-2", + }, + }, + }, + }, + }, + } +} + +func createTestMutationRequestWithInjectedContainers() *dtwebhook.MutationRequest { + request := createTestMutationRequestWithoutInjectedContainers() + + i := 0 + request.Pod.Spec.Containers[i].Env = append(request.Pod.Spec.Containers[i].Env, corev1.EnvVar{ + Name: isInjectedEnv, + Value: "true", + }) + + return request +} diff --git a/pkg/webhook/mutation/pod/v2/oneagent/init.go b/pkg/webhook/mutation/pod/v2/oneagent/init.go new file mode 100644 index 0000000000..606632acd3 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/oneagent/init.go @@ -0,0 +1,53 @@ +package oneagent + +import ( + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure" + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/move" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/arg" + corev1 "k8s.io/api/core/v1" +) + +const ( + bootstrapperSourceArgument = "source" // TODO import consts from bootstrapper + bootstrapperTargetArgument = "target" +) + +func mutateInitContainer(mutationRequest *dtwebhook.MutationRequest, installPath string) { + addInitArgs(*mutationRequest.Pod, mutationRequest.InstallContainer, mutationRequest.DynaKube, installPath) + addInitVolumeMounts(mutationRequest.InstallContainer) +} + +func addInitArgs(pod corev1.Pod, initContainer *corev1.Container, dk dynakube.DynaKube, installPath string) { + args := []arg.Arg{ + {Name: bootstrapperSourceArgument, Value: consts.AgentCodeModuleSource}, // TODO import consts from bootstrapper + {Name: bootstrapperTargetArgument, Value: binInitMountPath}, + {Name: configure.InstallPathFlag, Value: installPath}, + } + + if technology := getTechnology(pod, dk); technology != "" { + args = append(args, arg.Arg{Name: move.TechnologyFlag, Value: technology}) + } + + if initContainer.Args == nil { + initContainer.Args = []string{} + } + + initContainer.Args = append(initContainer.Args, arg.ConvertArgsToStrings(args)...) +} + +func getTechnology(pod corev1.Pod, dk dynakube.DynaKube) string { + if technology, ok := pod.Annotations[oacommon.AnnotationTechnologies]; ok { + return technology + } + + technology := dk.FeatureRemoteImageDownloadTechnology() + if technology != "" { + return technology + } + + return "" +} diff --git a/pkg/webhook/mutation/pod/v2/oneagent/init_test.go b/pkg/webhook/mutation/pod/v2/oneagent/init_test.go new file mode 100644 index 0000000000..4ac6ae1967 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/oneagent/init_test.go @@ -0,0 +1,66 @@ +package oneagent + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestAddInitArgs(t *testing.T) { + t.Run("WithTechnologyAnnotation", func(t *testing.T) { + pod := corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + oacommon.AnnotationTechnologies: "java", + }, + }, + } + initContainer := &corev1.Container{} + dk := dynakube.DynaKube{} + + addInitArgs(pod, initContainer, dk, oacommon.DefaultInstallPath) + + require.Contains(t, initContainer.Args, "--technology=java") + }) + + t.Run("WithTechnologyFeature", func(t *testing.T) { + pod := corev1.Pod{} + initContainer := &corev1.Container{} + dk := dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + dynakube.AnnotationTechnologies: "nodejs", + }, + }, + } + + addInitArgs(pod, initContainer, dk, oacommon.DefaultInstallPath) + + require.Contains(t, initContainer.Args, "--technology=nodejs") + }) + + t.Run("WithoutTechnology", func(t *testing.T) { + pod := corev1.Pod{} + initContainer := &corev1.Container{} + dk := dynakube.DynaKube{} + + addInitArgs(pod, initContainer, dk, oacommon.DefaultInstallPath) + + require.NotContains(t, initContainer.Args, "--technology=") + }) + + t.Run("WithDefaultArgs", func(t *testing.T) { + pod := corev1.Pod{} + initContainer := &corev1.Container{} + dk := dynakube.DynaKube{} + + addInitArgs(pod, initContainer, dk, oacommon.DefaultInstallPath) + + require.Contains(t, initContainer.Args, "--source=/opt/dynatrace/oneagent") + require.Contains(t, initContainer.Args, "--target=/mnt/bin") + }) +} diff --git a/pkg/webhook/mutation/pod/v2/oneagent/volumes.go b/pkg/webhook/mutation/pod/v2/oneagent/volumes.go new file mode 100644 index 0000000000..c7de5c2f82 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/oneagent/volumes.go @@ -0,0 +1,43 @@ +package oneagent + +import ( + "path/filepath" + + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/volumes" + corev1 "k8s.io/api/core/v1" +) + +const ( + binSubPath = "bin" + binInitMountPath = "/mnt/bin" + + ldPreloadPath = "/etc/ld.so.preload" + ldPreloadSubPath = "oneagent/ld.so.preload" // TODO: Get from the bootsrapper lib. +) + +func addVolumeMounts(container *corev1.Container, installPath string) { + container.VolumeMounts = append(container.VolumeMounts, + corev1.VolumeMount{ + Name: volumes.ConfigVolumeName, + MountPath: installPath, + SubPath: binSubPath, + }, + corev1.VolumeMount{ + Name: volumes.ConfigVolumeName, + MountPath: ldPreloadPath, + SubPath: filepath.Join(volumes.InitConfigSubPath, ldPreloadSubPath), + }, + ) + + volumes.AddConfigVolumeMount(container) +} + +func addInitVolumeMounts(initContainer *corev1.Container) { + initContainer.VolumeMounts = append(initContainer.VolumeMounts, + corev1.VolumeMount{ + Name: volumes.ConfigVolumeName, + MountPath: binInitMountPath, + SubPath: binSubPath, + }, + ) +} diff --git a/pkg/webhook/mutation/pod/v2/oneagent/volumes_test.go b/pkg/webhook/mutation/pod/v2/oneagent/volumes_test.go new file mode 100644 index 0000000000..67acb038a8 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/oneagent/volumes_test.go @@ -0,0 +1,46 @@ +package oneagent + +import ( + "path/filepath" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/volumes" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" +) + +func TestAddVolumeMounts(t *testing.T) { + t.Run("should add oneagent volume mounts", func(t *testing.T) { + container := &corev1.Container{ + Name: "test-container", + } + installPath := "test/path" + + addVolumeMounts(container, installPath) + require.Len(t, container.VolumeMounts, 3) + assert.Equal(t, volumes.ConfigVolumeName, container.VolumeMounts[0].Name) + assert.Equal(t, installPath, container.VolumeMounts[0].MountPath) + assert.Equal(t, binSubPath, container.VolumeMounts[0].SubPath) + + assert.Equal(t, volumes.ConfigVolumeName, container.VolumeMounts[1].Name) + assert.Equal(t, ldPreloadPath, container.VolumeMounts[1].MountPath) + assert.Equal(t, filepath.Join(volumes.InitConfigSubPath, ldPreloadSubPath), container.VolumeMounts[1].SubPath) + + assert.Equal(t, volumes.ConfigVolumeName, container.VolumeMounts[2].Name) + assert.Equal(t, filepath.Join(volumes.InitConfigSubPath, container.Name), container.VolumeMounts[2].SubPath) + assert.Equal(t, volumes.ConfigMountPath, container.VolumeMounts[2].MountPath) + }) +} + +func TestAddInitVolumeMounts(t *testing.T) { + t.Run("should add init volume mounts", func(t *testing.T) { + container := &corev1.Container{} + + addInitVolumeMounts(container) + require.Len(t, container.VolumeMounts, 1) + assert.Equal(t, volumes.ConfigVolumeName, container.VolumeMounts[0].Name) + assert.Equal(t, binInitMountPath, container.VolumeMounts[0].MountPath) + assert.Equal(t, binSubPath, container.VolumeMounts[0].SubPath) + }) +} diff --git a/pkg/webhook/mutation/pod/v2/webhook.go b/pkg/webhook/mutation/pod/v2/webhook.go new file mode 100644 index 0000000000..aaa6f605e6 --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/webhook.go @@ -0,0 +1,147 @@ +package v2 + +import ( + "context" + + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + metamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/metadata" + oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/oneagent" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Injector struct { + recorder events.EventRecorder + apiReader client.Reader + metaClient client.Client +} + +var _ dtwebhook.PodInjector = &Injector{} + +func NewInjector(apiReader client.Reader, metaClient client.Client, recorder events.EventRecorder) *Injector { + return &Injector{ + recorder: recorder, + apiReader: apiReader, + metaClient: metaClient, + } +} + +func (wh *Injector) Handle(ctx context.Context, mutationRequest *dtwebhook.MutationRequest) error { + wh.recorder.Setup(mutationRequest) + + if !wh.isInputSecretPresent(mutationRequest) { + return nil + } + + if !isCustomImageSet(mutationRequest) { + return nil + } + + if wh.isInjected(mutationRequest) { + if wh.handlePodReinvocation(mutationRequest) { + log.Info("reinvocation policy applied", "podName", mutationRequest.PodName()) + wh.recorder.SendPodUpdateEvent() + + return nil + } + + log.Info("no change, all containers already injected", "podName", mutationRequest.PodName()) + } else { + if err := wh.handlePodMutation(ctx, mutationRequest); err != nil { + return err + } + } + + setDynatraceInjectedAnnotation(mutationRequest) + + log.Info("injection finished for pod", "podName", mutationRequest.PodName(), "namespace", mutationRequest.Namespace.Name) + + return nil +} + +func (wh *Injector) isInjected(mutationRequest *dtwebhook.MutationRequest) bool { + installContainer := container.FindInitContainerInPodSpec(&mutationRequest.Pod.Spec, dtwebhook.InstallContainerName) + if installContainer != nil { + log.Info("Dynatrace init-container already present, skipping mutation, doing reinvocation", "containerName", dtwebhook.InstallContainerName) + + return true + } + + return false +} + +func (wh *Injector) handlePodMutation(ctx context.Context, mutationRequest *dtwebhook.MutationRequest) error { + mutationRequest.InstallContainer = createInitContainerBase(mutationRequest.Pod, mutationRequest.DynaKube) + + updated := oamutation.Mutate(mutationRequest) + if !updated { + oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoMutationNeededReason) + + return nil + } + + oacommon.SetInjectedAnnotation(mutationRequest.Pod) + + _ = metamutation.Mutate(ctx, wh.metaClient, mutationRequest) // TODO: finalize + + // TODO: Add `--attribute-container` for new containers to init-container + addInitContainerToPod(mutationRequest.Pod, mutationRequest.InstallContainer) + wh.recorder.SendPodInjectEvent() + + return nil +} + +func (wh *Injector) handlePodReinvocation(mutationRequest *dtwebhook.MutationRequest) bool { + updated := oamutation.Reinvoke(mutationRequest.BaseRequest) + // TODO: Add `--attribute-container` for new containers to init-container + + return updated +} + +func isCustomImageSet(mutationRequest *dtwebhook.MutationRequest) bool { + customImage := mutationRequest.DynaKube.OneAgent().GetCustomCodeModulesImage() + if customImage == "" { + oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoCodeModulesImageReason) + + return false + } + + return true +} + +func (wh *Injector) isInputSecretPresent(mutationRequest *dtwebhook.MutationRequest) bool { + var initSecret corev1.Secret + + secretObjectKey := client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: mutationRequest.Namespace.Name} + err := wh.apiReader.Get(mutationRequest.Context, secretObjectKey, &initSecret) + + if k8serrors.IsNotFound(err) { + log.Info("dynatrace-bootstrapper-config is not available, injection not possible", "pod", mutationRequest.PodName()) + + oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoBootstrapperConfigReason) + + return false + } else if err != nil { + log.Error(err, "unable to verify, if dynatrace-bootstrapper-config is available, injection not possible") + + oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoBootstrapperConfigReason) + + return false + } + + return true +} + +func setDynatraceInjectedAnnotation(mutationRequest *dtwebhook.MutationRequest) { + if mutationRequest.Pod.Annotations == nil { + mutationRequest.Pod.Annotations = make(map[string]string) + } + + mutationRequest.Pod.Annotations[dtwebhook.AnnotationDynatraceInjected] = "true" + delete(mutationRequest.Pod.Annotations, dtwebhook.AnnotationDynatraceReason) +} diff --git a/pkg/webhook/mutation/pod/v2/webhook_test.go b/pkg/webhook/mutation/pod/v2/webhook_test.go new file mode 100644 index 0000000000..064d046c5c --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/webhook_test.go @@ -0,0 +1,236 @@ +package v2 + +import ( + "context" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/record" + "k8s.io/utils/ptr" +) + +const ( + testNamespaceName = "test-namespace" + testPodName = "test-pod" + testDynakubeName = "test-dynakube" + customImage = "custom-image" +) + +func TestHandle(t *testing.T) { + ctx := context.Background() + + initSecret := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: consts.BootstrapperInitSecretName, + Namespace: testNamespaceName, + }, + } + + t.Run("no init secret => no injection + only annotation", func(t *testing.T) { + injector := createTestInjector() + injector.apiReader = fake.NewClient() + + request := createTestMutationRequest(getTestDynakube()) + + err := injector.Handle(ctx, request) + require.NoError(t, err) + + isInjected, ok := request.Pod.Annotations[oacommon.AnnotationInjected] + require.True(t, ok) + assert.Equal(t, "false", isInjected) + + reason, ok := request.Pod.Annotations[oacommon.AnnotationReason] + require.True(t, ok) + assert.Equal(t, NoBootstrapperConfigReason, reason) + }) + + t.Run("no codeModulesImage => no injection + only annotation", func(t *testing.T) { + injector := createTestInjector() + injector.apiReader = fake.NewClient(&initSecret) + + request := createTestMutationRequest(&dynakube.DynaKube{}) + + err := injector.Handle(ctx, request) + require.NoError(t, err) + + isInjected, ok := request.Pod.Annotations[oacommon.AnnotationInjected] + require.True(t, ok) + assert.Equal(t, "false", isInjected) + + reason, ok := request.Pod.Annotations[oacommon.AnnotationReason] + require.True(t, ok) + assert.Equal(t, NoCodeModulesImageReason, reason) + }) +} + +func TestIsInjected(t *testing.T) { + t.Run("init-container present == injected", func(t *testing.T) { + injector := createTestInjector() + + assert.True(t, injector.isInjected(createTestMutationRequestWithInjectedPod(getTestDynakube()))) + }) + + t.Run("init-container NOT present != injected", func(t *testing.T) { + injector := createTestInjector() + + assert.False(t, injector.isInjected(createTestMutationRequest(getTestDynakube()))) + }) +} + +func createTestInjector() *Injector { + return &Injector{ + recorder: events.NewRecorder(record.NewFakeRecorder(10)), + } +} + +func getTestDynakube() *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: getTestDynakubeMeta(), + Spec: dynakube.DynaKubeSpec{ + OneAgent: getAppMonSpec(&testResourceRequirements), + }, + } +} + +var testResourceRequirements = corev1.ResourceRequirements{ + Limits: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("100Mi"), + }, +} + +func getTestDynakubeNoInitLimits() *dynakube.DynaKube { + return &dynakube.DynaKube{ + ObjectMeta: getTestDynakubeMeta(), + Spec: dynakube.DynaKubeSpec{ + OneAgent: getAppMonSpec(nil), + }, + } +} + +func getTestDynakubeMeta() metav1.ObjectMeta { + return metav1.ObjectMeta{ + Name: testDynakubeName, + Namespace: testNamespaceName, + Annotations: map[string]string{ + dynakube.AnnotationFeatureRemoteImageDownload: "true", + }, + } +} + +func getAppMonSpec(initResources *corev1.ResourceRequirements) oneagent.Spec { + return oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{ + InitResources: initResources, + CodeModulesImage: customImage, + }}, + } +} + +func getTestPod() *corev1.Pod { + return &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPodName, + Namespace: testNamespaceName, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "container", + Image: "alpine", + SecurityContext: getTestSecurityContext(), + }, + }, + InitContainers: []corev1.Container{ + { + Name: "init-container", + Image: "alpine", + }, + }, + Volumes: []corev1.Volume{ + { + Name: "volume", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + }, + }, + } +} + +const testUser int64 = 420 + +func getTestSecurityContext() *corev1.SecurityContext { + return &corev1.SecurityContext{ + RunAsUser: ptr.To(testUser), + RunAsGroup: ptr.To(testUser), + } +} + +func createTestMutationRequest(dk *dynakube.DynaKube) *dtwebhook.MutationRequest { + return dtwebhook.NewMutationRequest(context.Background(), *getTestNamespace(), nil, getTestPod(), *dk) +} + +func createTestMutationRequestWithInjectedPod(dk *dynakube.DynaKube) *dtwebhook.MutationRequest { + return dtwebhook.NewMutationRequest(context.Background(), *getTestNamespace(), nil, getInjectedPod(), *dk) +} + +func getInjectedPod() *corev1.Pod { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPodName, + Namespace: testNamespaceName, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "container", + Image: "alpine", + SecurityContext: getTestSecurityContext(), + }, + }, + InitContainers: []corev1.Container{ + { + Name: "init-container", + Image: "alpine", + }, + }, + Volumes: []corev1.Volume{ + { + Name: "volume", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + }, + }, + } + installContainer := createInitContainerBase(pod, *getTestDynakube()) + pod.Spec.InitContainers = append(pod.Spec.InitContainers, *installContainer) + + return pod +} + +func getTestNamespace() *corev1.Namespace { + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: testNamespaceName, + Labels: map[string]string{ + dtwebhook.InjectionInstanceLabel: testDynakubeName, + }, + }, + } +} diff --git a/pkg/webhook/mutation/pod/webhook.go b/pkg/webhook/mutation/pod/webhook.go index 51cef79242..e09fe6f7c4 100644 --- a/pkg/webhook/mutation/pod/webhook.go +++ b/pkg/webhook/mutation/pod/webhook.go @@ -6,11 +6,12 @@ import ( "fmt" "os" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" k8spod "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/pod" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -38,18 +39,16 @@ func AddWebhookToManager(ctx context.Context, mgr manager.Manager, ns string) er } type webhook struct { + v1 dtwebhook.PodInjector + v2 dtwebhook.PodInjector + + recorder events.EventRecorder decoder admission.Decoder - recorder eventRecorder apiReader client.Reader - webhookImage string webhookNamespace string - clusterID string - - mutators []dtwebhook.PodMutator - apmExists bool - deployedViaOLM bool + deployedViaOLM bool } func (wh *webhook) Handle(ctx context.Context, request admission.Request) admission.Response { @@ -75,23 +74,18 @@ func (wh *webhook) Handle(ctx context.Context, request admission.Request) admiss return emptyPatch } - wh.setupEventRecorder(mutationRequest) + wh.recorder.Setup(mutationRequest) - if wh.isInjected(mutationRequest) { - if wh.handlePodReinvocation(mutationRequest) { - log.Info("reinvocation policy applied", "podName", podName) - wh.recorder.sendPodUpdateEvent() - - return createResponseForPod(mutationRequest.Pod, request) + if mutationRequest.DynaKube.FeatureBootstrapperInjection() && oacommon.IsEnabled(mutationRequest.BaseRequest) { + err := wh.v2.Handle(ctx, mutationRequest) + if err != nil { + return silentErrorResponse(mutationRequest.Pod, err) + } + } else { + err := wh.v1.Handle(ctx, mutationRequest) + if err != nil { + return silentErrorResponse(mutationRequest.Pod, err) } - - log.Info("no change, all containers already injected", "podName", podName) - - return emptyPatch - } - - if err := wh.handlePodMutation(ctx, mutationRequest); err != nil { - return silentErrorResponse(mutationRequest.Pod, err) } log.Info("injection finished for pod", "podName", podName, "namespace", request.Namespace) @@ -104,29 +98,14 @@ func mutationRequired(mutationRequest *dtwebhook.MutationRequest) bool { return false } - return maputils.GetFieldBool(mutationRequest.Pod.Annotations, dtwebhook.AnnotationDynatraceInject, true) -} - -func (wh *webhook) setupEventRecorder(mutationRequest *dtwebhook.MutationRequest) { - wh.recorder.dk = &mutationRequest.DynaKube - wh.recorder.pod = mutationRequest.Pod -} - -func (wh *webhook) isInjected(mutationRequest *dtwebhook.MutationRequest) bool { - for _, mutator := range wh.mutators { - if mutator.Injected(mutationRequest.BaseRequest) { - return true - } - } - - installContainer := container.FindInitContainerInPodSpec(&mutationRequest.Pod.Spec, dtwebhook.InstallContainerName) - if installContainer != nil { - log.Info("Dynatrace init-container already present, skipping mutation, doing reinvocation", "containerName", dtwebhook.InstallContainerName) + enabledOnPod := maputils.GetFieldBool(mutationRequest.Pod.Annotations, dtwebhook.AnnotationDynatraceInject, true) - return true + enabledOnContainers := false + for _, container := range mutationRequest.Pod.Spec.Containers { + enabledOnContainers = enabledOnContainers || !dtwebhook.IsContainerExcludedFromInjection(mutationRequest.DynaKube.Annotations, mutationRequest.Pod.Annotations, container.Name) } - return false + return enabledOnPod && enabledOnContainers } func (wh *webhook) isOcDebugPod(pod *corev1.Pod) bool { @@ -141,83 +120,6 @@ func (wh *webhook) isOcDebugPod(pod *corev1.Pod) bool { return true } -func podNeedsInjection(mutationRequest *dtwebhook.MutationRequest) bool { - needsInjection := false - for _, container := range mutationRequest.Pod.Spec.Containers { - needsInjection = needsInjection || !dtwebhook.IsContainerExcludedFromInjection(mutationRequest.DynaKube.Annotations, mutationRequest.Pod.Annotations, container.Name) - } - - return needsInjection -} - -func (wh *webhook) handlePodMutation(ctx context.Context, mutationRequest *dtwebhook.MutationRequest) error { - if !podNeedsInjection(mutationRequest) { - log.Info("no mutation is needed, all containers are excluded from injection.") - - return nil - } - - mutationRequest.InstallContainer = createInstallInitContainerBase(wh.webhookImage, wh.clusterID, mutationRequest.Pod, mutationRequest.DynaKube) - - _ = updateContainerInfo(mutationRequest.BaseRequest, mutationRequest.InstallContainer) - - var isMutated bool - - for _, mutator := range wh.mutators { - if !mutator.Enabled(mutationRequest.BaseRequest) { - continue - } - - if err := mutator.Mutate(ctx, mutationRequest); err != nil { - return err - } - - isMutated = true - } - - if !isMutated { - log.Info("no mutation is enabled") - - return nil - } - - addInitContainerToPod(mutationRequest.Pod, mutationRequest.InstallContainer) - wh.recorder.sendPodInjectEvent() - setDynatraceInjectedAnnotation(mutationRequest) - - return nil -} - -func (wh *webhook) handlePodReinvocation(mutationRequest *dtwebhook.MutationRequest) bool { - var needsUpdate bool - - reinvocationRequest := mutationRequest.ToReinvocationRequest() - - isMutated := updateContainerInfo(reinvocationRequest.BaseRequest, nil) - - if !isMutated { // == no new containers were detected, we only mutate new containers during reinvoke - return false - } - - for _, mutator := range wh.mutators { - if mutator.Enabled(mutationRequest.BaseRequest) { - if update := mutator.Reinvoke(reinvocationRequest); update { - needsUpdate = true - } - } - } - - return needsUpdate -} - -func setDynatraceInjectedAnnotation(mutationRequest *dtwebhook.MutationRequest) { - if mutationRequest.Pod.Annotations == nil { - mutationRequest.Pod.Annotations = make(map[string]string) - } - - mutationRequest.Pod.Annotations[dtwebhook.AnnotationDynatraceInjected] = "true" -} - // createResponseForPod tries to format pod as json func createResponseForPod(pod *corev1.Pod, req admission.Request) admission.Response { marshaledPod, err := json.MarshalIndent(pod, "", " ") diff --git a/pkg/webhook/mutation/pod/webhook_test.go b/pkg/webhook/mutation/pod/webhook_test.go index 4acd4f8989..239e8d757c 100644 --- a/pkg/webhook/mutation/pod/webhook_test.go +++ b/pkg/webhook/mutation/pod/webhook_test.go @@ -2,28 +2,24 @@ package pod import ( "context" - "encoding/json" + "errors" "testing" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" - "github.com/Dynatrace/dynatrace-operator/pkg/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" - "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/metadata" - oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" webhookmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/webhook" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) @@ -36,323 +32,281 @@ const ( testDynakubeName = "test-dynakube" ) -var testResourceRequirements = corev1.ResourceRequirements{ - Limits: map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceCPU: resource.MustParse("100m"), - corev1.ResourceMemory: resource.MustParse("100Mi"), - }, -} +func TestHandle(t *testing.T) { + ctx := context.Background() -type mutatorTest struct { - name string - mutators []dtwebhook.PodMutator - testPod *corev1.Pod - objects []client.Object - expectedResult func(t *testing.T, response *admission.Response, mutators []dtwebhook.PodMutator) -} + t.Run("can't get NS ==> no inject, err in message", func(t *testing.T) { + wh := createTestWebhook( + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), + []client.Object{}, + ) -func TestMutator(t *testing.T) { - tests := []mutatorTest{ - { - name: "happy path", - mutators: []dtwebhook.PodMutator{createSimplePodMutatorMock(t), createSimplePodMutatorMock(t)}, - testPod: getTestPod(), - objects: []client.Object{getTestDynakube(), getTestNamespace()}, - expectedResult: func(t *testing.T, response *admission.Response, mutators []dtwebhook.PodMutator) { - require.NotNil(t, response) - assert.True(t, response.Allowed) - assert.Nil(t, response.Result) - assert.NotNil(t, response.Patches) - - for _, mutator := range mutators { - assertPodMutatorCalls(t, mutator, 1) - } - }, - }, - { - name: "disable all mutators with dynatrace.com/inject", - mutators: []dtwebhook.PodMutator{createSimplePodMutatorMock(t), createSimplePodMutatorMock(t)}, - testPod: getTestPodWithInjectionDisabled(), - objects: []client.Object{getTestDynakube(), getTestNamespace()}, - expectedResult: func(t *testing.T, response *admission.Response, mutators []dtwebhook.PodMutator) { - require.NotNil(t, response) - assert.True(t, response.Allowed) - assert.NotNil(t, response.Result) - assert.Nil(t, response.Patches) - - for _, mutator := range mutators { - assertPodMutatorCalls(t, mutator, 0) - } - }, - }, - { - name: "sad path", - mutators: []dtwebhook.PodMutator{createFailPodMutatorMock(t)}, - testPod: getTestPod(), - objects: []client.Object{getTestDynakube(), getTestNamespace()}, - expectedResult: func(t *testing.T, response *admission.Response, mutators []dtwebhook.PodMutator) { - require.NotNil(t, response) - assert.True(t, response.Allowed) - assert.Contains(t, response.Result.Message, "Failed") - assert.Nil(t, response.Patches) - - for _, mutator := range mutators { - assertPodMutatorCalls(t, mutator, 1) - } - - // Logging newline so go test can parse the output correctly - log.Info("") - }, - }, - { - name: "oc debug pod", - mutators: []dtwebhook.PodMutator{createSimplePodMutatorMock(t)}, - testPod: getTestPodWithOcDebugPodAnnotations(), - objects: []client.Object{getTestDynakube(), getTestNamespace()}, - expectedResult: func(t *testing.T, response *admission.Response, mutators []dtwebhook.PodMutator) { - require.NotNil(t, response) - assert.True(t, response.Allowed) - assert.NotNil(t, response.Result) - assert.Nil(t, response.Patches) - assert.Nil(t, response.Patch) - - for _, mutator := range mutators { - assertPodMutatorCalls(t, mutator, 0) - } - }, - }, - } + request := createTestAdmissionRequest(getTestPodWithInjectionDisabled()) - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - ctx := context.Background() - request := createTestAdmissionRequest(test.testPod) - // merge test objects with the test pod - objects := test.objects - objects = append(objects, test.testPod) - podWebhook := createTestWebhook(test.mutators, objects) - - response := podWebhook.Handle(ctx, *request) - test.expectedResult(t, &response, test.mutators) - }) - } -} + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.True(t, resp.Allowed) + assert.NotEmpty(t, resp.Result.Message) + assert.Contains(t, resp.Result.Message, "err") + }) -// TestDoubleInjection is special test case for making sure that we do not inject the init-container 2 times incase 1 of the mutators are skipped. -// The mutators are intentionally NOT mocked, as to mock them properly for this scenario you would need to basically reimplement them in the mock. -// This test is necessary as the current interface is not ready to handle the scenario properly. -// Scenario: OneAgent mutation is Enabled however needs to be skipped due to not meeting the requirements, so it needs to annotate but not fully inject -func TestDoubleInjection(t *testing.T) { - noCommunicationHostDK := getTestDynakube() - fakeClient := fake.NewClient(noCommunicationHostDK, getTestNamespace()) - podWebhook := &webhook{ - apiReader: fakeClient, - decoder: admission.NewDecoder(scheme.Scheme), - recorder: eventRecorder{recorder: record.NewFakeRecorder(10), pod: &corev1.Pod{}, dk: noCommunicationHostDK}, - webhookImage: testImage, - webhookNamespace: testNamespaceName, - clusterID: testClusterID, - apmExists: false, - mutators: []dtwebhook.PodMutator{ - oamutation.NewMutator( - testImage, - testClusterID, - testNamespaceName, - fakeClient, - fakeClient, - ), - metadata.NewMutator( - testNamespaceName, - fakeClient, - fakeClient, - fakeClient, - ), - }, - } + t.Run("can't get DK ==> no inject, err in message", func(t *testing.T) { + wh := createTestWebhook( + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), + []client.Object{getTestNamespace()}, + ) - pod := getTestPod() + request := createTestAdmissionRequest(getTestPodWithInjectionDisabled()) - request := createTestAdmissionRequest(pod) + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.True(t, resp.Allowed) + assert.NotEmpty(t, resp.Result.Message) + assert.Contains(t, resp.Result.Message, "err") + }) - response := podWebhook.Handle(context.Background(), *request) - require.NotNil(t, response) - assert.True(t, response.Allowed) - assert.Nil(t, response.Result) - require.Len(t, response.Patches, 2) + t.Run("DK name missing from NS but OLM ==> no inject, no err in message", func(t *testing.T) { + ns := getTestNamespace() + ns.Labels = map[string]string{} + wh := createTestWebhook( + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), + []client.Object{ns}, + ) + wh.deployedViaOLM = true + + request := createTestAdmissionRequest(getTestPodWithInjectionDisabled()) + + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.True(t, resp.Allowed) + assert.NotEmpty(t, resp.Result.Message) + assert.NotContains(t, resp.Result.Message, "err") + }) - allowedPatchPaths := []string{ - "/spec/initContainers/1", - "/metadata/annotations", - } - alreadySeenPaths := []string{} + t.Run("DK name missing from NS ==> no inject, err in message", func(t *testing.T) { + ns := getTestNamespace() + ns.Labels = map[string]string{} + wh := createTestWebhook( + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), + []client.Object{ns}, + ) + + request := createTestAdmissionRequest(getTestPodWithInjectionDisabled()) + + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.True(t, resp.Allowed) + assert.NotEmpty(t, resp.Result.Message) + assert.Contains(t, resp.Result.Message, "err") + }) - for _, patch := range response.Patches { - path := patch.Path - assert.NotContains(t, alreadySeenPaths, path) - assert.Contains(t, allowedPatchPaths, path) - alreadySeenPaths = append(alreadySeenPaths, path) - } + t.Run("no inject annotation ==> no inject, empty patch", func(t *testing.T) { + wh := createTestWebhook( + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), + []client.Object{ + getTestNamespace(), + getTestDynakube(), + }, + ) - // simulate initial mutation, annotations + init-container <== skip in case on communication hosts - pod.Annotations = map[string]string{ - dtwebhook.AnnotationOneAgentInjected: "false", - dtwebhook.AnnotationOneAgentReason: oamutation.EmptyConnectionInfoReason, - } - pod.Spec.InitContainers = append(pod.Spec.InitContainers, corev1.Container{Name: dtwebhook.InstallContainerName}) + request := createTestAdmissionRequest(getTestPodWithInjectionDisabled()) - // adding communicationHost to the dynakube to make the scenario more complicated - // it shouldn't try to mutate the pod because now it could be enabled, that is just asking for trouble. - communicationHostDK := getTestDynakube() - communicationHostDK.Status.OneAgent.ConnectionInfoStatus.CommunicationHosts = []oneagent.CommunicationHostStatus{{Host: "test"}} - fakeClient = fake.NewClient(communicationHostDK, getTestNamespace()) - podWebhook.apiReader = fakeClient + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.True(t, resp.Allowed) + assert.Equal(t, admission.Patched(""), resp) + }) - // simulate a Reinvocation - request = createTestAdmissionRequest(pod) - response = podWebhook.Handle(context.Background(), *request) + t.Run("no inject annotation (per container) ==> no inject, empty patch", func(t *testing.T) { + wh := createTestWebhook( + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), + []client.Object{ + getTestNamespace(), + getTestDynakube(), + }, + ) - require.NotNil(t, response) - assert.Equal(t, admission.Patched(""), response) -} + request := createTestAdmissionRequest(getTestPodWithInjectionDisabledOnContainer()) -func TestHandlePodMutation(t *testing.T) { - t.Run("should call both mutators, initContainer and annotation added, no error", func(t *testing.T) { - mutator1 := createSimplePodMutatorMock(t) - mutator2 := createSimplePodMutatorMock(t) - dk := getTestDynakube() - podWebhook := createTestWebhook([]dtwebhook.PodMutator{mutator1, mutator2}, nil) - mutationRequest := createTestMutationRequest(dk) + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.True(t, resp.Allowed) + assert.Equal(t, admission.Patched(""), resp) + }) - err := podWebhook.handlePodMutation(context.Background(), mutationRequest) - require.NoError(t, err) - assert.NotNil(t, mutationRequest.InstallContainer) + t.Run("OC debug pod ==> no inject", func(t *testing.T) { + wh := createTestWebhook( + webhookmock.NewPodInjector(t), + webhookmock.NewPodInjector(t), + []client.Object{ + getTestNamespace(), + getTestDynakube(), + }, + ) - require.Len(t, mutationRequest.Pod.Spec.InitContainers, 2) + request := createTestAdmissionRequest(getTestPodWithOcDebugPodAnnotations()) - assertContainersInfo(t, mutationRequest.ToReinvocationRequest(), &mutationRequest.Pod.Spec.InitContainers[1]) + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.True(t, resp.Allowed) + assert.Equal(t, admission.Patched(""), resp) + }) - initSecurityContext := mutationRequest.Pod.Spec.InitContainers[1].SecurityContext - require.NotNil(t, initSecurityContext) + t.Run("no FF appmon-dk ==> v1 injector", func(t *testing.T) { + v1Injector := webhookmock.NewPodInjector(t) + v1Injector.On("Handle", mock.Anything, mock.Anything).Return(nil) + wh := createTestWebhook( + v1Injector, + webhookmock.NewPodInjector(t), + []client.Object{ + getTestNamespace(), + getTestDynakubeDefaultAppMon(), + }, + ) - require.NotNil(t, initSecurityContext.Privileged) - assert.False(t, *initSecurityContext.Privileged) + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) - require.NotNil(t, initSecurityContext.AllowPrivilegeEscalation) - assert.False(t, *initSecurityContext.AllowPrivilegeEscalation) + request := createTestAdmissionRequest(getTestPod()) - require.NotNil(t, initSecurityContext.ReadOnlyRootFilesystem) - assert.True(t, *initSecurityContext.ReadOnlyRootFilesystem) + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.NotEqual(t, admission.Patched(""), resp) + }) - assert.NotNil(t, initSecurityContext.RunAsNonRoot) - assert.True(t, *initSecurityContext.RunAsNonRoot) + t.Run("FF appmon-dk WITHOUT CSI ==> v2 injector", func(t *testing.T) { + dk := getTestDynakubeDefaultAppMon() + dk.Annotations = map[string]string{ + dynakube.AnnotationFeatureRemoteImageDownload: "true", + } - assert.Equal(t, mutationRequest.Pod.Spec.InitContainers[1].Resources, testResourceRequirements) - assert.Equal(t, "true", mutationRequest.Pod.Annotations[dtwebhook.AnnotationDynatraceInjected]) - mutator1.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) - mutator1.AssertCalled(t, "Mutate", mock.Anything, mutationRequest) - mutator2.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) - mutator2.AssertCalled(t, "Mutate", mock.Anything, mutationRequest) - }) - t.Run("should call 1 webhook, 1 error, no initContainer and annotation", func(t *testing.T) { - sadMutator := createFailPodMutatorMock(t) - happyMutator := createSimplePodMutatorMock(t) - dk := getTestDynakube() - podWebhook := createTestWebhook([]dtwebhook.PodMutator{sadMutator, happyMutator}, nil) - mutationRequest := createTestMutationRequest(dk) - - err := podWebhook.handlePodMutation(context.Background(), mutationRequest) - require.Error(t, err) - assert.NotNil(t, mutationRequest.InstallContainer) - assert.Len(t, mutationRequest.Pod.Spec.InitContainers, 1) - assert.NotEqual(t, "true", mutationRequest.Pod.Annotations[dtwebhook.AnnotationDynatraceInjected]) - sadMutator.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) - sadMutator.AssertCalled(t, "Mutate", mock.Anything, mutationRequest) - happyMutator.AssertNotCalled(t, "Enabled", mock.Anything) - happyMutator.AssertNotCalled(t, "Mutate", mock.Anything, mock.Anything) + v2Injector := webhookmock.NewPodInjector(t) + v2Injector.On("Handle", mock.Anything, mock.Anything).Return(nil) + wh := createTestWebhook( + webhookmock.NewPodInjector(t), + v2Injector, + []client.Object{ + getTestNamespace(), + dk, + }, + ) + + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + + request := createTestAdmissionRequest(getTestPod()) + + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.NotEqual(t, admission.Patched(""), resp) }) -} -func TestHandlePodReinvocation(t *testing.T) { - t.Run("should call both mutators, updated == true", func(t *testing.T) { - mutator1 := createAlreadyInjectedPodMutatorMock(t) - mutator2 := createAlreadyInjectedPodMutatorMock(t) - dk := getTestDynakube() - podWebhook := createTestWebhook([]dtwebhook.PodMutator{mutator1, mutator2}, nil) - mutationRequest := createTestMutationRequestWithInjectedPod(dk) + t.Run("FF metadata-dk WITHOUT CSI ==> v1 injector", func(t *testing.T) { + dk := getTestMetadataDynakube() + dk.Annotations = map[string]string{ + dynakube.AnnotationFeatureRemoteImageDownload: "true", + } + + v1Injector := webhookmock.NewPodInjector(t) + v1Injector.On("Handle", mock.Anything, mock.Anything).Return(nil) + wh := createTestWebhook( + v1Injector, + webhookmock.NewPodInjector(t), + []client.Object{ + getTestNamespace(), + dk, + }, + ) - updated := podWebhook.handlePodReinvocation(mutationRequest) - require.True(t, updated) + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) - require.Len(t, mutationRequest.Pod.Spec.InitContainers, 2) - assertContainersInfo(t, mutationRequest.ToReinvocationRequest(), &mutationRequest.Pod.Spec.InitContainers[1]) + request := createTestAdmissionRequest(getTestPod()) - mutator1.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) - mutator1.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) - mutator2.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) - mutator2.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) - }) - t.Run("should call both webhook, only 1 update, updated == true", func(t *testing.T) { - failingMutator := createFailPodMutatorMock(t) - workingMutator := createAlreadyInjectedPodMutatorMock(t) - dk := getTestDynakube() - podWebhook := createTestWebhook([]dtwebhook.PodMutator{failingMutator, workingMutator}, nil) - mutationRequest := createTestMutationRequestWithInjectedPod(dk) - - updated := podWebhook.handlePodReinvocation(mutationRequest) - require.True(t, updated) - failingMutator.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) - failingMutator.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) - workingMutator.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) - workingMutator.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) - }) - t.Run("should call webhook, no update", func(t *testing.T) { - failingMutator := createFailPodMutatorMock(t) - dk := getTestDynakube() - podWebhook := createTestWebhook([]dtwebhook.PodMutator{failingMutator}, nil) - mutationRequest := createTestMutationRequestWithInjectedPod(dk) - - updated := podWebhook.handlePodReinvocation(mutationRequest) - require.False(t, updated) - failingMutator.AssertCalled(t, "Enabled", mutationRequest.BaseRequest) - failingMutator.AssertCalled(t, "Reinvoke", mutationRequest.ToReinvocationRequest()) - failingMutator.AssertNotCalled(t, "Injected", mock.Anything) - failingMutator.AssertNotCalled(t, "Mutated", mock.Anything, mock.Anything) + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.NotEqual(t, admission.Patched(""), resp) }) -} -func assertContainersInfo(t *testing.T, request *dtwebhook.ReinvocationRequest, installContainer *corev1.Container) { - rawContainerInfo := env.FindEnvVar(installContainer.Env, consts.ContainerInfoEnv) - require.NotNil(t, rawContainerInfo) + t.Run("FF appmon-dk WITH CSI ==> v1 injector", func(t *testing.T) { + dk := getTestDynakubeDefaultAppMon() + dk.Annotations = map[string]string{ + dynakube.AnnotationFeatureRemoteImageDownload: "true", + } + + v1Injector := webhookmock.NewPodInjector(t) + v1Injector.On("Handle", mock.Anything, mock.Anything).Return(nil) + wh := createTestWebhook( + v1Injector, + webhookmock.NewPodInjector(t), + []client.Object{ + getTestNamespace(), + dk, + }, + ) + + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: true}) + + request := createTestAdmissionRequest(getTestPod()) + + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.NotEqual(t, admission.Patched(""), resp) + }) - var containerInfo []startup.ContainerInfo - err := json.Unmarshal([]byte(rawContainerInfo.Value), &containerInfo) - require.NoError(t, err) + t.Run("v1 injector error => silent error", func(t *testing.T) { + v1Injector := webhookmock.NewPodInjector(t) + v1Injector.On("Handle", mock.Anything, mock.Anything).Return(errors.New("BOOM")) + wh := createTestWebhook( + v1Injector, + webhookmock.NewPodInjector(t), + []client.Object{ + getTestNamespace(), + getTestDynakubeDefaultAppMon(), + }, + ) - for _, container := range request.Pod.Spec.Containers { - found := false + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) - for _, info := range containerInfo { - if container.Name == info.Name { - assert.Equal(t, container.Image, info.Image) + request := createTestAdmissionRequest(getTestPod()) - found = true + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.True(t, resp.Allowed) + assert.NotEmpty(t, resp.Result.Message) + assert.Contains(t, resp.Result.Message, "BOOM") + }) - break - } + t.Run("v2 injector error => silent error", func(t *testing.T) { + dk := getTestDynakubeDefaultAppMon() + dk.Annotations = map[string]string{ + dynakube.AnnotationFeatureRemoteImageDownload: "true", } - require.True(t, found) - } -} + v2Injector := webhookmock.NewPodInjector(t) + v2Injector.On("Handle", mock.Anything, mock.Anything).Return(errors.New("BOOM")) + wh := createTestWebhook( + webhookmock.NewPodInjector(t), + v2Injector, + []client.Object{ + getTestNamespace(), + dk, + }, + ) -func assertPodMutatorCalls(t *testing.T, mutator dtwebhook.PodMutator, expectedCalls int) { - mock, ok := mutator.(*webhookmock.PodMutator) - if !ok { - t.Fatalf("assertPodMutatorCalls: webhook is not a mock") - } + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) - mock.AssertNumberOfCalls(t, "Enabled", expectedCalls) - mock.AssertNumberOfCalls(t, "Mutate", expectedCalls) + request := createTestAdmissionRequest(getTestPod()) + + resp := wh.Handle(ctx, *request) + require.NotNil(t, resp) + assert.True(t, resp.Allowed) + assert.NotEmpty(t, resp.Result.Message) + assert.Contains(t, resp.Result.Message, "BOOM") + }) } func getTestPodWithInjectionDisabled() *corev1.Pod { @@ -374,75 +328,56 @@ func getTestPodWithOcDebugPodAnnotations() *corev1.Pod { return pod } -func createTestWebhook(mutators []dtwebhook.PodMutator, objects []client.Object) *webhook { +func getTestPodWithInjectionDisabledOnContainer() *corev1.Pod { + pod := getTestPod() + pod.Annotations = map[string]string{} + + for _, c := range pod.Spec.Containers { + pod.Annotations[dtwebhook.AnnotationContainerInjection+"/"+c.Name] = "false" + } + + return pod +} + +func createTestWebhook(v1, v2 dtwebhook.PodInjector, objects []client.Object) *webhook { decoder := admission.NewDecoder(scheme.Scheme) return &webhook{ + v1: v1, + v2: v2, apiReader: fake.NewClient(objects...), decoder: decoder, - recorder: eventRecorder{recorder: record.NewFakeRecorder(10), pod: &corev1.Pod{}, dk: getTestDynakube()}, - webhookImage: testImage, webhookNamespace: testNamespaceName, - clusterID: testClusterID, - apmExists: false, - mutators: mutators, + recorder: events.NewRecorder(record.NewFakeRecorder(10)), } } -func createSimplePodMutatorMock(t *testing.T) *webhookmock.PodMutator { - mutator := webhookmock.NewPodMutator(t) - mutator.On("Enabled", mock.Anything).Return(true).Maybe() - mutator.On("Injected", mock.Anything).Return(false).Maybe() - mutator.On("Mutate", mock.Anything, mock.Anything).Return(nil).Maybe() - mutator.On("Reinvoke", mock.Anything).Return(true).Maybe() - - return mutator -} - -func createAlreadyInjectedPodMutatorMock(t *testing.T) *webhookmock.PodMutator { - mutator := webhookmock.NewPodMutator(t) - mutator.On("Enabled", mock.Anything).Return(true).Maybe() - mutator.On("Injected", mock.Anything).Return(true).Maybe() - mutator.On("Mutate", mock.Anything, mock.Anything).Return(nil).Maybe() - mutator.On("Reinvoke", mock.Anything).Return(true).Maybe() - - return mutator -} - -func createFailPodMutatorMock(t *testing.T) *webhookmock.PodMutator { - mutator := webhookmock.NewPodMutator(t) - mutator.On("Enabled", mock.Anything).Return(true).Maybe() - mutator.On("Injected", mock.Anything).Return(false).Maybe() - mutator.On("Mutate", mock.Anything, mock.Anything).Return(errors.New("BOOM")).Maybe() - mutator.On("Reinvoke", mock.Anything).Return(false).Maybe() - - return mutator -} - func getTestDynakube() *dynakube.DynaKube { return &dynakube.DynaKube{ ObjectMeta: getTestDynakubeMeta(), Spec: dynakube.DynaKubeSpec{ - OneAgent: getCloudNativeSpec(&testResourceRequirements), + OneAgent: getCloudNativeSpec(), }, } } -func getTestDynakubeNoInitLimits() *dynakube.DynaKube { +func getTestDynakubeDefaultAppMon() *dynakube.DynaKube { return &dynakube.DynaKube{ ObjectMeta: getTestDynakubeMeta(), Spec: dynakube.DynaKubeSpec{ - OneAgent: getCloudNativeSpec(nil), + OneAgent: oneagent.Spec{ + ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, + }, }, } } -func getTestDynakubeDefaultAppMon() *dynakube.DynaKube { +func getTestMetadataDynakube() *dynakube.DynaKube { return &dynakube.DynaKube{ ObjectMeta: getTestDynakubeMeta(), Spec: dynakube.DynaKubeSpec{ - OneAgent: oneagent.Spec{ - ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, + MetadataEnrichment: dynakube.MetadataEnrichment{ + Enabled: ptr.To(true), }, }, } @@ -455,12 +390,10 @@ func getTestDynakubeMeta() metav1.ObjectMeta { } } -func getCloudNativeSpec(initResources *corev1.ResourceRequirements) oneagent.Spec { +func getCloudNativeSpec() oneagent.Spec { return oneagent.Spec{ CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ - AppInjectionSpec: oneagent.AppInjectionSpec{ - InitResources: initResources, - }, + AppInjectionSpec: oneagent.AppInjectionSpec{}, }, } } diff --git a/pkg/webhook/mutator.go b/pkg/webhook/request.go similarity index 73% rename from pkg/webhook/mutator.go rename to pkg/webhook/request.go index abf8b3a3f1..44cc68ff15 100644 --- a/pkg/webhook/mutator.go +++ b/pkg/webhook/request.go @@ -8,21 +8,42 @@ import ( corev1 "k8s.io/api/core/v1" ) -type PodMutator interface { - // Enabled returns true if the mutator needs to be executed for the given request. - // This is used to filter out mutators that are not needed for the given request. - Enabled(request *BaseRequest) bool +func NewMutationRequest(ctx context.Context, namespace corev1.Namespace, installContainer *corev1.Container, pod *corev1.Pod, dk dynakube.DynaKube) *MutationRequest { + return &MutationRequest{ + BaseRequest: newBaseRequest(pod, namespace, dk), + Context: ctx, + InstallContainer: installContainer, + } +} + +// MutationRequest contains all the information needed to mutate a pod +// It is meant to be passed into each mutator, so that they can mutate the elements in the way they need to, +// and after passing it in to all the mutator the request will have the final state which can be used to mutate the pod. +type MutationRequest struct { + *BaseRequest + Context context.Context + InstallContainer *corev1.Container +} - // Injected returns true if the mutator has already injected into the pod of the given request. - // This is used during reinvocation to prevent multiple injections. - Injected(request *BaseRequest) bool +func (request *MutationRequest) ToReinvocationRequest() *ReinvocationRequest { + return &ReinvocationRequest{ + BaseRequest: request.BaseRequest, + } +} - // Mutate mutates the elements of the given MutationRequest, specifically the pod and installContainer. - Mutate(ctx context.Context, request *MutationRequest) error +// ReinvocationRequest contains all the information needed to reinvoke a pod +// It is meant to be passed into each mutator, so that they can mutate the elements in the way they need to, +// and after passing it in to all the mutator the request will have the final state which can be used to mutate the pod. +type ReinvocationRequest struct { + *BaseRequest +} - // Reinvocation mutates the pod of the given ReinvocationRequest. - // It only mutates the parts of the pod that haven't been mutated yet. (example: another webhook mutated the pod after our webhook was executed) - Reinvoke(request *ReinvocationRequest) bool +func newBaseRequest(pod *corev1.Pod, namespace corev1.Namespace, dk dynakube.DynaKube) *BaseRequest { + return &BaseRequest{ + Pod: pod, + DynaKube: dk, + Namespace: namespace, + } } // BaseRequest is the base request for all mutation requests @@ -58,41 +79,3 @@ func (req *BaseRequest) NewContainers(isInjected func(corev1.Container) bool) (n return } - -// MutationRequest contains all the information needed to mutate a pod -// It is meant to be passed into each mutator, so that they can mutate the elements in the way they need to, -// and after passing it in to all the mutator the request will have the final state which can be used to mutate the pod. -type MutationRequest struct { - *BaseRequest - Context context.Context - InstallContainer *corev1.Container -} - -// ReinvocationRequest contains all the information needed to reinvoke a pod -// It is meant to be passed into each mutator, so that they can mutate the elements in the way they need to, -// and after passing it in to all the mutator the request will have the final state which can be used to mutate the pod. -type ReinvocationRequest struct { - *BaseRequest -} - -func newBaseRequest(pod *corev1.Pod, namespace corev1.Namespace, dk dynakube.DynaKube) *BaseRequest { - return &BaseRequest{ - Pod: pod, - DynaKube: dk, - Namespace: namespace, - } -} - -func NewMutationRequest(ctx context.Context, namespace corev1.Namespace, installContainer *corev1.Container, pod *corev1.Pod, dk dynakube.DynaKube) *MutationRequest { - return &MutationRequest{ - BaseRequest: newBaseRequest(pod, namespace, dk), - Context: ctx, - InstallContainer: installContainer, - } -} - -func (request *MutationRequest) ToReinvocationRequest() *ReinvocationRequest { - return &ReinvocationRequest{ - BaseRequest: request.BaseRequest, - } -} diff --git a/test/features/applicationmonitoring/metadata_enrichment.go b/test/features/applicationmonitoring/metadata_enrichment.go index b07373a6db..6c6ba5d716 100644 --- a/test/features/applicationmonitoring/metadata_enrichment.go +++ b/test/features/applicationmonitoring/metadata_enrichment.go @@ -12,7 +12,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" maputil "github.com/Dynatrace/dynatrace-operator/pkg/util/map" - "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/deployment" @@ -71,8 +72,8 @@ func MetadataEnrichment(t *testing.T) features.Feature { sample.AsDeployment(), sample.WithNamespaceLabels(injectEverythingLabels), sample.WithAnnotations(map[string]string{ - webhook.AnnotationOneAgentInject: "false", - webhook.AnnotationMetadataEnrichmentInject: "true", + oacommon.AnnotationInject: "false", + metacommon.AnnotationInject: "true", })), assess: deploymentPodsHaveOnlyMetadataEnrichmentInitContainer, }, @@ -82,8 +83,8 @@ func MetadataEnrichment(t *testing.T) features.Feature { sample.WithName("pod-metadata-annotation"), sample.WithNamespaceLabels(injectEverythingLabels), sample.WithAnnotations(map[string]string{ - webhook.AnnotationOneAgentInject: "false", - webhook.AnnotationMetadataEnrichmentInject: "true", + oacommon.AnnotationInject: "false", + metacommon.AnnotationInject: "true", })), assess: podHasOnlyMetadataEnrichmentInitContainer, }, @@ -110,8 +111,8 @@ func MetadataEnrichment(t *testing.T) features.Feature { sample.WithName("pod-oa-annotation"), sample.WithNamespaceLabels(injectEverythingLabels), sample.WithAnnotations(map[string]string{ - webhook.AnnotationOneAgentInject: "true", - webhook.AnnotationMetadataEnrichmentInject: "false", + oacommon.AnnotationInject: "true", + metacommon.AnnotationInject: "false", })), assess: podHasOnlyOneAgentInitContainer, }, @@ -201,8 +202,8 @@ func podHasCompleteInitContainer(samplePod *sample.App) features.Func { //nolint assert.True(t, env.IsIn(envVars, consts.AgentInjectedEnv)) - assert.Contains(t, testPod.Annotations, webhook.AnnotationWorkloadKind) - assert.Contains(t, testPod.Annotations, webhook.AnnotationWorkloadName) + assert.Contains(t, testPod.Annotations, metacommon.AnnotationWorkloadKind) + assert.Contains(t, testPod.Annotations, metacommon.AnnotationWorkloadName) return ctx } @@ -224,8 +225,8 @@ func podHasOnlyOneAgentInitContainer(samplePod *sample.App) features.Func { //no assert.True(t, env.IsIn(envVars, consts.AgentInjectedEnv)) - assert.NotContains(t, testPod.Annotations, webhook.AnnotationWorkloadKind) - assert.NotContains(t, testPod.Annotations, webhook.AnnotationWorkloadName) + assert.NotContains(t, testPod.Annotations, metacommon.AnnotationWorkloadKind) + assert.NotContains(t, testPod.Annotations, metacommon.AnnotationWorkloadName) return ctx } @@ -274,7 +275,7 @@ func assessOnlyMetadataEnrichmentIsInjected(t *testing.T) deployment.PodConsumer assert.False(t, env.IsIn(envVars, consts.AgentInjectedEnv)) - assert.Contains(t, pod.Annotations, webhook.AnnotationWorkloadKind) - assert.Contains(t, pod.Annotations, webhook.AnnotationWorkloadName) + assert.Contains(t, pod.Annotations, metacommon.AnnotationWorkloadKind) + assert.Contains(t, pod.Annotations, metacommon.AnnotationWorkloadName) } } diff --git a/test/features/applicationmonitoring/read_only_csi_volume.go b/test/features/applicationmonitoring/read_only_csi_volume.go index 6dc0f11161..491c712c34 100644 --- a/test/features/applicationmonitoring/read_only_csi_volume.go +++ b/test/features/applicationmonitoring/read_only_csi_volume.go @@ -9,7 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" - oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" + oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/codemodules" dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" diff --git a/test/features/cloudnative/codemodules/codemodules.go b/test/features/cloudnative/codemodules/codemodules.go index 1e2d4fdf21..9e92b24305 100644 --- a/test/features/cloudnative/codemodules/codemodules.go +++ b/test/features/cloudnative/codemodules/codemodules.go @@ -18,8 +18,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" - "github.com/Dynatrace/dynatrace-operator/pkg/webhook" - oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" + oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1/oneagent" "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/csi" @@ -521,13 +521,13 @@ func volumesAreMountedCorrectly(sampleApp sample.App) features.Func { assert.True(t, isVolumeAttached(t, volumes, oamutation.OneAgentBinVolumeName)) assert.True(t, isVolumeMounted(t, volumeMounts, oamutation.OneAgentBinVolumeName)) - listCommand := shell.ListDirectory(webhook.DefaultInstallPath) + listCommand := shell.ListDirectory(oacommon.DefaultInstallPath) executionResult, err := pod.Exec(ctx, resource, podItem, sampleApp.ContainerName(), listCommand...) require.NoError(t, err) assert.NotEmpty(t, executionResult.StdOut.String()) - diskUsage := getDiskUsage(ctx, t, envConfig.Client().Resources(), podItem, sampleApp.ContainerName(), webhook.DefaultInstallPath) + diskUsage := getDiskUsage(ctx, t, envConfig.Client().Resources(), podItem, sampleApp.ContainerName(), oacommon.DefaultInstallPath) assert.Positive(t, diskUsage) }) @@ -543,7 +543,7 @@ func isVolumeMounted(t *testing.T, volumeMounts []corev1.VolumeMount, volumeMoun if volumeMount.Name == volumeMountName { result = true - assert.Equal(t, webhook.DefaultInstallPath, volumeMount.MountPath) + assert.Equal(t, oacommon.DefaultInstallPath, volumeMount.MountPath) assert.False(t, volumeMount.ReadOnly) } } diff --git a/test/helpers/proxy/proxy.go b/test/helpers/proxy/proxy.go index 4428b80ce2..2b39ab7c21 100644 --- a/test/helpers/proxy/proxy.go +++ b/test/helpers/proxy/proxy.go @@ -13,7 +13,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/common" "github.com/Dynatrace/dynatrace-operator/pkg/webhook" - oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/oneagent" + oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/curl" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/deployment" diff --git a/test/mocks/pkg/webhook/pod_injector.go b/test/mocks/pkg/webhook/pod_injector.go new file mode 100644 index 0000000000..9f81946381 --- /dev/null +++ b/test/mocks/pkg/webhook/pod_injector.go @@ -0,0 +1,84 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + context "context" + + webhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + mock "github.com/stretchr/testify/mock" +) + +// PodInjector is an autogenerated mock type for the PodInjector type +type PodInjector struct { + mock.Mock +} + +type PodInjector_Expecter struct { + mock *mock.Mock +} + +func (_m *PodInjector) EXPECT() *PodInjector_Expecter { + return &PodInjector_Expecter{mock: &_m.Mock} +} + +// Handle provides a mock function with given fields: _a0, _a1 +func (_m *PodInjector) Handle(_a0 context.Context, _a1 *webhook.MutationRequest) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Handle") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *webhook.MutationRequest) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// PodInjector_Handle_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Handle' +type PodInjector_Handle_Call struct { + *mock.Call +} + +// Handle is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *webhook.MutationRequest +func (_e *PodInjector_Expecter) Handle(_a0 interface{}, _a1 interface{}) *PodInjector_Handle_Call { + return &PodInjector_Handle_Call{Call: _e.mock.On("Handle", _a0, _a1)} +} + +func (_c *PodInjector_Handle_Call) Run(run func(_a0 context.Context, _a1 *webhook.MutationRequest)) *PodInjector_Handle_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*webhook.MutationRequest)) + }) + return _c +} + +func (_c *PodInjector_Handle_Call) Return(_a0 error) *PodInjector_Handle_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *PodInjector_Handle_Call) RunAndReturn(run func(context.Context, *webhook.MutationRequest) error) *PodInjector_Handle_Call { + _c.Call.Return(run) + return _c +} + +// NewPodInjector creates a new instance of PodInjector. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewPodInjector(t interface { + mock.TestingT + Cleanup(func()) +}) *PodInjector { + mock := &PodInjector{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} From 5f02962552211f5c5bf69e6ca5690bab7823320d Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Thu, 13 Mar 2025 13:28:28 +0100 Subject: [PATCH 309/426] Put ActiveGate `customProperties` in KSPM sample under comment (#4589) --- .../v1beta4/kubernetesSecurityPostureManagement.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml index 929e8c20e3..4043d82b34 100644 --- a/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml +++ b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml @@ -16,11 +16,12 @@ spec: capabilities: - kubernetes-monitoring - customProperties: - value: | - [kubernetes_monitoring] - kubernetes_configuration_dataset_pipeline_enabled = true - kubernetes_configuration_dataset_pipeline_include_node_config = true + # The KSPM ActiveGate pipeline is enabled by default with ActiveGate >= 1.311. This custom properties are obsolete then. + # customProperties: + # value: | + # [kubernetes_monitoring] + # kubernetes_configuration_dataset_pipeline_enabled = true + # kubernetes_configuration_dataset_pipeline_include_node_config = true templates: {} # Required in combination with kspm enabled. From fe87a11889a9e0edccc4d12aeb134f82b56859be Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Thu, 13 Mar 2025 13:34:03 +0100 Subject: [PATCH 310/426] Adopt ActiveGate PVC handling. (#4585) --- .../internal/statefulset/statefulset.go | 56 +++-- .../internal/statefulset/statefulset_test.go | 216 ++++++++++-------- 2 files changed, 152 insertions(+), 120 deletions(-) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index de7115c67b..62a2144815 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -145,13 +145,16 @@ func (statefulSetBuilder Builder) buildTopologySpreadConstraints(capability capa func (statefulSetBuilder Builder) buildVolumes() []corev1.Volume { volumes := []corev1.Volume{} - if !(statefulSetBuilder.dynakube.IsOTLPingestEnabled() || statefulSetBuilder.dynakube.TelemetryIngest().IsEnabled()) || statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume { - volumes = append(volumes, corev1.Volume{ - Name: consts.GatewayTmpVolumeName, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }) + + if statefulSetBuilder.dynakube.Spec.ActiveGate.PersistentVolumeClaim == nil { + if !isDefaultPVCNeeded(statefulSetBuilder.dynakube) { + volumes = append(volumes, corev1.Volume{ + Name: consts.GatewayTmpVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }) + } } return volumes @@ -273,28 +276,31 @@ func (statefulSetBuilder Builder) nodeAffinity() *corev1.Affinity { return &affinity } +func isDefaultPVCNeeded(dk dynakube.DynaKube) bool { + return (dk.TelemetryIngest().IsEnabled() || dk.IsOTLPingestEnabled()) && !dk.Spec.ActiveGate.UseEphemeralVolume +} + func (statefulSetBuilder Builder) addPersistentVolumeClaim(sts *appsv1.StatefulSet) { - if (statefulSetBuilder.dynakube.IsOTLPingestEnabled() || statefulSetBuilder.dynakube.TelemetryIngest().IsEnabled()) && !statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume { - if statefulSetBuilder.dynakube.Spec.ActiveGate.PersistentVolumeClaim == nil { - sts.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: consts.GatewayTmpVolumeName, - }, - Spec: defaultPVCSpec(), + if statefulSetBuilder.dynakube.Spec.ActiveGate.PersistentVolumeClaim != nil { + // validation webhook ensures that statefulSetBuilder.dynakube.Spec.ActiveGate.UseEphemeralVolume is false at this point + sts.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: consts.GatewayTmpVolumeName, }, - } - } else { - sts.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: consts.GatewayTmpVolumeName, - }, - Spec: *statefulSetBuilder.dynakube.Spec.ActiveGate.PersistentVolumeClaim, + Spec: *statefulSetBuilder.dynakube.Spec.ActiveGate.PersistentVolumeClaim, + }, + } + sts.Spec.PersistentVolumeClaimRetentionPolicy = defaultPVCRetentionPolicy() + } else if isDefaultPVCNeeded(statefulSetBuilder.dynakube) { + sts.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: consts.GatewayTmpVolumeName, }, - } + Spec: defaultPVCSpec(), + }, } - sts.Spec.PersistentVolumeClaimRetentionPolicy = defaultPVCRetentionPolicy() } } diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index 24c0743da7..db5332f136 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -490,51 +490,132 @@ func TestSecurityContexts(t *testing.T) { }) } -func TestVolumes(t *testing.T) { - t.Run("empty dir volume exists when PersistentVolumeClaim = nil and UseEphemeralVolume = true", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.EnableOTLPingest = true - dk.Spec.ActiveGate.PersistentVolumeClaim = nil - dk.Spec.ActiveGate.UseEphemeralVolume = true - multiCapability := capability.NewMultiCapability(&dk) - statefulsetBuilder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) - sts, _ := statefulsetBuilder.CreateStatefulSet([]builder.Modifier{ - modifiers.NewKubernetesMonitoringModifier(dk, multiCapability), - modifiers.NewReadOnlyModifier(dk), - }) +func TestTempVolume(t *testing.T) { + myPVCspec := corev1.PersistentVolumeClaimSpec{ + StorageClassName: ptr.To("test"), + VolumeName: "foo-pv", + } - require.NotEmpty(t, sts) + tests := []struct { + name string + telemetryIngest *telemetryingest.Spec + pvc *corev1.PersistentVolumeClaimSpec + useEphemeral bool + emptyDirExpected bool + pvcExpected bool + expectedPvcSpec corev1.PersistentVolumeClaimSpec + }{ + { + name: "EmptyDir and no PVC when PersistentVolumeClaim = nil, TelemetryIngest enabled, UseEphemeralVolume = true", + pvc: nil, + telemetryIngest: &telemetryingest.Spec{}, + useEphemeral: true, + emptyDirExpected: true, + pvcExpected: false, + }, + { + name: "default PVC and no EmptyDir when PersistentVolumeClaim = nil, TelemetryIngest enabled, UseEphemeralVolume = false", + pvc: nil, + telemetryIngest: &telemetryingest.Spec{}, + useEphemeral: false, + emptyDirExpected: false, + pvcExpected: true, + expectedPvcSpec: defaultPVCSpec(), + }, + { + name: "EmptyDir and no PVC when PersistentVolumeClaim = nil, TelemetryIngest not enabled, UseEphemeralVolume = true", + pvc: nil, + telemetryIngest: nil, + useEphemeral: true, + emptyDirExpected: true, + pvcExpected: false, + }, + { + name: "EmptyDir and no PVC when PersistentVolumeClaim = nil, TelemetryIngest not enabled, UseEphemeralVolume = false", + pvc: nil, + telemetryIngest: nil, + useEphemeral: false, + emptyDirExpected: true, + pvcExpected: false, + }, + { + name: "custom PVC and no EmptyDir when PersistentVolumeClaim != nil, TelemetryIngest enabled, UseEphemeralVolume = false", + pvc: &myPVCspec, + telemetryIngest: &telemetryingest.Spec{}, + useEphemeral: false, + emptyDirExpected: false, + pvcExpected: true, + expectedPvcSpec: myPVCspec, + }, + { + name: "custom PVC and no EmptyDir when PersistentVolumeClaim != nil, TelemetryIngest enabled, UseEphemeralVolume = true", + pvc: &myPVCspec, + telemetryIngest: &telemetryingest.Spec{}, + useEphemeral: true, + emptyDirExpected: false, + pvcExpected: true, + expectedPvcSpec: myPVCspec, + }, + { + name: "custom PVC and no EmptyDir when PersistentVolumeClaim != nil, TelemetryIngest not enabled, UseEphemeralVolume = false", + pvc: &myPVCspec, + telemetryIngest: nil, + useEphemeral: false, + emptyDirExpected: false, + pvcExpected: true, + expectedPvcSpec: myPVCspec, + }, + { + name: "custom PVC and no EmptyDir when PersistentVolumeClaim != nil, TelemetryIngest not enabled, UseEphemeralVolume = true", + pvc: &myPVCspec, + telemetryIngest: nil, + useEphemeral: true, + emptyDirExpected: false, + pvcExpected: true, + expectedPvcSpec: myPVCspec, + }, + } - expectedVolume := corev1.Volume{ - Name: consts.GatewayTmpVolumeName, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - } - require.Contains(t, sts.Spec.Template.Spec.Volumes, expectedVolume) - }) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + dk := getTestDynakube() - t.Run("empty dir volume doesn't exists when UseEphemeralVolume = false", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.EnableOTLPingest = true - dk.Spec.ActiveGate.UseEphemeralVolume = false - multiCapability := capability.NewMultiCapability(&dk) - statefulsetBuilder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) - sts, _ := statefulsetBuilder.CreateStatefulSet([]builder.Modifier{ - modifiers.NewKubernetesMonitoringModifier(dk, multiCapability), - modifiers.NewReadOnlyModifier(dk), - }) + dk.Spec.ActiveGate.PersistentVolumeClaim = test.pvc + dk.Spec.TelemetryIngest = test.telemetryIngest + dk.Spec.ActiveGate.UseEphemeralVolume = test.useEphemeral - require.NotEmpty(t, sts) + multiCapability := capability.NewMultiCapability(&dk) + statefulsetBuilder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) + sts, _ := statefulsetBuilder.CreateStatefulSet([]builder.Modifier{ + modifiers.NewKubernetesMonitoringModifier(dk, multiCapability), + modifiers.NewReadOnlyModifier(dk), + }) - expectedVolume := corev1.Volume{ - Name: consts.GatewayTmpVolumeName, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - } - require.NotContains(t, sts.Spec.Template.Spec.Volumes, expectedVolume) - }) + require.NotEmpty(t, sts) + + expectedEmptyDirVolume := corev1.Volume{ + Name: consts.GatewayTmpVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + } + + if test.emptyDirExpected { + require.Contains(t, sts.Spec.Template.Spec.Volumes, expectedEmptyDirVolume) + } else { + require.NotContains(t, sts.Spec.Template.Spec.Volumes, expectedEmptyDirVolume) + } + + if test.pvcExpected { + require.Len(t, sts.Spec.VolumeClaimTemplates, 1) + require.Equal(t, test.expectedPvcSpec, sts.Spec.VolumeClaimTemplates[0].Spec) + require.Equal(t, consts.GatewayTmpVolumeName, sts.Spec.VolumeClaimTemplates[0].Name) + require.Equal(t, defaultPVCRetentionPolicy(), sts.Spec.PersistentVolumeClaimRetentionPolicy) + } else { + require.Empty(t, sts.Spec.VolumeClaimTemplates) + } + }) + } } func TestVolumeMounts(t *testing.T) { @@ -556,58 +637,3 @@ func TestVolumeMounts(t *testing.T) { require.Contains(t, sts.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) }) } - -func TestPVC(t *testing.T) { - test := func(dk dynakube.DynaKube, multiCapability capability.Capability, pvcSpec corev1.PersistentVolumeClaimSpec) { - statefulsetBuilder := NewStatefulSetBuilder(testKubeUID, testConfigHash, dk, multiCapability) - sts, _ := statefulsetBuilder.CreateStatefulSet([]builder.Modifier{ - modifiers.NewKubernetesMonitoringModifier(dk, multiCapability), - modifiers.NewReadOnlyModifier(dk), - }) - - require.NotEmpty(t, sts) - - require.Equal(t, pvcSpec, sts.Spec.VolumeClaimTemplates[0].Spec) - require.Equal(t, consts.GatewayTmpVolumeName, sts.Spec.VolumeClaimTemplates[0].Name) - require.Equal(t, defaultPVCRetentionPolicy(), sts.Spec.PersistentVolumeClaimRetentionPolicy) - } - - t.Run("use custom PVC with OTLPingest", func(t *testing.T) { - dk := getTestDynakube() - multiCapability := capability.NewMultiCapability(&dk) - myPVCspec := corev1.PersistentVolumeClaimSpec{ - StorageClassName: ptr.To("test"), - VolumeName: "foo-pv", - } - dk.Spec.EnableOTLPingest = true - dk.Spec.ActiveGate.PersistentVolumeClaim = &myPVCspec - - test(dk, multiCapability, myPVCspec) - }) - t.Run("use custom PVC with TelemetryIngest", func(t *testing.T) { - dk := getTestDynakube() - multiCapability := capability.NewMultiCapability(&dk) - myPVCspec := corev1.PersistentVolumeClaimSpec{ - StorageClassName: ptr.To("test"), - VolumeName: "foo-pv", - } - dk.Spec.TelemetryIngest = &telemetryingest.Spec{} - dk.Spec.ActiveGate.PersistentVolumeClaim = &myPVCspec - - test(dk, multiCapability, myPVCspec) - }) - t.Run("use default PVC with OTLPingest", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.EnableOTLPingest = true - multiCapability := capability.NewMultiCapability(&dk) - - test(dk, multiCapability, defaultPVCSpec()) - }) - t.Run("use default PVC with TelemetryIngest", func(t *testing.T) { - dk := getTestDynakube() - dk.Spec.TelemetryIngest = &telemetryingest.Spec{} - multiCapability := capability.NewMultiCapability(&dk) - - test(dk, multiCapability, defaultPVCSpec()) - }) -} From b47b559cfe0d1b147c4e0752abf493a0c90dabff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 13 Mar 2025 12:44:05 +0000 Subject: [PATCH 311/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1741861735 (main) (#4590) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a25160923e..b4c77659fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1741626669@sha256:91828a5ca154132e18072cf885f6bb41bb881e6158f30b793f4b424ec144b87d AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1741861735@sha256:8a6071b01366611fd9433bf9688f5c3150de819874fa2c06c4fcd4c25ea26f03 AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1741850090@sha256:8d53b60617e53e4dbd6c0d485c569801f48dbeb40b48c8424a67e33a07320968 AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From c95b7f7b15c537e85006659361456eac0ce5485c Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Thu, 13 Mar 2025 16:11:55 +0100 Subject: [PATCH 312/426] Add validation to deny init bootstrapper without code modules image set (#4593) --- pkg/api/validation/dynakube/oneagent.go | 10 ++++++++++ pkg/api/validation/dynakube/validation.go | 1 + 2 files changed, 11 insertions(+) diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index 0302918a5d..aacdc48ac1 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -19,6 +19,8 @@ const ( errorImageFieldSetWithoutCSIFlag = `The DynaKube specification attempts to enable ApplicationMonitoring mode and retrieve the respective image, but the CSI driver and/or remote image download is not enabled.` + errorBootstrapperRemoteImageDownloadRequiresCodeModulesImage = `The DynaKube specification enables remote image download, but the code modules image is not set.` + errorNodeSelectorConflict = `The Dynakube specification conflicts with another Dynakube's OneAgent or Standalone-LogMonitoring. Only one Agent per node is supported. Use a nodeSelector to avoid this conflict. Conflicting DynaKubes: %s` @@ -153,6 +155,14 @@ func imageFieldSetWithoutCSIFlag(_ context.Context, v *Validator, dk *dynakube.D return "" } +func missingCodeModulesImage(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { + if dk.FeatureBootstrapperInjection() && len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) == 0 { + return errorBootstrapperRemoteImageDownloadRequiresCodeModulesImage + } + + return "" +} + func hasConflictingMatchLabels(labelMap, otherLabelMap map[string]string) bool { if labelMap == nil || otherLabelMap == nil { return true diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 1c926be932..2d9c716e1f 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -46,6 +46,7 @@ var ( conflictingNamespaceSelector, noResourcesAvailable, imageFieldSetWithoutCSIFlag, + missingCodeModulesImage, conflictingOneAgentVolumeStorageSettings, nameViolatesDNS1035, nameTooLong, From 5de24e39125716c6dde628a3f0606ccddec40e68 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Mar 2025 11:18:47 +0000 Subject: [PATCH 313/426] chore(deps): update aquasecurity/trivy-action action to v0.30.0 (main) (#4596) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3e4d4247a7..cfebe435f0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -240,7 +240,7 @@ jobs: registry-type: public - name: Create sbom for ${{matrix.registry}} id: sbom - uses: aquasecurity/trivy-action@18f2510ee396bbf400402947b394f2dd8c87dbb0 # 0.29.0 + uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0 with: image-ref: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ needs.manifest.outputs.digest }} format: 'cyclonedx' From c01767bf2cb7b1ec24c3c2255bb096d42ad42bd6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Mar 2025 13:23:52 +0000 Subject: [PATCH 314/426] chore(deps): update docker/login-action action to v3.4.0 (main) (#4598) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 4 ++-- .github/workflows/release.yaml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ec9fd6b722..ad659efd01 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -217,7 +217,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} @@ -243,7 +243,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index cfebe435f0..10d3273ed4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -94,7 +94,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry if: ${{ matrix.registry != 'amazon-ecr' }} - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ${{ matrix.url }} username: ${{ secrets[matrix.username] }} @@ -162,7 +162,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry if: ${{ matrix.registry != 'amazon-ecr' }} - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ${{ matrix.url }} username: ${{ secrets[matrix.username] }} @@ -222,7 +222,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry if: ${{ matrix.registry != 'amazon-ecr' }} - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ${{ matrix.url }} username: ${{ secrets[matrix.username] }} @@ -266,7 +266,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ${{ env.SCAN_REGISTRY }} username: ${{ secrets.RHCC_USERNAME }} @@ -329,7 +329,7 @@ jobs: run: | helm registry login -u "${{ secrets.DOCKERHUB_USERNAME }}" -p "${{ secrets.DOCKERHUB_PASSWORD }}" "registry.hub.docker.com" - name: Login Docker to dockerhub - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: docker.io username: ${{ secrets.DOCKERHUB_USERNAME }} From 857c102a8b5f01c07e0df4ba9a3582ce5b08a007 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:39:36 +0100 Subject: [PATCH 315/426] Configure attributes for bootstrapper injection (#4595) --- .../mutation/pod/v1/metadata/config.go | 2 +- .../mutation/pod/v1/oneagent/config.go | 2 +- pkg/webhook/mutation/pod/v1/oneagent/env.go | 2 +- pkg/webhook/mutation/pod/v2/attributes.go | 118 +++++ .../mutation/pod/v2/attributes_test.go | 440 ++++++++++++++++++ pkg/webhook/mutation/pod/v2/common/arg/arg.go | 4 + .../mutation/pod/v2/common/volumes/volumes.go | 2 +- pkg/webhook/mutation/pod/v2/init.go | 24 +- pkg/webhook/mutation/pod/v2/init_test.go | 18 +- .../mutation/pod/v2/metadata/config.go | 2 +- .../mutation/pod/v2/metadata/containers.go | 43 +- pkg/webhook/mutation/pod/v2/webhook.go | 32 +- pkg/webhook/mutation/pod/v2/webhook_test.go | 100 +++- 13 files changed, 750 insertions(+), 39 deletions(-) create mode 100644 pkg/webhook/mutation/pod/v2/attributes.go create mode 100644 pkg/webhook/mutation/pod/v2/attributes_test.go diff --git a/pkg/webhook/mutation/pod/v1/metadata/config.go b/pkg/webhook/mutation/pod/v1/metadata/config.go index 15d2801878..9de4fa7891 100644 --- a/pkg/webhook/mutation/pod/v1/metadata/config.go +++ b/pkg/webhook/mutation/pod/v1/metadata/config.go @@ -11,5 +11,5 @@ const ( ) var ( - log = logd.Get().WithName("metadata-enrichment-pod-v1-mutation") + log = logd.Get().WithName("v1-pod-mutation-metadata-enrichment") ) diff --git a/pkg/webhook/mutation/pod/v1/oneagent/config.go b/pkg/webhook/mutation/pod/v1/oneagent/config.go index d82d22a0a0..8a54e4a2a6 100644 --- a/pkg/webhook/mutation/pod/v1/oneagent/config.go +++ b/pkg/webhook/mutation/pod/v1/oneagent/config.go @@ -5,7 +5,7 @@ import ( ) var ( - log = logd.Get().WithName("oneagent-pod-v1-mutation") + log = logd.Get().WithName("v1-pod-mutation-oneagent") ) const ( diff --git a/pkg/webhook/mutation/pod/v1/oneagent/env.go b/pkg/webhook/mutation/pod/v1/oneagent/env.go index 9109bdc616..f742af3ca8 100644 --- a/pkg/webhook/mutation/pod/v1/oneagent/env.go +++ b/pkg/webhook/mutation/pod/v1/oneagent/env.go @@ -7,7 +7,7 @@ import ( func addInstallerInitEnvs(initContainer *corev1.Container, installer installerInfo) { initContainer.Env = append(initContainer.Env, - corev1.EnvVar{Name: consts.AgentInstallerFlavorEnv, Value: installer.flavor}, // TODO: is this needed + corev1.EnvVar{Name: consts.AgentInstallerFlavorEnv, Value: installer.flavor}, corev1.EnvVar{Name: consts.AgentInstallerTechEnv, Value: installer.technologies}, corev1.EnvVar{Name: consts.AgentInstallPathEnv, Value: installer.installPath}, corev1.EnvVar{Name: consts.AgentInstallerUrlEnv, Value: installer.installerURL}, diff --git a/pkg/webhook/mutation/pod/v2/attributes.go b/pkg/webhook/mutation/pod/v2/attributes.go new file mode 100644 index 0000000000..81b58ae3dd --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/attributes.go @@ -0,0 +1,118 @@ +package v2 + +import ( + "fmt" + "strings" + + containerattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/container" + podattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/pod" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/mounts" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/volumes" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/metadata" + corev1 "k8s.io/api/core/v1" +) + +func (wh *Injector) addPodAttributes(request *dtwebhook.MutationRequest) error { + attrs := podattr.Attributes{ + PodInfo: podattr.PodInfo{ + PodName: createEnvVarRef(consts.K8sPodNameEnv), + PodUid: createEnvVarRef(consts.K8sPodUIDEnv), + NamespaceName: request.Pod.Namespace, + }, + ClusterInfo: podattr.ClusterInfo{ + ClusterUId: request.DynaKube.Status.KubeSystemUUID, + DTClusterEntity: request.DynaKube.Status.KubernetesClusterMEID, + }, + UserDefined: map[string]string{ + "k8s.cluster.name": request.DynaKube.Status.KubernetesClusterName, // TODO: make it part of podattr.Attributes + "k8s.node.name": createEnvVarRef(consts.K8sNodeNameEnv), // TODO: make it part of podattr.Attributes + }, + } + + envs := []corev1.EnvVar{ + {Name: consts.K8sPodNameEnv, ValueFrom: env.NewEnvVarSourceForField("metadata.name")}, + {Name: consts.K8sPodUIDEnv, ValueFrom: env.NewEnvVarSourceForField("metadata.uid")}, + {Name: consts.K8sNodeNameEnv, ValueFrom: env.NewEnvVarSourceForField("spec.nodeName")}, + } + + request.InstallContainer.Env = append(request.InstallContainer.Env, envs...) + + err := metadata.Mutate(wh.metaClient, request, &attrs) + if err != nil { + return err + } + + args, err := podattr.ToArgs(attrs) + if err != nil { + return err + } + + request.InstallContainer.Args = append(request.InstallContainer.Args, args...) + + return nil +} + +func createEnvVarRef(envName string) string { + return fmt.Sprintf("$(%s)", envName) +} + +func addContainerAttributes(request *dtwebhook.MutationRequest) error { + attributes := []containerattr.Attributes{} + for _, c := range request.NewContainers(isInjected) { + attributes = append(attributes, containerattr.Attributes{ + ImageInfo: createImageInfo(c.Image), + ContainerName: c.Name, + }) + } + + if len(attributes) > 0 { + args, err := containerattr.ToArgs(attributes) + if err != nil { + return err + } + + request.InstallContainer.Args = append(request.InstallContainer.Args, args...) + } + + return nil +} + +func isInjected(container corev1.Container) bool { + return mounts.IsIn(container.VolumeMounts, volumes.ConfigVolumeName) +} + +func createImageInfo(imageURI string) containerattr.ImageInfo { // TODO: move to bootstrapper repo + // can't use the name.ParseReference() as that will fill in some defaults if certain things are defined, but we want to preserve the original string value, without any modification. Tried it with a regexp, was worse. + imageInfo := containerattr.ImageInfo{} + + repoPart := "" + + registrySplit := strings.SplitN(imageURI, "/", 2) + if len(registrySplit) == 1 { + repoPart = registrySplit[0] + } else if len(registrySplit) == 2 { + imageInfo.Registry = registrySplit[0] + repoPart = registrySplit[1] + } + + digestSplit := strings.SplitN(repoPart, "@", 2) + if len(digestSplit) == 1 { + repoPart = digestSplit[0] + } else if len(digestSplit) == 2 { + imageInfo.ImageDigest = digestSplit[1] + repoPart = digestSplit[0] + } + + tagSplit := strings.SplitN(repoPart, ":", 2) + if len(tagSplit) == 1 { + imageInfo.Repository = tagSplit[0] + } else if len(tagSplit) == 2 { + imageInfo.Tag = tagSplit[1] + imageInfo.Repository = tagSplit[0] + } + + return imageInfo +} diff --git a/pkg/webhook/mutation/pod/v2/attributes_test.go b/pkg/webhook/mutation/pod/v2/attributes_test.go new file mode 100644 index 0000000000..753e36464d --- /dev/null +++ b/pkg/webhook/mutation/pod/v2/attributes_test.go @@ -0,0 +1,440 @@ +package v2 + +import ( + "encoding/json" + "strings" + "testing" + + containerattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/container" + podattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/pod" + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/volumes" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" +) + +func TestAddPodAttributes(t *testing.T) { + validateAttributes := func(t *testing.T, request dtwebhook.MutationRequest) podattr.Attributes { + t.Helper() + + require.NotEmpty(t, request.InstallContainer.Args) + + rawArgs := []string{} + + for _, arg := range request.InstallContainer.Args { + splitArg := strings.SplitN(arg, "=", 2) + require.Len(t, splitArg, 2) + rawArgs = append(rawArgs, splitArg[1]) + } + + attr, err := podattr.ParseAttributes(rawArgs) + require.NoError(t, err) + + assert.Equal(t, request.DynaKube.Status.KubernetesClusterMEID, attr.DTClusterEntity) + assert.Equal(t, request.DynaKube.Status.KubeSystemUUID, attr.ClusterUId) + assert.Contains(t, attr.PodName, consts.K8sPodNameEnv) + assert.Contains(t, attr.PodUid, consts.K8sPodUIDEnv) + assert.Equal(t, request.Pod.Namespace, attr.NamespaceName) + + require.Len(t, request.InstallContainer.Env, 3) + assert.NotNil(t, env.FindEnvVar(request.InstallContainer.Env, consts.K8sPodNameEnv)) + assert.NotNil(t, env.FindEnvVar(request.InstallContainer.Env, consts.K8sPodUIDEnv)) + assert.NotNil(t, env.FindEnvVar(request.InstallContainer.Env, consts.K8sNodeNameEnv)) + + return attr + } + + validateAdditionAttributes := func(t *testing.T, request dtwebhook.MutationRequest) { + t.Helper() + + attr := validateAttributes(t, request) + + require.NotEmpty(t, request.Pod.OwnerReferences) + assert.Equal(t, strings.ToLower(request.Pod.OwnerReferences[0].Kind), attr.WorkloadKind) + assert.Equal(t, request.Pod.OwnerReferences[0].Name, attr.WorkloadName) + + metaAnnotationCount := 0 + + for key := range request.Namespace.Annotations { + if strings.Contains(key, metacommon.AnnotationPrefix) { + metaAnnotationCount++ + } + } + + assert.Len(t, attr.UserDefined, metaAnnotationCount+2) // TODO: this +2 should be removed once k8s.node.name and k8s.cluster.name are part of the actual Attributes + require.Len(t, request.Pod.Annotations, 3+metaAnnotationCount) + assert.Equal(t, strings.ToLower(request.Pod.OwnerReferences[0].Kind), request.Pod.Annotations[metacommon.AnnotationWorkloadKind]) + assert.Equal(t, request.Pod.OwnerReferences[0].Name, request.Pod.Annotations[metacommon.AnnotationWorkloadName]) + assert.Equal(t, "true", request.Pod.Annotations[metacommon.AnnotationInjected]) + } + + t.Run("add attributes and related envs, do not change pod or app-container", func(t *testing.T) { + injector := createTestInjectorBase() + + initContainer := corev1.Container{ + Args: []string{}, + } + pod := corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + }, + } + + expectedPod := pod.DeepCopy() + + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + Pod: &pod, + DynaKube: dynakube.DynaKube{ + Status: dynakube.DynaKubeStatus{ + KubernetesClusterMEID: "meid", + KubeSystemUUID: "systemuuid", + KubernetesClusterName: "meidname", + }, + }, + }, + InstallContainer: &initContainer, + } + + err := injector.addPodAttributes(&request) + require.NoError(t, err) + + require.Equal(t, *expectedPod, *request.BaseRequest.Pod) + validateAttributes(t, request) + }) + + t.Run("metadata enrichment passes => additional args and annotations", func(t *testing.T) { + initContainer := corev1.Container{ + Args: []string{}, + } + pod := corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + OwnerReferences: []metav1.OwnerReference{ + { + Name: "owner", + APIVersion: "v1", + Kind: "ReplicationController", + Controller: ptr.To(true), + }, + }, + }, + } + owner := corev1.ReplicationController{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "ReplicationController", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "owner", + }, + } + injector := createTestInjectorBase() + injector.metaClient = fake.NewClient(&owner, &pod) + + expectedPod := pod.DeepCopy() + + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + Pod: &pod, + DynaKube: dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + MetadataEnrichment: dynakube.MetadataEnrichment{ + Enabled: ptr.To(true), + }, + }, + Status: dynakube.DynaKubeStatus{ + KubernetesClusterMEID: "meid", + KubeSystemUUID: "systemuuid", + KubernetesClusterName: "meidname", + }, + }, + }, + InstallContainer: &initContainer, + } + + err := injector.addPodAttributes(&request) + require.NoError(t, err) + require.NotEqual(t, *expectedPod, *request.BaseRequest.Pod) + + validateAdditionAttributes(t, request) + }) + + t.Run("metadata enrichment fails => error", func(t *testing.T) { + injector := createTestInjectorBase() + injector.metaClient = fake.NewClient() + + initContainer := corev1.Container{ + Args: []string{}, + } + pod := corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + OwnerReferences: []metav1.OwnerReference{ + { + Name: "owner", + APIVersion: "v1", + Kind: "ReplicationController", + Controller: ptr.To(true), + }, + }, + }, + } + + expectedPod := pod.DeepCopy() + + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + Pod: &pod, + Namespace: corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + metacommon.AnnotationPrefix + "/test": "test", + }, + }, + }, + DynaKube: dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + MetadataEnrichment: dynakube.MetadataEnrichment{ + Enabled: ptr.To(true), + }, + }, + Status: dynakube.DynaKubeStatus{ + KubernetesClusterMEID: "meid", + KubeSystemUUID: "systemuuid", + KubernetesClusterName: "meidname", + }, + }, + }, + InstallContainer: &initContainer, + } + + err := injector.addPodAttributes(&request) + require.Error(t, err) + require.Equal(t, *expectedPod, *request.BaseRequest.Pod) + }) +} + +func TestAddContainerAttributes(t *testing.T) { + validateContainerAttributes := func(t *testing.T, pod corev1.Pod, args []string) { + t.Helper() + + require.NotEmpty(t, args) + + for _, arg := range args { + splitArg := strings.Split(arg, "=") + require.Len(t, splitArg, 2) + + var attr containerattr.Attributes + + require.NoError(t, json.Unmarshal([]byte(splitArg[1]), &attr)) + assert.Contains(t, pod.Spec.Containers, corev1.Container{ + Name: attr.ContainerName, + Image: attr.ToURI(), + }) + } + } + + t.Run("add container-attributes, do not change pod or app-container", func(t *testing.T) { + app1Container := corev1.Container{ + Name: "app-1-name", + Image: "registry1.example.com/repository/image:tag", + } + app2Container := corev1.Container{ + Name: "app-2-name", + Image: "registry2.example.com/repository/image:tag", + } + initContainer := corev1.Container{ + Args: []string{}, + } + pod := corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + app1Container, + app2Container, + }, + }, + } + + expectedPod := pod.DeepCopy() + + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + Pod: &pod, + }, + InstallContainer: &initContainer, + } + + addContainerAttributes(&request) + + require.Equal(t, *expectedPod, *request.BaseRequest.Pod) + + validateContainerAttributes(t, pod, initContainer.Args) + }) + + t.Run("no new container ==> no new arg", func(t *testing.T) { + app1Container := corev1.Container{ + Name: "app-1-name", + Image: "registry1.example.com/repository/image:tag", + } + volumes.AddConfigVolumeMount(&app1Container) + + app2Container := corev1.Container{ + Name: "app-2-name", + Image: "registry2.example.com/repository/image:tag", + } + volumes.AddConfigVolumeMount(&app2Container) + + initContainer := corev1.Container{ + Args: []string{}, + } + pod := corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + app1Container, + app2Container, + }, + }, + } + + expectedPod := pod.DeepCopy() + + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + Pod: &pod, + }, + InstallContainer: &initContainer, + } + + addContainerAttributes(&request) + + require.Equal(t, *expectedPod, *request.BaseRequest.Pod) + require.Empty(t, initContainer.Args) + }) + + t.Run("partially new => only add new", func(t *testing.T) { + app1Container := corev1.Container{ + Name: "app-1-name", + Image: "registry1.example.com/repository/image:tag", + } + volumes.AddConfigVolumeMount(&app1Container) + + app2Container := corev1.Container{ + Name: "app-2-name", + Image: "registry2.example.com/repository/image:tag", + } + + initContainer := corev1.Container{ + Args: []string{}, + } + pod := corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + app1Container, + app2Container, + }, + }, + } + + expectedPod := pod.DeepCopy() + + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + Pod: &pod, + }, + InstallContainer: &initContainer, + } + + addContainerAttributes(&request) + + require.Equal(t, *expectedPod, *request.BaseRequest.Pod) + require.Len(t, initContainer.Args, 1) + validateContainerAttributes(t, pod, initContainer.Args) + }) +} + +func TestCreateImageInfo(t *testing.T) { + type testCase struct { + title string + in string + out containerattr.ImageInfo + } + + testCases := []testCase{ + { + title: "empty URI", + in: "", + out: containerattr.ImageInfo{}, + }, + { + title: "URI with tag", + in: "registry.example.com/repository/image:tag", + out: containerattr.ImageInfo{ + Registry: "registry.example.com", + Repository: "repository/image", + Tag: "tag", + ImageDigest: "", + }, + }, + { + title: "URI with digest", + in: "registry.example.com/repository/image@sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc", + out: containerattr.ImageInfo{ + Registry: "registry.example.com", + Repository: "repository/image", + Tag: "", + ImageDigest: "sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc", + }, + }, + { + title: "URI with digest and tag", + in: "registry.example.com/repository/image:tag@sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc", + out: containerattr.ImageInfo{ + Registry: "registry.example.com", + Repository: "repository/image", + Tag: "tag", + ImageDigest: "sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc", + }, + }, + { + title: "URI with missing tag", + in: "registry.example.com/repository/image", + out: containerattr.ImageInfo{ + Registry: "registry.example.com", + Repository: "repository/image", + }, + }, + { + title: "URI with docker.io (special case in certain libraries)", + in: "docker.io/php:fpm-stretch", + out: containerattr.ImageInfo{ + Registry: "docker.io", + Repository: "php", + Tag: "fpm-stretch", + }, + }, + { + title: "URI with missing registry", + in: "php:fpm-stretch", + out: containerattr.ImageInfo{ + Repository: "php", + Tag: "fpm-stretch", + }, + }, + } + for _, test := range testCases { + t.Run(test.title, func(t *testing.T) { + imageInfo := createImageInfo(test.in) + + require.Equal(t, test.out, imageInfo) + }) + } +} diff --git a/pkg/webhook/mutation/pod/v2/common/arg/arg.go b/pkg/webhook/mutation/pod/v2/common/arg/arg.go index d91f12361b..0098e23e99 100644 --- a/pkg/webhook/mutation/pod/v2/common/arg/arg.go +++ b/pkg/webhook/mutation/pod/v2/common/arg/arg.go @@ -8,6 +8,10 @@ type Arg struct { } func (a Arg) String() string { + if a.Value == "" { + return "--" + a.Name + } + return fmt.Sprintf("--%s=%s", a.Name, a.Value) } diff --git a/pkg/webhook/mutation/pod/v2/common/volumes/volumes.go b/pkg/webhook/mutation/pod/v2/common/volumes/volumes.go index d48643385d..065bde0d18 100644 --- a/pkg/webhook/mutation/pod/v2/common/volumes/volumes.go +++ b/pkg/webhook/mutation/pod/v2/common/volumes/volumes.go @@ -13,7 +13,7 @@ const ( ConfigVolumeName = "dynatrace-config" InitConfigMountPath = "/mnt/config" InitConfigSubPath = "config" - ConfigMountPath = "var/lib/dynatrace" + ConfigMountPath = "/var/lib/dynatrace" InputVolumeName = "dynatrace-input" InitInputMountPath = "/mnt/input" diff --git a/pkg/webhook/mutation/pod/v2/init.go b/pkg/webhook/mutation/pod/v2/init.go index 1f440500c5..a44976df96 100644 --- a/pkg/webhook/mutation/pod/v2/init.go +++ b/pkg/webhook/mutation/pod/v2/init.go @@ -1,30 +1,42 @@ package v2 import ( + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/arg" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/volumes" corev1 "k8s.io/api/core/v1" "k8s.io/utils/ptr" ) func createInitContainerBase(pod *corev1.Pod, dk dynakube.DynaKube) *corev1.Container { + args := []arg.Arg{ + { + Name: configure.ConfigFolderFlag, + Value: volumes.InitConfigMountPath, + }, + { + Name: configure.InputFolderFlag, + Value: volumes.InitInputMountPath, + }, + } + + if areErrorsSuppressed(pod, dk) { + args = append(args, arg.Arg{Name: "suppress-error"}) // TODO: import arg from bootstrapper package + } + initContainer := &corev1.Container{ Name: dtwebhook.InstallContainerName, Image: dk.OneAgent().GetCustomCodeModulesImage(), ImagePullPolicy: corev1.PullIfNotPresent, SecurityContext: securityContextForInitContainer(pod, dk), Resources: initContainerResources(dk), + Args: arg.ConvertArgsToStrings(args), } - if areErrorsSuppressed(pod, dk) { - initContainer.Args = append(initContainer.Args, "--suppress-errors") // TODO: import arg from bootstrapper package - } - - // TODO: Add all `--attribute` args to init-container - return initContainer } diff --git a/pkg/webhook/mutation/pod/v2/init_test.go b/pkg/webhook/mutation/pod/v2/init_test.go index 854e9dce6b..b43c3c7241 100644 --- a/pkg/webhook/mutation/pod/v2/init_test.go +++ b/pkg/webhook/mutation/pod/v2/init_test.go @@ -116,7 +116,7 @@ func TestCreateInitContainerBase(t *testing.T) { assert.Equal(t, corev1.SeccompProfileTypeRuntimeDefault, initContainer.SecurityContext.SeccompProfile.Type) }) - t.Run("should not set suppress-errors arg - according to dk", func(t *testing.T) { + t.Run("should not set suppress-error arg - according to dk", func(t *testing.T) { dk := getTestDynakube() dk.Annotations = map[string]string{dynakube.AnnotationInjectionFailurePolicy: "fail"} pod := getTestPod() @@ -124,10 +124,10 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer := createInitContainerBase(pod, *dk) - assert.NotContains(t, initContainer.Args, "--suppress-errors") + assert.NotContains(t, initContainer.Args, "--suppress-error") }) - t.Run("should not set suppress-errors arg - according to pod", func(t *testing.T) { + t.Run("should not set suppress-error arg - according to pod", func(t *testing.T) { dk := getTestDynakube() dk.Annotations = map[string]string{dynakube.AnnotationInjectionFailurePolicy: "silent"} pod := getTestPod() @@ -135,10 +135,10 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer := createInitContainerBase(pod, *dk) - assert.NotContains(t, initContainer.Args, "--suppress-errors") + assert.NotContains(t, initContainer.Args, "--suppress-error") }) - t.Run("should set suppress-errors arg - default", func(t *testing.T) { + t.Run("should set suppress-error arg - default", func(t *testing.T) { dk := getTestDynakube() dk.Annotations = map[string]string{} pod := getTestPod() @@ -146,10 +146,10 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer := createInitContainerBase(pod, *dk) - assert.Contains(t, initContainer.Args, "--suppress-errors") + assert.Contains(t, initContainer.Args, "--suppress-error") }) - t.Run("should set suppress-errors arg - unknown value", func(t *testing.T) { + t.Run("should set suppress-error arg - unknown value", func(t *testing.T) { dk := getTestDynakube() dk.Annotations = map[string]string{dynakube.AnnotationInjectionFailurePolicy: "asd"} pod := getTestPod() @@ -157,7 +157,7 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer := createInitContainerBase(pod, *dk) - assert.Contains(t, initContainer.Args, "--suppress-errors") + assert.Contains(t, initContainer.Args, "--suppress-error") dk = getTestDynakube() dk.Annotations = map[string]string{} @@ -166,7 +166,7 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer = createInitContainerBase(pod, *dk) - assert.Contains(t, initContainer.Args, "--suppress-errors") + assert.Contains(t, initContainer.Args, "--suppress-error") }) } diff --git a/pkg/webhook/mutation/pod/v2/metadata/config.go b/pkg/webhook/mutation/pod/v2/metadata/config.go index 11e7fcedff..8a678f8d8e 100644 --- a/pkg/webhook/mutation/pod/v2/metadata/config.go +++ b/pkg/webhook/mutation/pod/v2/metadata/config.go @@ -5,5 +5,5 @@ import ( ) var ( - log = logd.Get().WithName("metadata-enrichment-pod-v2-mutation") + log = logd.Get().WithName("v2-pod-mutation-metadata-enrichment") ) diff --git a/pkg/webhook/mutation/pod/v2/metadata/containers.go b/pkg/webhook/mutation/pod/v2/metadata/containers.go index 2ce40b8030..d7339ea95a 100644 --- a/pkg/webhook/mutation/pod/v2/metadata/containers.go +++ b/pkg/webhook/mutation/pod/v2/metadata/containers.go @@ -1,21 +1,54 @@ package metadata import ( - "context" + "maps" + "strings" + podattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/pod" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" "sigs.k8s.io/controller-runtime/pkg/client" ) -func Mutate(context context.Context, metaClient client.Client, request *dtwebhook.MutationRequest) bool { +func Mutate(metaClient client.Client, request *dtwebhook.MutationRequest, attributes *podattr.Attributes) error { if !metacommon.IsEnabled(request.BaseRequest) { - return false + return nil } log.Info("adding metadata-enrichment to pod", "name", request.PodName()) - // TODO: probably will only modify the iniContainer and pod, not the containers + workloadInfo, err := metacommon.RetrieveWorkload(metaClient, request) + if err != nil { + return err + } + + attributes.WorkloadInfo = podattr.WorkloadInfo{ + WorkloadKind: workloadInfo.Kind, + WorkloadName: workloadInfo.Name, + } + + addMetadataToInitArgs(request, attributes) + + metacommon.SetInjectedAnnotation(request.Pod) + metacommon.SetWorkloadAnnotations(request.Pod, workloadInfo) + + return nil +} + +func addMetadataToInitArgs(request *dtwebhook.MutationRequest, attributes *podattr.Attributes) { + metacommon.CopyMetadataFromNamespace(request.Pod, request.Namespace, request.DynaKube) + + metadataAnnotations := map[string]string{} + + for key, value := range request.Pod.Annotations { + if !strings.HasPrefix(key, dynakube.MetadataPrefix) { + continue + } + + split := strings.Split(key, dynakube.MetadataPrefix) + metadataAnnotations[split[1]] = value + } - return true + maps.Copy(attributes.UserDefined, metadataAnnotations) } diff --git a/pkg/webhook/mutation/pod/v2/webhook.go b/pkg/webhook/mutation/pod/v2/webhook.go index aaa6f605e6..09075a346f 100644 --- a/pkg/webhook/mutation/pod/v2/webhook.go +++ b/pkg/webhook/mutation/pod/v2/webhook.go @@ -8,7 +8,6 @@ import ( dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" - metamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/metadata" oamutation "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/oneagent" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -31,7 +30,7 @@ func NewInjector(apiReader client.Reader, metaClient client.Client, recorder eve } } -func (wh *Injector) Handle(ctx context.Context, mutationRequest *dtwebhook.MutationRequest) error { +func (wh *Injector) Handle(_ context.Context, mutationRequest *dtwebhook.MutationRequest) error { wh.recorder.Setup(mutationRequest) if !wh.isInputSecretPresent(mutationRequest) { @@ -52,7 +51,7 @@ func (wh *Injector) Handle(ctx context.Context, mutationRequest *dtwebhook.Mutat log.Info("no change, all containers already injected", "podName", mutationRequest.PodName()) } else { - if err := wh.handlePodMutation(ctx, mutationRequest); err != nil { + if err := wh.handlePodMutation(mutationRequest); err != nil { return err } } @@ -75,9 +74,14 @@ func (wh *Injector) isInjected(mutationRequest *dtwebhook.MutationRequest) bool return false } -func (wh *Injector) handlePodMutation(ctx context.Context, mutationRequest *dtwebhook.MutationRequest) error { +func (wh *Injector) handlePodMutation(mutationRequest *dtwebhook.MutationRequest) error { mutationRequest.InstallContainer = createInitContainerBase(mutationRequest.Pod, mutationRequest.DynaKube) + err := addContainerAttributes(mutationRequest) + if err != nil { + return err + } + updated := oamutation.Mutate(mutationRequest) if !updated { oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoMutationNeededReason) @@ -85,11 +89,15 @@ func (wh *Injector) handlePodMutation(ctx context.Context, mutationRequest *dtwe return nil } - oacommon.SetInjectedAnnotation(mutationRequest.Pod) + err = wh.addPodAttributes(mutationRequest) + if err != nil { + log.Info("failed to add pod attributes to init-container") - _ = metamutation.Mutate(ctx, wh.metaClient, mutationRequest) // TODO: finalize + return err + } + + oacommon.SetInjectedAnnotation(mutationRequest.Pod) - // TODO: Add `--attribute-container` for new containers to init-container addInitContainerToPod(mutationRequest.Pod, mutationRequest.InstallContainer) wh.recorder.SendPodInjectEvent() @@ -97,8 +105,16 @@ func (wh *Injector) handlePodMutation(ctx context.Context, mutationRequest *dtwe } func (wh *Injector) handlePodReinvocation(mutationRequest *dtwebhook.MutationRequest) bool { + mutationRequest.InstallContainer = container.FindInitContainerInPodSpec(&mutationRequest.Pod.Spec, dtwebhook.InstallContainerName) + + err := addContainerAttributes(mutationRequest) + if err != nil { + log.Error(err, "error during reinvocation for updating the init-container, failed to update container-attributes on the init container") + + return false + } + updated := oamutation.Reinvoke(mutationRequest.BaseRequest) - // TODO: Add `--attribute-container` for new containers to init-container return updated } diff --git a/pkg/webhook/mutation/pod/v2/webhook_test.go b/pkg/webhook/mutation/pod/v2/webhook_test.go index 064d046c5c..c925652597 100644 --- a/pkg/webhook/mutation/pod/v2/webhook_test.go +++ b/pkg/webhook/mutation/pod/v2/webhook_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" @@ -38,7 +39,7 @@ func TestHandle(t *testing.T) { } t.Run("no init secret => no injection + only annotation", func(t *testing.T) { - injector := createTestInjector() + injector := createTestInjectorBase() injector.apiReader = fake.NewClient() request := createTestMutationRequest(getTestDynakube()) @@ -56,7 +57,7 @@ func TestHandle(t *testing.T) { }) t.Run("no codeModulesImage => no injection + only annotation", func(t *testing.T) { - injector := createTestInjector() + injector := createTestInjectorBase() injector.apiReader = fake.NewClient(&initSecret) request := createTestMutationRequest(&dynakube.DynaKube{}) @@ -72,23 +73,45 @@ func TestHandle(t *testing.T) { require.True(t, ok) assert.Equal(t, NoCodeModulesImageReason, reason) }) + + t.Run("happy path", func(t *testing.T) { + injector := createTestInjectorBase() + injector.apiReader = fake.NewClient(&initSecret) + + request := createTestMutationRequest(getTestDynakube()) + + err := injector.Handle(ctx, request) + require.NoError(t, err) + + isInjected, ok := request.Pod.Annotations[oacommon.AnnotationInjected] + require.True(t, ok) + assert.Equal(t, "true", isInjected) + + _, ok = request.Pod.Annotations[oacommon.AnnotationReason] + require.False(t, ok) + + installContainer := container.FindInitContainerInPodSpec(&request.Pod.Spec, dtwebhook.InstallContainerName) + require.NotNil(t, installContainer) + assert.Len(t, installContainer.Env, 3) + assert.Len(t, installContainer.Args, 14) + }) } func TestIsInjected(t *testing.T) { t.Run("init-container present == injected", func(t *testing.T) { - injector := createTestInjector() + injector := createTestInjectorBase() assert.True(t, injector.isInjected(createTestMutationRequestWithInjectedPod(getTestDynakube()))) }) t.Run("init-container NOT present != injected", func(t *testing.T) { - injector := createTestInjector() + injector := createTestInjectorBase() assert.False(t, injector.isInjected(createTestMutationRequest(getTestDynakube()))) }) } -func createTestInjector() *Injector { +func createTestInjectorBase() *Injector { return &Injector{ recorder: events.NewRecorder(record.NewFakeRecorder(10)), } @@ -100,6 +123,11 @@ func getTestDynakube() *dynakube.DynaKube { Spec: dynakube.DynaKubeSpec{ OneAgent: getAppMonSpec(&testResourceRequirements), }, + Status: dynakube.DynaKubeStatus{ + KubernetesClusterMEID: "meid", + KubeSystemUUID: "systemuuid", + KubernetesClusterName: "meidname", + }, } } @@ -149,7 +177,7 @@ func getTestPod() *corev1.Pod { Containers: []corev1.Container{ { Name: "container", - Image: "alpine", + Image: "docker.io/php:fpm-stretch", SecurityContext: getTestSecurityContext(), }, }, @@ -234,3 +262,63 @@ func getTestNamespace() *corev1.Namespace { }, } } + +func TestIsCustomImageSet(t *testing.T) { + t.Run("true", func(t *testing.T) { + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + DynaKube: *getTestDynakube(), + }, + } + + assert.True(t, isCustomImageSet(&request)) + }) + t.Run("false, set annotations", func(t *testing.T) { + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + DynaKube: *getTestDynakube(), + Pod: &corev1.Pod{}, + }, + } + + request.DynaKube.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage = "" + + assert.False(t, isCustomImageSet(&request)) + assert.Equal(t, NoCodeModulesImageReason, request.Pod.Annotations[oacommon.AnnotationReason]) + assert.Equal(t, "false", request.Pod.Annotations[oacommon.AnnotationInjected]) + }) +} + +func TestSetDynatraceInjectedAnnotation(t *testing.T) { + t.Run("add annotation", func(t *testing.T) { + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + Pod: &corev1.Pod{}, + }, + } + + setDynatraceInjectedAnnotation(&request) + + require.Len(t, request.Pod.Annotations, 1) + assert.Equal(t, "true", request.Pod.Annotations[dtwebhook.AnnotationDynatraceInjected]) + }) + + t.Run("remove reason annotation", func(t *testing.T) { + request := dtwebhook.MutationRequest{ + BaseRequest: &dtwebhook.BaseRequest{ + Pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + dtwebhook.AnnotationDynatraceReason: "beep", + }, + }, + }, + }, + } + + setDynatraceInjectedAnnotation(&request) + + require.Len(t, request.Pod.Annotations, 1) + assert.Equal(t, "true", request.Pod.Annotations[dtwebhook.AnnotationDynatraceInjected]) + }) +} From d58978c982b3f54f657804ba2a2988fb8a123a1c Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Fri, 14 Mar 2025 17:24:34 +0100 Subject: [PATCH 316/426] fix: supportarchive e2e test, wrong field selector (#4597) --- cmd/support_archive/builder.go | 6 +++--- cmd/support_archive/resource_query.go | 6 ++++-- test/features/support_archive/files.go | 7 ++++++- test/helpers/kubeobjects/event/list.go | 4 ++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/cmd/support_archive/builder.go b/cmd/support_archive/builder.go index 4678a28087..e7d7df4e55 100644 --- a/cmd/support_archive/builder.go +++ b/cmd/support_archive/builder.go @@ -39,7 +39,7 @@ const ( collectManagedLogsFlagName = "managed-logs" numEventsFlagName = "num-events" defaultSimFileSize = 10 - defaultNumEvents = 300 + DefaultNumEvents = 300 ) const ( @@ -55,7 +55,7 @@ var ( loadsimFileSizeFlagValue int collectManagedLogsFlagValue bool delayFlagValue int - numEventsFlagValue int + NumEventsFlagValue int ) type CommandBuilder struct { @@ -94,7 +94,7 @@ func addFlags(cmd *cobra.Command) { cmd.PersistentFlags().IntVar(&loadsimFilesFlagValue, loadsimFilesFlagName, 0, "Number of simulated log files (default 0)") cmd.PersistentFlags().BoolVar(&collectManagedLogsFlagValue, collectManagedLogsFlagName, true, "Add logs from rolled out pods to the support archive.") cmd.PersistentFlags().IntVar(&delayFlagValue, delayFlagName, 0, "Delay start of support-archive collection. Useful for standalone execution with 'kubectl run'") - cmd.PersistentFlags().IntVar(&numEventsFlagValue, numEventsFlagName, defaultNumEvents, fmt.Sprintf("Number of events to be fetched (default %d)", defaultNumEvents)) + cmd.PersistentFlags().IntVar(&NumEventsFlagValue, numEventsFlagName, DefaultNumEvents, fmt.Sprintf("Number of events to be fetched (default %d)", DefaultNumEvents)) } func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { diff --git a/cmd/support_archive/resource_query.go b/cmd/support_archive/resource_query.go index 1a2be37e19..1bb1eb1d00 100644 --- a/cmd/support_archive/resource_query.go +++ b/cmd/support_archive/resource_query.go @@ -16,6 +16,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) +var DefaultEventFieldSelector = fields.OneTermEqualSelector("type", corev1.EventTypeWarning) + type resourceQueryGroup struct { resources []schema.GroupVersionKind filters []client.ListOption @@ -114,9 +116,9 @@ func getEventsQueryGroup(namespace string) resourceQueryGroup { }, filters: []client.ListOption{ client.InNamespace(namespace), - client.Limit(numEventsFlagValue), + client.Limit(NumEventsFlagValue), &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector("type", corev1.EventTypeWarning), + FieldSelector: DefaultEventFieldSelector, }, }, } diff --git a/test/features/support_archive/files.go b/test/features/support_archive/files.go index 7a993c7991..85425df731 100644 --- a/test/features/support_archive/files.go +++ b/test/features/support_archive/files.go @@ -24,6 +24,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/statefulset" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/e2e-framework/klient/k8s/resources" ) @@ -352,7 +353,11 @@ func (r requiredFiles) getRequiredConfigMapFiles() []string { } func (r requiredFiles) getRequiredEventFiles() []string { - events := event.List(r.t, r.ctx, r.resources, r.dk.Namespace) + optFunc := func(options *metav1.ListOptions) { + options.Limit = int64(support_archive.NumEventsFlagValue) + options.FieldSelector = fmt.Sprint(support_archive.DefaultEventFieldSelector) + } + events := event.List(r.t, r.ctx, r.resources, r.dk.Namespace, optFunc) requiredFiles := make([]string, 0) for _, requiredEvent := range events.Items { diff --git a/test/helpers/kubeobjects/event/list.go b/test/helpers/kubeobjects/event/list.go index 22152ef3ab..76a4de105d 100644 --- a/test/helpers/kubeobjects/event/list.go +++ b/test/helpers/kubeobjects/event/list.go @@ -11,10 +11,10 @@ import ( "sigs.k8s.io/e2e-framework/klient/k8s/resources" ) -func List(t *testing.T, ctx context.Context, resource *resources.Resources, namespace string) corev1.EventList { +func List(t *testing.T, ctx context.Context, resource *resources.Resources, namespace string, listOpt resources.ListOption) corev1.EventList { var events corev1.EventList - require.NoError(t, resource.WithNamespace(namespace).List(ctx, &events)) + require.NoError(t, resource.WithNamespace(namespace).List(ctx, &events, listOpt)) return events } From d5e93994547288044f5683c327d5a0ab9e3906c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 06:18:44 +0000 Subject: [PATCH 317/426] fix(deps): update module github.com/spf13/afero to v1.13.0 (main) (#4602) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 4bfebc8d50..c7bc49011d 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.21.1 - github.com/spf13/afero v1.12.0 + github.com/spf13/afero v1.13.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v1.27.0 @@ -153,11 +153,11 @@ require ( golang.org/x/sync v0.12.0 // indirect golang.org/x/term v0.30.0 // indirect golang.org/x/text v0.23.0 // indirect - golang.org/x/time v0.8.0 // indirect + golang.org/x/time v0.11.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/protobuf v1.36.5 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 41809a960b..3881b39981 100644 --- a/go.sum +++ b/go.sum @@ -153,8 +153,8 @@ github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWN github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.13.0 h1:vsS0j+yJBlVMOn+zGCK3C5uhtp8GDT8RsJCdlr3Ne2s= +github.com/spf13/afero v1.13.0/go.mod h1:YyftDRCfbalZwshZ4hPgI6ZXNussxDgGOacazISk/84= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= @@ -341,8 +341,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -357,10 +357,10 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= -google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= -google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= From 379a5459525159de5853064870466dedbd1242a6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 22:03:37 +0000 Subject: [PATCH 318/426] fix(deps): update module github.com/spf13/afero to v1.14.0 (main) (#4603) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c7bc49011d..e1b5789e06 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.21.1 - github.com/spf13/afero v1.13.0 + github.com/spf13/afero v1.14.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v1.27.0 diff --git a/go.sum b/go.sum index 3881b39981..b2d91f810e 100644 --- a/go.sum +++ b/go.sum @@ -153,8 +153,8 @@ github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWN github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.13.0 h1:vsS0j+yJBlVMOn+zGCK3C5uhtp8GDT8RsJCdlr3Ne2s= -github.com/spf13/afero v1.13.0/go.mod h1:YyftDRCfbalZwshZ4hPgI6ZXNussxDgGOacazISk/84= +github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= +github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= From 1e34d8ab7b41eb2423ace43bce4505bcd40a978d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 08:52:28 +0000 Subject: [PATCH 319/426] chore(deps): update actions/setup-node action to v4.3.0 (main) (#4604) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ad659efd01..84dc0c02e0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -109,7 +109,7 @@ jobs: uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 with: token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 + - uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 - name: Check deepcopy files are up-to-date id: deepcopy run: | From 4fe1a17077828912a88d67bbd32e79f0eb37a3e0 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Mon, 17 Mar 2025 09:59:05 +0100 Subject: [PATCH 320/426] Add and use bootstrapper-config secret replication (#4600) --- .../dynakube/injection/reconciler.go | 2 +- .../bootstrapperconfig/bootstrapperconfig.go | 29 ++++--- .../bootstrapperconfig_test.go | 64 +++++++++++----- .../namespace/bootstrapperconfig/replicate.go | 51 +++++++++++++ .../bootstrapperconfig/replicate_test.go | 76 +++++++++++++++++++ pkg/webhook/mutation/pod/register.go | 8 +- pkg/webhook/mutation/pod/v2/webhook.go | 21 +++-- pkg/webhook/mutation/pod/v2/webhook_test.go | 38 +++++++++- 8 files changed, 249 insertions(+), 40 deletions(-) create mode 100644 pkg/injection/namespace/bootstrapperconfig/replicate.go create mode 100644 pkg/injection/namespace/bootstrapperconfig/replicate_test.go diff --git a/pkg/controllers/dynakube/injection/reconciler.go b/pkg/controllers/dynakube/injection/reconciler.go index cdb4467072..bc0180098e 100644 --- a/pkg/controllers/dynakube/injection/reconciler.go +++ b/pkg/controllers/dynakube/injection/reconciler.go @@ -207,7 +207,7 @@ func (r *reconciler) cleanupOneAgentInjection(ctx context.Context) { } if r.dk.FeatureBootstrapperInjection() { - err = bootstrapperconfig.Cleanup(ctx, r.client, r.apiReader, namespaces) + err = bootstrapperconfig.Cleanup(ctx, r.client, r.apiReader, namespaces, *r.dk) if err != nil { log.Error(err, "failed to clean-up bootstrapper code module injection init-secrets") } diff --git a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go index 47cfbfc9cf..c82f48a7d9 100644 --- a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go +++ b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go @@ -61,17 +61,27 @@ func (s *SecretGenerator) GenerateForDynakube(ctx context.Context, dk *dynakube. return err } + err = s.createSourceForWebhook(ctx, dk, data) + if err != nil { + return err + } + log.Info("done updating init secrets") return nil } -func Cleanup(ctx context.Context, client client.Client, apiReader client.Reader, namespaces []corev1.Namespace) error { +func Cleanup(ctx context.Context, client client.Client, apiReader client.Reader, namespaces []corev1.Namespace, dk dynakube.DynaKube) error { nsList := make([]string, 0, len(namespaces)) for _, ns := range namespaces { nsList = append(nsList, ns.Name) } + err := k8ssecret.Query(client, apiReader, log).DeleteForNamespace(ctx, GetSourceSecretName(dk.Name), dk.Namespace) + if err != nil { + log.Error(err, "failed to delete the source bootstrapper-config secret", "name", GetSourceSecretName(dk.Name)) + } + return k8ssecret.Query(client, apiReader, log).DeleteForNamespaces(ctx, consts.BootstrapperInitSecretName, nsList) } @@ -97,16 +107,17 @@ func (s *SecretGenerator) generate(ctx context.Context, dk *dynakube.DynaKube) ( return nil, errors.WithStack(err) } - initialConnectRetryMs := "" - if dk.FeatureAgentInitialConnectRetry() > -1 { - initialConnectRetryMs = strconv.Itoa(dk.FeatureAgentInitialConnectRetry()) - } - - return map[string][]byte{ + data := map[string][]byte{ pmc.InputFileName: pmcSecret, ca.TrustedCertsInputFile: trustedCAs, ca.AgCertsInputFile: agCerts, - curl.InputFileName: []byte(initialConnectRetryMs), endpoint.InputFileName: []byte(endpointProperties), - }, nil + } + + if dk.FeatureAgentInitialConnectRetry() > -1 { + initialConnectRetryMs := strconv.Itoa(dk.FeatureAgentInitialConnectRetry()) + data[curl.InputFileName] = []byte(initialConnectRetryMs) + } + + return data, err } diff --git a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go index d2d041f26b..3e3574fa47 100644 --- a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go +++ b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -61,7 +62,7 @@ func TestNewSecretGenerator(t *testing.T) { func TestGenerateForDynakube(t *testing.T) { t.Run("succcessfully generate secret for dynakube", func(t *testing.T) { - dynakube := &dynakube.DynaKube{ + dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Name: testDynakube, Namespace: testNamespaceDynatrace, @@ -72,13 +73,13 @@ func TestGenerateForDynakube(t *testing.T) { } clt := fake.NewClientWithIndex( - dynakube, + dk, clientInjectedNamespace(testNamespace, testDynakube), clientSecret(testDynakube, testNamespaceDynatrace, map[string][]byte{ dtclient.ApiToken: []byte(testAPIToken), dtclient.PaasToken: []byte(testPaasToken), }), - clientSecret(dynakube.OneAgent().GetTenantSecret(), testNamespaceDynatrace, map[string][]byte{ + clientSecret(dk.OneAgent().GetTenantSecret(), testNamespaceDynatrace, map[string][]byte{ "tenant-token": []byte(testTenantToken), }), ) @@ -88,15 +89,21 @@ func TestGenerateForDynakube(t *testing.T) { mockDTClient.On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("uint")).Return(&dtclient.ProcessModuleConfig{}, nil) secretGenerator := NewSecretGenerator(clt, clt, mockDTClient) - err := secretGenerator.GenerateForDynakube(context.Background(), dynakube) + err := secretGenerator.GenerateForDynakube(context.Background(), dk) require.NoError(t, err) var secret corev1.Secret err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &secret) require.NoError(t, err) + require.Equal(t, consts.BootstrapperInitSecretName, secret.Name) + assert.NotEmpty(t, secret.Data) - require.NotEmpty(t, secret) - assert.Equal(t, consts.BootstrapperInitSecretName, secret.Name) + var sourceSecret corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: GetSourceSecretName(dk.Name), Namespace: dk.Namespace}, &sourceSecret) + require.NoError(t, err) + + require.Equal(t, GetSourceSecretName(dk.Name), sourceSecret.Name) + assert.Equal(t, secret.Data, sourceSecret.Data) }) t.Run("succcessfully generate secret with fields for dynakube", func(t *testing.T) { dk := &dynakube.DynaKube{ @@ -175,6 +182,13 @@ func TestGenerateForDynakube(t *testing.T) { _, ok = secret.Data[endpoint.InputFileName] require.True(t, ok) + + var sourceSecret corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: GetSourceSecretName(dk.Name), Namespace: dk.Namespace}, &sourceSecret) + require.NoError(t, err) + + require.Equal(t, GetSourceSecretName(dk.Name), sourceSecret.Name) + assert.Equal(t, secret.Data, sourceSecret.Data) }) t.Run("update secret with preexisting secret + fields", func(t *testing.T) { dk := &dynakube.DynaKube{ @@ -216,6 +230,11 @@ func TestGenerateForDynakube(t *testing.T) { ca.TrustedCertsInputFile: []byte(oldTrustedCa), ca.AgCertsInputFile: []byte(oldCertValue), }), + clientSecret(GetSourceSecretName(dk.Name), dk.Namespace, map[string][]byte{ + pmc.InputFileName: nil, + ca.TrustedCertsInputFile: []byte(oldTrustedCa), + ca.AgCertsInputFile: []byte(oldCertValue), + }), ) mockDTClient := dtclientmock.NewClient(t) @@ -251,6 +270,13 @@ func TestGenerateForDynakube(t *testing.T) { _, ok = secret.Data[endpoint.InputFileName] require.True(t, ok) + + var sourceSecret corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: GetSourceSecretName(dk.Name), Namespace: dk.Namespace}, &sourceSecret) + require.NoError(t, err) + + require.Equal(t, GetSourceSecretName(dk.Name), sourceSecret.Name) + assert.Equal(t, secret.Data, sourceSecret.Data) }) t.Run("fail while generating secret for dynakube", func(t *testing.T) { dynakube := &dynakube.DynaKube{ @@ -283,7 +309,7 @@ func TestGenerateForDynakube(t *testing.T) { } func TestCleanup(t *testing.T) { - dynakube := &dynakube.DynaKube{ + dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Name: testDynakube, Namespace: testNamespaceDynatrace, @@ -294,17 +320,18 @@ func TestCleanup(t *testing.T) { } clt := fake.NewClientWithIndex( - dynakube, + dk, clientInjectedNamespace(testNamespace, testDynakube), clientSecret(testDynakube, testNamespaceDynatrace, map[string][]byte{ dtclient.ApiToken: []byte(testAPIToken), dtclient.PaasToken: []byte(testPaasToken), }), - clientSecret(dynakube.OneAgent().GetTenantSecret(), testNamespaceDynatrace, map[string][]byte{ + clientSecret(dk.OneAgent().GetTenantSecret(), testNamespaceDynatrace, map[string][]byte{ "tenant-token": []byte(testTenantToken), }), clientSecret(consts.BootstrapperInitSecretName, testNamespace, nil), clientSecret(consts.BootstrapperInitSecretName, testNamespace2, nil), + clientSecret(GetSourceSecretName(dk.Name), dk.Namespace, nil), ) namespaces := []corev1.Namespace{ {ObjectMeta: metav1.ObjectMeta{Name: testNamespace}}, @@ -325,22 +352,21 @@ func TestCleanup(t *testing.T) { require.NotEmpty(t, secretNS2) assert.Equal(t, consts.BootstrapperInitSecretName, secretNS2.Name) - err = Cleanup(context.Background(), clt, clt, namespaces) + err = Cleanup(context.Background(), clt, clt, namespaces, *dk) require.NoError(t, err) - var deletedSecretNS1 corev1.Secret - err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &deletedSecretNS1) + var deleted corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &deleted) require.Error(t, err) + assert.True(t, errors.IsNotFound(err)) - require.Empty(t, deletedSecretNS1) - assert.NotEqual(t, consts.BootstrapperInitSecretName, deletedSecretNS1.Name) - - var deletedSecretNS2 corev1.Secret - err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace}, &deletedSecretNS2) + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: testNamespace2}, &deleted) require.Error(t, err) + assert.True(t, errors.IsNotFound(err)) - require.Empty(t, deletedSecretNS2) - assert.NotEqual(t, consts.BootstrapperInitSecretName, deletedSecretNS2.Name) + err = clt.Get(context.Background(), client.ObjectKey{Name: GetSourceSecretName(dk.Name), Namespace: dk.Namespace}, &deleted) + require.Error(t, err) + assert.True(t, errors.IsNotFound(err)) } func clientSecret(secretName string, namespaceName string, data map[string][]byte) *corev1.Secret { diff --git a/pkg/injection/namespace/bootstrapperconfig/replicate.go b/pkg/injection/namespace/bootstrapperconfig/replicate.go new file mode 100644 index 0000000000..f0692ba2ec --- /dev/null +++ b/pkg/injection/namespace/bootstrapperconfig/replicate.go @@ -0,0 +1,51 @@ +package bootstrapperconfig + +import ( + "context" + "fmt" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + sourceSecretTemplate = "%s-bootstrapper-config" +) + +func GetSourceSecretName(dkName string) string { + return fmt.Sprintf(sourceSecretTemplate, dkName) +} + +func Replicate(ctx context.Context, dk dynakube.DynaKube, query k8ssecret.QueryObject, targetNs string) error { + source, err := query.Get(ctx, types.NamespacedName{Name: GetSourceSecretName(dk.Name), Namespace: dk.Namespace}) + if err != nil { + return err + } + + secret, err := k8ssecret.BuildForNamespace(consts.BootstrapperInitSecretName, targetNs, source.Data, k8ssecret.SetLabels(source.Labels)) + if err != nil { + return err + } + + return client.IgnoreAlreadyExists(query.Create(ctx, secret)) +} + +func (s *SecretGenerator) createSourceForWebhook(ctx context.Context, dk *dynakube.DynaKube, data map[string][]byte) error { + coreLabels := k8slabels.NewCoreLabels(dk.Name, k8slabels.WebhookComponentLabel) + + secret, err := k8ssecret.BuildForNamespace(GetSourceSecretName(dk.Name), dk.Namespace, data, k8ssecret.SetLabels(coreLabels.BuildLabels())) + if err != nil { + return err + } + + _, err = k8ssecret.Query(s.client, s.apiReader, log).WithOwner(dk).CreateOrUpdate(ctx, secret) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/injection/namespace/bootstrapperconfig/replicate_test.go b/pkg/injection/namespace/bootstrapperconfig/replicate_test.go new file mode 100644 index 0000000000..63cf45e29e --- /dev/null +++ b/pkg/injection/namespace/bootstrapperconfig/replicate_test.go @@ -0,0 +1,76 @@ +package bootstrapperconfig + +import ( + "context" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func TestReplicate(t *testing.T) { + ctx := context.Background() + dk := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dk", + Namespace: "dk-ns", + }, + } + + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user-ns", + }, + } + + data := map[string][]byte{ + "data": []byte("beep"), + } + + t.Run("create", func(t *testing.T) { + source := clientSecret(GetSourceSecretName(dk.Name), dk.Namespace, data) + source.Labels = map[string]string{ + "key": "value", + } + clt := fake.NewClientWithIndex( + dk, + ns, + source, + ) + + err := Replicate(ctx, *dk, secret.Query(clt, clt, log), ns.Name) + require.NoError(t, err) + + var replicated corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: ns.Name}, &replicated) + require.NoError(t, err) + assert.Equal(t, source.Data, replicated.Data) + assert.Equal(t, source.Labels, replicated.Labels) + }) + + t.Run("already exists => no update + no error", func(t *testing.T) { + source := clientSecret(GetSourceSecretName(dk.Name), dk.Namespace, data) + alreadyPresent := clientSecret(consts.BootstrapperInitSecretName, ns.Name, nil) + clt := fake.NewClientWithIndex( + dk, + ns, + source, + alreadyPresent, + ) + + err := Replicate(ctx, *dk, secret.Query(clt, clt, log), ns.Name) + require.NoError(t, err) + + var replicated corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: ns.Name}, &replicated) + require.NoError(t, err) + assert.NotEqual(t, source.Data, replicated.Data) + }) +} diff --git a/pkg/webhook/mutation/pod/register.go b/pkg/webhook/mutation/pod/register.go index 520a51ba4d..152e8c3b9e 100644 --- a/pkg/webhook/mutation/pod/register.go +++ b/pkg/webhook/mutation/pod/register.go @@ -10,8 +10,8 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/util/oneagentapm" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" - "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1" - "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2" + podv1 "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v1" + podv2 "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -59,8 +59,8 @@ func registerInjectEndpoint(ctx context.Context, mgr manager.Manager, webhookNam } mgr.GetWebhookServer().Register("/inject", &webhooks.Admission{Handler: &webhook{ - v1: v1.NewInjector(apiReader, kubeClient, metaClient, eventRecorder, clusterID, webhookPodImage, webhookNamespace), - v2: v2.NewInjector(apiReader, metaClient, eventRecorder), + v1: podv1.NewInjector(apiReader, kubeClient, metaClient, eventRecorder, clusterID, webhookPodImage, webhookNamespace), + v2: podv2.NewInjector(kubeClient, apiReader, metaClient, eventRecorder), apiReader: apiReader, webhookNamespace: webhookNamespace, deployedViaOLM: kubesystem.IsDeployedViaOlm(*webhookPod), diff --git a/pkg/webhook/mutation/pod/v2/webhook.go b/pkg/webhook/mutation/pod/v2/webhook.go index 09075a346f..801c23406b 100644 --- a/pkg/webhook/mutation/pod/v2/webhook.go +++ b/pkg/webhook/mutation/pod/v2/webhook.go @@ -4,7 +4,9 @@ import ( "context" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/bootstrapperconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" @@ -16,15 +18,17 @@ import ( type Injector struct { recorder events.EventRecorder + kubeClient client.Client apiReader client.Reader metaClient client.Client } var _ dtwebhook.PodInjector = &Injector{} -func NewInjector(apiReader client.Reader, metaClient client.Client, recorder events.EventRecorder) *Injector { +func NewInjector(kubeClient client.Client, apiReader client.Reader, metaClient client.Client, recorder events.EventRecorder) *Injector { return &Injector{ recorder: recorder, + kubeClient: kubeClient, apiReader: apiReader, metaClient: metaClient, } @@ -137,12 +141,19 @@ func (wh *Injector) isInputSecretPresent(mutationRequest *dtwebhook.MutationRequ err := wh.apiReader.Get(mutationRequest.Context, secretObjectKey, &initSecret) if k8serrors.IsNotFound(err) { - log.Info("dynatrace-bootstrapper-config is not available, injection not possible", "pod", mutationRequest.PodName()) + log.Info("dynatrace-bootstrapper-config is not available, trying to replicate", "pod", mutationRequest.PodName()) - oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoBootstrapperConfigReason) + err = bootstrapperconfig.Replicate(mutationRequest.Context, mutationRequest.DynaKube, secret.Query(wh.kubeClient, wh.apiReader, log), mutationRequest.Namespace.Name) + if k8serrors.IsNotFound(err) { + log.Info("dynatrace-bootstrapper-config is not available, injection not possible", "pod", mutationRequest.PodName()) - return false - } else if err != nil { + oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoBootstrapperConfigReason) + + return false + } + } + + if err != nil { log.Error(err, "unable to verify, if dynatrace-bootstrapper-config is available, injection not possible") oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoBootstrapperConfigReason) diff --git a/pkg/webhook/mutation/pod/v2/webhook_test.go b/pkg/webhook/mutation/pod/v2/webhook_test.go index c925652597..0528ea33dd 100644 --- a/pkg/webhook/mutation/pod/v2/webhook_test.go +++ b/pkg/webhook/mutation/pod/v2/webhook_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/bootstrapperconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" @@ -19,6 +20,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( @@ -38,9 +40,10 @@ func TestHandle(t *testing.T) { }, } - t.Run("no init secret => no injection + only annotation", func(t *testing.T) { + t.Run("no init secret + no init secret source => no injection + only annotation", func(t *testing.T) { injector := createTestInjectorBase() - injector.apiReader = fake.NewClient() + clt := fake.NewClient() + injector.apiReader = clt request := createTestMutationRequest(getTestDynakube()) @@ -56,6 +59,37 @@ func TestHandle(t *testing.T) { assert.Equal(t, NoBootstrapperConfigReason, reason) }) + t.Run("no init secret + source => replicate + inject", func(t *testing.T) { + injector := createTestInjectorBase() + request := createTestMutationRequest(getTestDynakube()) + + source := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: bootstrapperconfig.GetSourceSecretName(request.DynaKube.Name), + Namespace: request.DynaKube.Namespace, + }, + Data: map[string][]byte{"data": []byte("beep")}, + } + clt := fake.NewClient(&source) + injector.kubeClient = clt + injector.apiReader = clt + + err := injector.Handle(ctx, request) + require.NoError(t, err) + + var replicated corev1.Secret + err = clt.Get(context.Background(), client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: request.Namespace.Name}, &replicated) + require.NoError(t, err) + assert.Equal(t, source.Data, replicated.Data) + + isInjected, ok := request.Pod.Annotations[oacommon.AnnotationInjected] + require.True(t, ok) + assert.Equal(t, "true", isInjected) + + _, ok = request.Pod.Annotations[oacommon.AnnotationReason] + require.False(t, ok) + }) + t.Run("no codeModulesImage => no injection + only annotation", func(t *testing.T) { injector := createTestInjectorBase() injector.apiReader = fake.NewClient(&initSecret) From 0a3a3d2c8fbbfce372da4a486ff040d9e82f8c6d Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Mon, 17 Mar 2025 10:06:14 +0100 Subject: [PATCH 321/426] Rename "remote-image-download" to "node-image-pull" (#4601) --- doc/api/feature-flags.md | 2 +- pkg/api/v1beta4/dynakube/dynakube_props.go | 2 +- pkg/api/v1beta4/dynakube/feature_flags.go | 8 ++++---- pkg/api/v1beta4/dynakube/oneagent_props.go | 2 +- pkg/api/validation/dynakube/oneagent.go | 6 +++--- pkg/api/validation/dynakube/oneagent_test.go | 4 ++-- pkg/controllers/csi/provisioner/controller_test.go | 2 +- pkg/controllers/csi/provisioner/install.go | 2 +- pkg/controllers/dynakube/injection/reconciler_test.go | 2 +- pkg/injection/namespace/mapper/dynakubes_test.go | 8 ++++---- pkg/injection/namespace/mapper/mapper_test.go | 4 ++-- pkg/webhook/mutation/pod/v2/oneagent/init.go | 2 +- pkg/webhook/mutation/pod/v2/webhook_test.go | 2 +- pkg/webhook/mutation/pod/webhook_test.go | 8 ++++---- 14 files changed, 27 insertions(+), 27 deletions(-) diff --git a/doc/api/feature-flags.md b/doc/api/feature-flags.md index 0fc1253693..ab2d05b30a 100644 --- a/doc/api/feature-flags.md +++ b/doc/api/feature-flags.md @@ -58,7 +58,7 @@ const ( AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureRemoteImageDownload = AnnotationFeaturePrefix + "remote-image-download" + AnnotationFeatureNodeImagePull = AnnotationFeaturePrefix + "node-image-pull" // AnnotationTechnologies can be set on a Pod or DynaKube to configure which code module technologies to download. It's set to // "all" if not set. diff --git a/pkg/api/v1beta4/dynakube/dynakube_props.go b/pkg/api/v1beta4/dynakube/dynakube_props.go index 4037e5a6fc..c0db3da247 100644 --- a/pkg/api/v1beta4/dynakube/dynakube_props.go +++ b/pkg/api/v1beta4/dynakube/dynakube_props.go @@ -106,5 +106,5 @@ func (dk *DynaKube) IsTokenScopeVerificationAllowed(timeProvider *timeprovider.P } func (dk *DynaKube) FeatureBootstrapperInjection() bool { - return dk.OneAgent().IsApplicationMonitoringMode() && dk.FeatureRemoteImageDownload() && !dk.OneAgent().IsCSIAvailable() + return dk.OneAgent().IsApplicationMonitoringMode() && dk.FeatureNodeImagePull() && !dk.OneAgent().IsCSIAvailable() } diff --git a/pkg/api/v1beta4/dynakube/feature_flags.go b/pkg/api/v1beta4/dynakube/feature_flags.go index daced741e8..a4556aaf80 100644 --- a/pkg/api/v1beta4/dynakube/feature_flags.go +++ b/pkg/api/v1beta4/dynakube/feature_flags.go @@ -74,7 +74,7 @@ const ( AnnotationFeatureMaxFailedCsiMountAttempts = AnnotationFeaturePrefix + "max-csi-mount-attempts" AnnotationFeatureMaxCsiMountTimeout = AnnotationFeaturePrefix + "max-csi-mount-timeout" AnnotationFeatureReadOnlyCsiVolume = AnnotationFeaturePrefix + "injection-readonly-volume" - AnnotationFeatureRemoteImageDownload = AnnotationFeaturePrefix + "remote-image-download" + AnnotationFeatureNodeImagePull = AnnotationFeaturePrefix + "node-image-pull" falsePhrase = "false" truePhrase = "true" @@ -280,11 +280,11 @@ func (dk *DynaKube) FeatureReadOnlyCsiVolume() bool { return dk.getFeatureFlagRaw(AnnotationFeatureReadOnlyCsiVolume) == truePhrase } -func (dk *DynaKube) FeatureRemoteImageDownload() bool { - return dk.getFeatureFlagRaw(AnnotationFeatureRemoteImageDownload) == truePhrase +func (dk *DynaKube) FeatureNodeImagePull() bool { + return dk.getFeatureFlagRaw(AnnotationFeatureNodeImagePull) == truePhrase } -func (dk *DynaKube) FeatureRemoteImageDownloadTechnology() string { +func (dk *DynaKube) FeatureNodeImagePullTechnology() string { return dk.getFeatureFlagRaw(AnnotationTechnologies) } func (dk *DynaKube) FeatureInjectionFailurePolicy() string { diff --git a/pkg/api/v1beta4/dynakube/oneagent_props.go b/pkg/api/v1beta4/dynakube/oneagent_props.go index 09a8007c8e..d4b30e80a1 100644 --- a/pkg/api/v1beta4/dynakube/oneagent_props.go +++ b/pkg/api/v1beta4/dynakube/oneagent_props.go @@ -13,7 +13,7 @@ func (dk *DynaKube) OneAgent() *oneagent.OneAgent { dk.ApiUrlHost(), dk.FeatureOneAgentPrivileged(), dk.FeatureOneAgentSkipLivenessProbe(), - dk.FeatureRemoteImageDownload(), + dk.FeatureNodeImagePull(), ) return oa diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index aacdc48ac1..445a6be76c 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -19,7 +19,7 @@ const ( errorImageFieldSetWithoutCSIFlag = `The DynaKube specification attempts to enable ApplicationMonitoring mode and retrieve the respective image, but the CSI driver and/or remote image download is not enabled.` - errorBootstrapperRemoteImageDownloadRequiresCodeModulesImage = `The DynaKube specification enables remote image download, but the code modules image is not set.` + errorBootstrapperNodeImagePullRequiresCodeModulesImage = `The DynaKube specification enables node image pull, but the code modules image is not set.` errorNodeSelectorConflict = `The Dynakube specification conflicts with another Dynakube's OneAgent or Standalone-LogMonitoring. Only one Agent per node is supported. Use a nodeSelector to avoid this conflict. Conflicting DynaKubes: %s` @@ -147,7 +147,7 @@ func publicImageSetWithoutReadOnlyMode(_ context.Context, v *Validator, dk *dyna func imageFieldSetWithoutCSIFlag(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { if dk.OneAgent().IsApplicationMonitoringMode() { - if len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) > 0 && !v.modules.CSIDriver && !dk.FeatureRemoteImageDownload() { + if len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) > 0 && !v.modules.CSIDriver && !dk.FeatureNodeImagePull() { return errorImageFieldSetWithoutCSIFlag } } @@ -157,7 +157,7 @@ func imageFieldSetWithoutCSIFlag(_ context.Context, v *Validator, dk *dynakube.D func missingCodeModulesImage(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { if dk.FeatureBootstrapperInjection() && len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) == 0 { - return errorBootstrapperRemoteImageDownloadRequiresCodeModulesImage + return errorBootstrapperNodeImagePullRequiresCodeModulesImage } return "" diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index 8415cdb894..ad3b591d91 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -316,7 +316,7 @@ func TestImageFieldSetWithoutCSIFlag(t *testing.T) { Name: testName, Namespace: testNamespace, Annotations: map[string]string{ - dynakube.AnnotationFeatureRemoteImageDownload: "true", + dynakube.AnnotationFeatureNodeImagePull: "true", }, }, Spec: dynakube.DynaKubeSpec{ @@ -341,7 +341,7 @@ func TestImageFieldSetWithoutCSIFlag(t *testing.T) { Name: testName, Namespace: testNamespace, Annotations: map[string]string{ - dynakube.AnnotationFeatureRemoteImageDownload: "false", + dynakube.AnnotationFeatureNodeImagePull: "false", }, }, Spec: dynakube.DynaKubeSpec{ diff --git a/pkg/controllers/csi/provisioner/controller_test.go b/pkg/controllers/csi/provisioner/controller_test.go index dbc70c7683..6c6b9a015e 100644 --- a/pkg/controllers/csi/provisioner/controller_test.go +++ b/pkg/controllers/csi/provisioner/controller_test.go @@ -254,7 +254,7 @@ func createDynaKubeWithJobFF(t *testing.T) *dynakube.DynaKube { } dk.Status.CodeModules.ImageID = imageId dk.Annotations = map[string]string{ - dynakube.AnnotationFeatureRemoteImageDownload: "true", + dynakube.AnnotationFeatureNodeImagePull: "true", } return dk diff --git a/pkg/controllers/csi/provisioner/install.go b/pkg/controllers/csi/provisioner/install.go index 946c5b132e..79eeaaa2bf 100644 --- a/pkg/controllers/csi/provisioner/install.go +++ b/pkg/controllers/csi/provisioner/install.go @@ -51,7 +51,7 @@ func (provisioner *OneAgentProvisioner) installAgent(ctx context.Context, dk dyn func (provisioner *OneAgentProvisioner) getInstaller(ctx context.Context, dk dynakube.DynaKube) (installer.Installer, error) { switch { - case dk.FeatureRemoteImageDownload(): + case dk.FeatureNodeImagePull(): return provisioner.getJobInstaller(ctx, dk), nil case dk.OneAgent().GetCustomCodeModulesImage() != "": props := &image.Properties{ diff --git a/pkg/controllers/dynakube/injection/reconciler_test.go b/pkg/controllers/dynakube/injection/reconciler_test.go index 1038388031..7a2c3ebfde 100644 --- a/pkg/controllers/dynakube/injection/reconciler_test.go +++ b/pkg/controllers/dynakube/injection/reconciler_test.go @@ -396,7 +396,7 @@ func TestSetupOneAgentInjection(t *testing.T) { rec.dynatraceClient = dtClient rec.dk.Annotations = make(map[string]string) - rec.dk.Annotations[dynakube.AnnotationFeatureRemoteImageDownload] = "true" + rec.dk.Annotations[dynakube.AnnotationFeatureNodeImagePull] = "true" rec.versionReconciler = createVersionReconcilerMock(t) rec.connectionInfoReconciler = createGenericReconcilerMock(t) rec.pmcSecretreconciler = createGenericReconcilerMock(t) diff --git a/pkg/injection/namespace/mapper/dynakubes_test.go b/pkg/injection/namespace/mapper/dynakubes_test.go index 5c0c2dce9b..d2c90fc785 100644 --- a/pkg/injection/namespace/mapper/dynakubes_test.go +++ b/pkg/injection/namespace/mapper/dynakubes_test.go @@ -203,10 +203,10 @@ func TestUnmapFromDynaKube(t *testing.T) { t.Run("Remove "+consts.BootstrapperInitSecretName, func(t *testing.T) { installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) - dkRemoteImage := createDynakubeWithRemoteImageDownloadAndNoCSI("dk-test", convertToLabelSelector(labels)) + dkNodeImagePull := createDynakubeWithNodeImagePullAndNoCSI("dk-test", convertToLabelSelector(labels)) labels := map[string]string{ - dtwebhook.InjectionInstanceLabel: dkRemoteImage.Name, + dtwebhook.InjectionInstanceLabel: dkNodeImagePull.Name, } ns := createNamespace("ns-bootstrapper", labels) @@ -215,7 +215,7 @@ func TestUnmapFromDynaKube(t *testing.T) { clt := fake.NewClient(ns, ns2) ctx := context.Background() - namespaces, err := GetNamespacesForDynakube(ctx, clt, dkRemoteImage.Name) + namespaces, err := GetNamespacesForDynakube(ctx, clt, dkNodeImagePull.Name) require.NoError(t, err) var secretNS1 corev1.Secret @@ -238,7 +238,7 @@ func TestUnmapFromDynaKube(t *testing.T) { require.NotEmpty(t, secretNS2) assert.Equal(t, consts.BootstrapperInitSecretName, secretNS2.Name) - dm := NewDynakubeMapper(ctx, clt, clt, "dynatrace", dkRemoteImage) + dm := NewDynakubeMapper(ctx, clt, clt, "dynatrace", dkNodeImagePull) err = dm.UnmapFromDynaKube(namespaces) require.NoError(t, err) diff --git a/pkg/injection/namespace/mapper/mapper_test.go b/pkg/injection/namespace/mapper/mapper_test.go index d3933a3567..ab6accf2d7 100644 --- a/pkg/injection/namespace/mapper/mapper_test.go +++ b/pkg/injection/namespace/mapper/mapper_test.go @@ -53,12 +53,12 @@ func createDynakubeWithMetadataAndAppInjection(name string, selector metav1.Labe return dk } -func createDynakubeWithRemoteImageDownloadAndNoCSI(name string, selector metav1.LabelSelector) *dynakube.DynaKube { +func createDynakubeWithNodeImagePullAndNoCSI(name string, selector metav1.LabelSelector) *dynakube.DynaKube { dk := createBaseDynakube(name, true, false) dk.Annotations = make(map[string]string) - dk.Annotations[dynakube.AnnotationFeatureRemoteImageDownload] = "true" + dk.Annotations[dynakube.AnnotationFeatureNodeImagePull] = "true" dk.Spec.OneAgent.ApplicationMonitoring.NamespaceSelector = selector diff --git a/pkg/webhook/mutation/pod/v2/oneagent/init.go b/pkg/webhook/mutation/pod/v2/oneagent/init.go index 606632acd3..065a54847c 100644 --- a/pkg/webhook/mutation/pod/v2/oneagent/init.go +++ b/pkg/webhook/mutation/pod/v2/oneagent/init.go @@ -44,7 +44,7 @@ func getTechnology(pod corev1.Pod, dk dynakube.DynaKube) string { return technology } - technology := dk.FeatureRemoteImageDownloadTechnology() + technology := dk.FeatureNodeImagePullTechnology() if technology != "" { return technology } diff --git a/pkg/webhook/mutation/pod/v2/webhook_test.go b/pkg/webhook/mutation/pod/v2/webhook_test.go index 0528ea33dd..684f6906e7 100644 --- a/pkg/webhook/mutation/pod/v2/webhook_test.go +++ b/pkg/webhook/mutation/pod/v2/webhook_test.go @@ -186,7 +186,7 @@ func getTestDynakubeMeta() metav1.ObjectMeta { Name: testDynakubeName, Namespace: testNamespaceName, Annotations: map[string]string{ - dynakube.AnnotationFeatureRemoteImageDownload: "true", + dynakube.AnnotationFeatureNodeImagePull: "true", }, } } diff --git a/pkg/webhook/mutation/pod/webhook_test.go b/pkg/webhook/mutation/pod/webhook_test.go index 239e8d757c..89e26d66a4 100644 --- a/pkg/webhook/mutation/pod/webhook_test.go +++ b/pkg/webhook/mutation/pod/webhook_test.go @@ -182,7 +182,7 @@ func TestHandle(t *testing.T) { t.Run("FF appmon-dk WITHOUT CSI ==> v2 injector", func(t *testing.T) { dk := getTestDynakubeDefaultAppMon() dk.Annotations = map[string]string{ - dynakube.AnnotationFeatureRemoteImageDownload: "true", + dynakube.AnnotationFeatureNodeImagePull: "true", } v2Injector := webhookmock.NewPodInjector(t) @@ -208,7 +208,7 @@ func TestHandle(t *testing.T) { t.Run("FF metadata-dk WITHOUT CSI ==> v1 injector", func(t *testing.T) { dk := getTestMetadataDynakube() dk.Annotations = map[string]string{ - dynakube.AnnotationFeatureRemoteImageDownload: "true", + dynakube.AnnotationFeatureNodeImagePull: "true", } v1Injector := webhookmock.NewPodInjector(t) @@ -234,7 +234,7 @@ func TestHandle(t *testing.T) { t.Run("FF appmon-dk WITH CSI ==> v1 injector", func(t *testing.T) { dk := getTestDynakubeDefaultAppMon() dk.Annotations = map[string]string{ - dynakube.AnnotationFeatureRemoteImageDownload: "true", + dynakube.AnnotationFeatureNodeImagePull: "true", } v1Injector := webhookmock.NewPodInjector(t) @@ -283,7 +283,7 @@ func TestHandle(t *testing.T) { t.Run("v2 injector error => silent error", func(t *testing.T) { dk := getTestDynakubeDefaultAppMon() dk.Annotations = map[string]string{ - dynakube.AnnotationFeatureRemoteImageDownload: "true", + dynakube.AnnotationFeatureNodeImagePull: "true", } v2Injector := webhookmock.NewPodInjector(t) From ad74802965d771e3dcc94bef6485a17575b904aa Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Mon, 17 Mar 2025 12:38:16 +0100 Subject: [PATCH 322/426] Smartscape ClusterRole and ClusterRole binding for ActiveGate (#4592) Co-authored-by: Stefan Hauth Co-authored-by: StefanHauth <63204425+StefanHauth@users.noreply.github.com> --- ...lusterrole-kubernetes-monitoring-full.yaml | 61 ++++++++++++++ ...rrole-kubernetes-monitoring-full_test.yaml | 79 +++++++++++++++++++ config/helm/chart/default/values.yaml | 3 + 3 files changed, 143 insertions(+) create mode 100644 config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full.yaml create mode 100644 config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full_test.yaml diff --git a/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full.yaml b/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full.yaml new file mode 100644 index 0000000000..dc24b8dd5d --- /dev/null +++ b/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full.yaml @@ -0,0 +1,61 @@ +{{- if and .Values.rbac.kubernetesMonitoringFull.create .Values.rbac.activeGate.create }} +# Copyright 2021 Dynatrace LLC + +# 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. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: dynatrace-kubernetes-monitoring-full + labels: + {{- include "dynatrace-operator.activegateLabels" . | nindent 4 }} +rules: + - apiGroups: [ "*" ] + resources: [ "*" ] + verbs: + - list + - watch + - get + - nonResourceURLs: + - /metrics + - /version + - /readyz + - /livez + verbs: + - get + {{- if (eq (include "dynatrace-operator.openshiftOrOlm" .) "true") }} + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + - nonroot-v2 + resources: + - securitycontextconstraints + verbs: + - use + {{ end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dynatrace-kubernetes-monitoring-full + labels: + {{- include "dynatrace-operator.activegateLabels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: dynatrace-kubernetes-monitoring-full +subjects: + - kind: ServiceAccount + name: dynatrace-kubernetes-monitoring + namespace: {{ .Release.Namespace }} +{{ end }} diff --git a/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full_test.yaml b/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full_test.yaml new file mode 100644 index 0000000000..9e3cc8d0c9 --- /dev/null +++ b/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full_test.yaml @@ -0,0 +1,79 @@ +suite: test clusterrole for kubernetes monitoring full +templates: + - Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full.yaml +tests: + - it: ClusterRole should exist if enabled + documentIndex: 0 + set: + rbac.activeGate.create: true + rbac.kubernetesMonitoringFull.create.create: true + + asserts: + - isKind: + of: ClusterRole + - equal: + path: metadata.name + value: dynatrace-kubernetes-monitoring-full + - isNotEmpty: + path: metadata.labels + - isNotEmpty: + path: rules + - contains: + path: rules + content: + apiGroups: + - "*" + resources: + - "*" + verbs: + - list + - watch + - get + - contains: + path: rules + content: + nonResourceURLs: + - /metrics + - /version + - /readyz + - /livez + verbs: + - get + - it: ClusterRole should exist if enabled and have extra permissions if on openshift + documentIndex: 0 + set: + platform: openshift + rbac.activeGate.create: true + rbac.kubernetesMonitoringFull.create.create: true + asserts: + - isKind: + of: ClusterRole + - equal: + path: metadata.name + value: dynatrace-kubernetes-monitoring-full + - isNotEmpty: + path: metadata.labels + - contains: + path: rules + content: + apiGroups: + - security.openshift.io + resourceNames: + - privileged + - nonroot-v2 + resources: + - securitycontextconstraints + verbs: + - use + - it: shouldn't exist if activeGate is turned off + set: + rbac.kubernetesMonitoringFull.create: true + rbac.activeGate.create: false + asserts: + - hasDocuments: + count: 0 + - it: shouldn't exist by default + set: + asserts: + - hasDocuments: + count: 0 diff --git a/config/helm/chart/default/values.yaml b/config/helm/chart/default/values.yaml index c6bf800c9d..cbb41262ac 100644 --- a/config/helm/chart/default/values.yaml +++ b/config/helm/chart/default/values.yaml @@ -220,4 +220,7 @@ rbac: kspm: create: true annotations: {} + kubernetesMonitoringFull: + create: false + annotations: {} supportability: true From 49595b333464ade08a542b7b84c060261a556e9d Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Mon, 17 Mar 2025 13:17:22 +0100 Subject: [PATCH 323/426] Add bootstrapper (CSI-Driver variant) e2e test (#4599) --- doc/e2e/features.md | 36 ++++++++ hack/make/tests/e2e.mk | 4 + pkg/api/validation/dynakube/oneagent.go | 2 +- pkg/api/validation/dynakube/oneagent_test.go | 4 +- .../bootstrapper/node_image_pull_csi.go | 89 +++++++++++++++++++ .../cloudnative/codemodules/codemodules.go | 16 ++-- test/helpers/kubeobjects/job/get.go | 44 +++++++++ test/scenarios/standard/standard_test.go | 2 + 8 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 test/features/bootstrapper/node_image_pull_csi.go create mode 100644 test/helpers/kubeobjects/job/get.go diff --git a/doc/e2e/features.md b/doc/e2e/features.md index 9c40449062..7d3646db8c 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -79,6 +79,24 @@ func WithoutCSI(t *testing.T) features.Feature ApplicationMonitoring deployment without CSI driver +# bootstrapper + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/bootstrapper" +``` + +## Index + +- [func InstallWithCSI(t *testing.T) features.Feature](<#InstallWithCSI>) + + + +## func [InstallWithCSI]() + +```go +func InstallWithCSI(t *testing.T) features.Feature +``` + # classic ```go @@ -181,12 +199,22 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/codemo ## Index +- [func ImageHasBeenDownloaded(dk dynakube.DynaKube) features.Func](<#ImageHasBeenDownloaded>) - [func InstallFromImage(t *testing.T) features.Feature](<#InstallFromImage>) +- [func VolumesAreMountedCorrectly(sampleApp sample.App) features.Func](<#VolumesAreMountedCorrectly>) - [func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxy>) - [func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxyAndAGCert>) - [func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxyCA>) - [func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxyCAAndAGCert>) + + +## func [ImageHasBeenDownloaded]() + +```go +func ImageHasBeenDownloaded(dk dynakube.DynaKube) features.Func +``` + ## func [InstallFromImage]() @@ -197,6 +225,14 @@ func InstallFromImage(t *testing.T) features.Feature Verification that the storage in the CSI driver directory does not increase when there are multiple tenants and pods which are monitored. + + +## func [VolumesAreMountedCorrectly]() + +```go +func VolumesAreMountedCorrectly(sampleApp sample.App) features.Func +``` + ## func [WithProxy]() diff --git a/hack/make/tests/e2e.mk b/hack/make/tests/e2e.mk index 0b91e4e347..46f4d8047a 100644 --- a/hack/make/tests/e2e.mk +++ b/hack/make/tests/e2e.mk @@ -112,6 +112,10 @@ test/e2e/applicationmonitoring/readonlycsivolume: manifests/crd/helm test/e2e/applicationmonitoring/withoutcsi: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "app-monitoring-without-csi" $(SKIPCLEANUP) +## Runs Application Monitoring bootstrapper with CSI e2e test only +test/e2e/applicationmonitoring/bootstrapper-csi: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "node-image-pull-with-csi" $(SKIPCLEANUP) + ## Runs public registry images e2e test only test/e2e/publicregistry: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "public-registry-images" $(SKIPCLEANUP) diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index 445a6be76c..af718ea8ff 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -17,7 +17,7 @@ import ( const ( errorConflictingOneagentMode = `The DynaKube specification attempts to use multiple OneAgent modes simultaneously, which is not supported.` - errorImageFieldSetWithoutCSIFlag = `The DynaKube specification attempts to enable ApplicationMonitoring mode and retrieve the respective image, but the CSI driver and/or remote image download is not enabled.` + errorImageFieldSetWithoutCSIFlag = `The DynaKube specification attempts to enable ApplicationMonitoring mode and retrieve the respective image, but the CSI driver and/or node image pull is not enabled.` errorBootstrapperNodeImagePullRequiresCodeModulesImage = `The DynaKube specification enables node image pull, but the code modules image is not set.` diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index ad3b591d91..39f4172924 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -307,7 +307,7 @@ func TestImageFieldSetWithoutCSIFlag(t *testing.T) { }) }) - t.Run("spec with appMon enabled, csi driver not enabled but remote image download enabled and image set", func(t *testing.T) { + t.Run("spec with appMon enabled, csi driver not enabled but node image pull enabled and image set", func(t *testing.T) { setupDisabledCSIEnv(t) testImage := "testImage" @@ -332,7 +332,7 @@ func TestImageFieldSetWithoutCSIFlag(t *testing.T) { }) }) - t.Run("spec with appMon enabled, csi driver and remote image download not enabled and image set", func(t *testing.T) { + t.Run("spec with appMon enabled, csi driver and node image pull not enabled and image set", func(t *testing.T) { setupDisabledCSIEnv(t) testImage := "testImage" diff --git a/test/features/bootstrapper/node_image_pull_csi.go b/test/features/bootstrapper/node_image_pull_csi.go new file mode 100644 index 0000000000..f285068780 --- /dev/null +++ b/test/features/bootstrapper/node_image_pull_csi.go @@ -0,0 +1,89 @@ +//go:build e2e + +package bootstrapper + +import ( + "context" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/codemodules" + "github.com/Dynatrace/dynatrace-operator/test/helpers" + dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/job" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/namespace" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/pod" + "github.com/Dynatrace/dynatrace-operator/test/helpers/sample" + "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" + "github.com/stretchr/testify/require" + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" +) + +const ( + bootstrapperImage = "quay.io/dynatrace/dynatrace-bootstrapper:snapshot" +) + +func InstallWithCSI(t *testing.T) features.Feature { + builder := features.New("node-image-pull-with-csi") + secretConfig := tenant.GetSingleTenantSecret(t) + + appMonDynakube := *dynakubeComponents.New( + dynakubeComponents.WithName("app-codemodules"), + dynakubeComponents.WithApplicationMonitoringSpec(&oneagent.ApplicationMonitoringSpec{AppInjectionSpec: oneagent.AppInjectionSpec{CodeModulesImage: bootstrapperImage}}), + dynakubeComponents.WithAnnotations(map[string]string{dynakube.AnnotationFeatureNodeImagePull: "true"}), + dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), + ) + + sampleNamespace := *namespace.New("codemodules-sample-node-image-pull") + sampleApp := sample.NewApp(t, &appMonDynakube, + sample.AsDeployment(), + sample.WithNamespace(sampleNamespace), + ) + + builder.Assess("create sample namespace", sampleApp.InstallNamespace()) + + dynakubeComponents.Install(builder, helpers.LevelAssess, &secretConfig, appMonDynakube) + + builder.Assess("check if jobs completed", jobsAreCompleted(appMonDynakube)) + + builder.Assess("check if jobs got cleaned up", jobsAreCleanedUp(appMonDynakube)) + + builder.Assess("install sample app", sampleApp.Install()) + + builder.Assess("codemodules have been downloaded", codemodules.ImageHasBeenDownloaded(appMonDynakube)) + builder.Assess("volumes are mounted correctly", codemodules.VolumesAreMountedCorrectly(*sampleApp)) + + builder.Teardown(sampleApp.Uninstall()) + dynakubeComponents.Delete(builder, helpers.LevelTeardown, appMonDynakube) + + return builder.Feature() +} + +func jobsAreCompleted(dk dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + resource := envConfig.Client().Resources() + + jobList := job.GetJobsForOwner(ctx, t, resource, dk.Name, dk.Namespace) + require.NotEmpty(t, jobList.Items) + + for _, job := range jobList.Items { + t.Logf("waiting for job to be completed: %s", job.Name) + ctx = pod.WaitForPodsDeletionWithOwner(job.Name, job.Namespace)(ctx, t, envConfig) + } + + return ctx + } +} + +func jobsAreCleanedUp(dk dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + resource := envConfig.Client().Resources() + + jobList := job.GetJobsForOwner(ctx, t, resource, dk.Name, dk.Namespace) + require.Empty(t, jobList.Items) + + return ctx + } +} diff --git a/test/features/cloudnative/codemodules/codemodules.go b/test/features/cloudnative/codemodules/codemodules.go index 9e92b24305..cf241443a1 100644 --- a/test/features/cloudnative/codemodules/codemodules.go +++ b/test/features/cloudnative/codemodules/codemodules.go @@ -106,11 +106,11 @@ func InstallFromImage(t *testing.T) features.Feature { // Register actual test cloudnative.AssessSampleInitContainers(builder, sampleApp) - builder.Assess("codemodules have been downloaded", imageHasBeenDownloaded(cloudNativeDynakube)) + builder.Assess("codemodules have been downloaded", ImageHasBeenDownloaded(cloudNativeDynakube)) builder.Assess("checking storage used", measureDiskUsage(appDynakube.Namespace, storageMap)) dynakubeComponents.Install(builder, helpers.LevelAssess, &secretConfigs[1], appDynakube) builder.Assess("storage size has not increased", diskUsageDoesNotIncrease(appDynakube.Namespace, storageMap)) - builder.Assess("volumes are mounted correctly", volumesAreMountedCorrectly(*sampleApp)) + builder.Assess("volumes are mounted correctly", VolumesAreMountedCorrectly(*sampleApp)) // Register sample, dynakubeComponents and operator uninstall builder.Teardown(sampleApp.Uninstall()) @@ -170,7 +170,7 @@ func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature { // Register actual test cloudnative.AssessSampleInitContainers(builder, sampleApp) istio.AssessIstio(builder, cloudNativeDynakube, *sampleApp) - builder.Assess("codemodules have been downloaded", imageHasBeenDownloaded(cloudNativeDynakube)) + builder.Assess("codemodules have been downloaded", ImageHasBeenDownloaded(cloudNativeDynakube)) builder.Assess("check env variables of oneagent pods", checkOneAgentEnvVars(cloudNativeDynakube)) builder.Assess("check proxy settings in ruxitagentproc.conf", proxy.CheckRuxitAgentProcFileHasProxySetting(*sampleApp, proxySpec)) @@ -236,7 +236,7 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature { cloudnative.AssessSampleInitContainers(builder, sampleApp) istio.AssessIstio(builder, cloudNativeDynakube, *sampleApp) - builder.Assess("codemodules have been downloaded", imageHasBeenDownloaded(cloudNativeDynakube)) + builder.Assess("codemodules have been downloaded", ImageHasBeenDownloaded(cloudNativeDynakube)) agTlsSecret := corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -322,7 +322,7 @@ func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature cloudnative.AssessSampleInitContainers(builder, sampleApp) istio.AssessIstio(builder, cloudNativeDynakube, *sampleApp) - builder.Assess("codemodules have been downloaded", imageHasBeenDownloaded(cloudNativeDynakube)) + builder.Assess("codemodules have been downloaded", ImageHasBeenDownloaded(cloudNativeDynakube)) cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agCrt }, nil) cloudnative.AssessOneAgentContainer(builder, func() []byte { return agCrt }, nil) @@ -394,7 +394,7 @@ func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Featur cloudnative.AssessSampleInitContainers(builder, sampleApp) istio.AssessIstio(builder, cloudNativeDynakube, *sampleApp) - builder.Assess("codemodules have been downloaded", imageHasBeenDownloaded(cloudNativeDynakube)) + builder.Assess("codemodules have been downloaded", ImageHasBeenDownloaded(cloudNativeDynakube)) cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agCrt }, trustedCa) cloudnative.AssessOneAgentContainer(builder, func() []byte { return agCrt }, trustedCa) @@ -422,7 +422,7 @@ func codeModulesAppInjectSpec(t *testing.T) *oneagent.AppInjectionSpec { } } -func imageHasBeenDownloaded(dk dynakube.DynaKube) features.Func { +func ImageHasBeenDownloaded(dk dynakube.DynaKube) features.Func { return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { resource := envConfig.Client().Resources() clientset, err := kubernetes.NewForConfig(resource.GetConfig()) @@ -508,7 +508,7 @@ func getDiskUsage(ctx context.Context, t *testing.T, resource *resources.Resourc return diskUsage } -func volumesAreMountedCorrectly(sampleApp sample.App) features.Func { +func VolumesAreMountedCorrectly(sampleApp sample.App) features.Func { return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { resource := envConfig.Client().Resources() err := deployment.NewQuery(ctx, resource, client.ObjectKey{ diff --git a/test/helpers/kubeobjects/job/get.go b/test/helpers/kubeobjects/job/get.go new file mode 100644 index 0000000000..f483be173a --- /dev/null +++ b/test/helpers/kubeobjects/job/get.go @@ -0,0 +1,44 @@ +//go:build e2e + +package job + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + batchv1 "k8s.io/api/batch/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "sigs.k8s.io/e2e-framework/klient/k8s/resources" +) + +func GetJobsForOwner(ctx context.Context, t *testing.T, resource *resources.Resources, ownerName, namespace string) batchv1.JobList { + jobs := GetJobsForNamespace(ctx, t, resource, namespace) + + var targetJobs batchv1.JobList + for _, pod := range jobs.Items { + if len(pod.ObjectMeta.OwnerReferences) < 1 { + continue + } + + if pod.ObjectMeta.OwnerReferences[0].Name == ownerName { + targetJobs.Items = append(targetJobs.Items, pod) + } + } + + return targetJobs +} + +func GetJobsForNamespace(ctx context.Context, t *testing.T, resource *resources.Resources, namespace string) batchv1.JobList { + var jobs batchv1.JobList + err := resource.WithNamespace(namespace).List(ctx, &jobs) + + if err != nil { + if k8serrors.IsNotFound(err) { + err = nil + } + require.NoError(t, err) + } + + return jobs +} diff --git a/test/scenarios/standard/standard_test.go b/test/scenarios/standard/standard_test.go index 9f4dc37135..d9326695b2 100644 --- a/test/scenarios/standard/standard_test.go +++ b/test/scenarios/standard/standard_test.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/test/features/activegate" "github.com/Dynatrace/dynatrace-operator/test/features/applicationmonitoring" + "github.com/Dynatrace/dynatrace-operator/test/features/bootstrapper" "github.com/Dynatrace/dynatrace-operator/test/features/classic" classicToCloud "github.com/Dynatrace/dynatrace-operator/test/features/classic/switch_modes" "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/codemodules" @@ -64,6 +65,7 @@ func TestStandard(t *testing.T) { classic.Feature(t), classicToCloud.Feature(t), cloudToClassic.Feature(t), + bootstrapper.InstallWithCSI(t), } testEnv.Test(t, scenarios.FilterFeatures(*cfg, feats)...) From 2ffebfa095c1b9ed9399104d5618c3205bc2c9a2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 05:37:59 +0000 Subject: [PATCH 324/426] chore(deps): update golangci/golangci-lint-action action to v6.5.2 (main) (#4608) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 84dc0c02e0..54ead326cc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,7 +86,7 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint - uses: golangci/golangci-lint-action@4696ba8babb6127d732c3c6dde519db15edab9ea # v6.5.1 + uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2 with: # renovate depName=github.com/golangci/golangci-lint version: v1.64.7 From f960758fb42bb909c2208fc16e1ee02a31825a26 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 06:27:15 +0000 Subject: [PATCH 325/426] chore(deps): update module github.com/golangci/golangci-lint to v1.64.8 (main) (#4609) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- hack/make/prerequisites.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 54ead326cc..fbaca8e3de 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -89,7 +89,7 @@ jobs: uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2 with: # renovate depName=github.com/golangci/golangci-lint - version: v1.64.7 + version: v1.64.8 args: --build-tags e2e --timeout 300s --out-${NO_FUTURE}format colored-line-number - name: Run deadcode id: deadcode diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 8ca31e740e..acf413fb6b 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -3,7 +3,7 @@ kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.2 # renovate depName=github.com/golangci/golangci-lint -golang_ci_cmd_version=v1.64.7 +golang_ci_cmd_version=v1.64.8 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.5 # renovate depName=golang.org/x/tools From 92423de900473e2735f314da2df70d10e2568fe4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 08:23:24 +0000 Subject: [PATCH 326/426] fix(deps): update module go.opentelemetry.io/collector/component to v1.28.0 (main) (#4610) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index e1b5789e06..6901c61680 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/afero v1.14.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 - go.opentelemetry.io/collector/component v1.27.0 + go.opentelemetry.io/collector/component v1.28.0 go.opentelemetry.io/collector/confmap v1.27.0 go.opentelemetry.io/collector/pipeline v0.121.0 go.opentelemetry.io/collector/service v0.121.0 @@ -64,7 +64,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect @@ -117,7 +117,7 @@ require ( go.opentelemetry.io/collector/featuregate v1.27.0 // indirect go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0 // indirect go.opentelemetry.io/collector/internal/telemetry v0.121.0 // indirect - go.opentelemetry.io/collector/pdata v1.27.0 // indirect + go.opentelemetry.io/collector/pdata v1.28.0 // indirect go.opentelemetry.io/collector/pdata/pprofile v0.121.0 // indirect go.opentelemetry.io/collector/pdata/testdata v0.121.0 // indirect go.opentelemetry.io/collector/pipeline/xpipeline v0.121.0 // indirect @@ -130,7 +130,7 @@ require ( go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect go.opentelemetry.io/contrib/config v0.14.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect - go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect @@ -143,11 +143,11 @@ require ( go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect go.opentelemetry.io/otel/log v0.10.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect - go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sync v0.12.0 // indirect diff --git a/go.sum b/go.sum index b2d91f810e..77c2b5e68a 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76 github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -183,8 +183,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/collector v0.121.0 h1:K23nHTjhqKDOYpBUDyeK0/Yjzs5Py8Ysvec7zyKXuK0= go.opentelemetry.io/collector v0.121.0/go.mod h1:M4TlnmkjIgishm2DNCk9K3hMKTmAsY9w8cNFsp9EchM= -go.opentelemetry.io/collector/component v1.27.0 h1:6wk0K23YT9lSprX8BH9x5w8ssAORE109ekH/ix2S614= -go.opentelemetry.io/collector/component v1.27.0/go.mod h1:fIyBHoa7vDyZL3Pcidgy45cx24tBe7iHWne097blGgo= +go.opentelemetry.io/collector/component v1.28.0 h1:SQAGxxuyZ+d5tOsuEka8m9oE+wAroaYQpJ8NTIbl6Lk= +go.opentelemetry.io/collector/component v1.28.0/go.mod h1:te8gbcKU6Mgu7ewo/2VYDSbCkLrhOYYy2llayXCF0bI= go.opentelemetry.io/collector/component/componentstatus v0.121.0 h1:G4KqBUuAqnQ1kB3fUxXPwspjwnhGZzdArlO7vc343og= go.opentelemetry.io/collector/component/componentstatus v0.121.0/go.mod h1:ufRv8q15XNdbr9nNzdepMHlLl2aC3NHQgecCzp5VRns= go.opentelemetry.io/collector/component/componenttest v0.121.0 h1:4q1/7WnP9LPKaY4HAd8/OkzhllZpRACKAOlWsqbrzqc= @@ -231,8 +231,8 @@ go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0 h1:gefyTUyn1WHIPv go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0/go.mod h1:JM4FHRtacWUGEiZUpR2utoRfvgTdvYk+3OBJjyD9RzQ= go.opentelemetry.io/collector/internal/telemetry v0.121.0 h1:vSJg6eS2rpxL8gGFDQEO8OTsIYRO2sDKiyUyEHAFspU= go.opentelemetry.io/collector/internal/telemetry v0.121.0/go.mod h1:B8og4U7fKoCBrumTxSTr6PKbXDc1t9H1a8bKBcZjHQk= -go.opentelemetry.io/collector/pdata v1.27.0 h1:66yI7FYkUDia74h48Fd2/KG2Vk8DxZnGw54wRXykCEU= -go.opentelemetry.io/collector/pdata v1.27.0/go.mod h1:18e8/xDZsqyj00h/5HM5GLdJgBzzG9Ei8g9SpNoiMtI= +go.opentelemetry.io/collector/pdata v1.28.0 h1:xSZyvTOOc2Wmz4PoxrVqeQfodLgs9k7gowLAnzZN0eU= +go.opentelemetry.io/collector/pdata v1.28.0/go.mod h1:asKE8MD/4SOKz1mCrGdAz4VO2U2HUNg8A6094uK7pq0= go.opentelemetry.io/collector/pdata/pprofile v0.121.0 h1:DFBelDRsZYxEaSoxSRtseAazsHJfqfC/Yl64uPicl2g= go.opentelemetry.io/collector/pdata/pprofile v0.121.0/go.mod h1:j/fjrd7ybJp/PXkba92QLzx7hykUVmU8x/WJvI2JWSg= go.opentelemetry.io/collector/pdata/testdata v0.121.0 h1:FFz+rdb7o6JRZ82Zmp6WKEdKnEMaoF3jLb7F1F21ijg= @@ -263,8 +263,8 @@ go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0Lgyp go.opentelemetry.io/contrib/config v0.14.0/go.mod h1:77rDmFPqBae5jtQ2C78RuDTHz4P27C8LzoN0MZyumYQ= go.opentelemetry.io/contrib/propagators/b3 v1.34.0 h1:9pQdCEvV/6RWQmag94D6rhU+A4rzUhYBEJ8bpscx5p8= go.opentelemetry.io/contrib/propagators/b3 v1.34.0/go.mod h1:FwM71WS8i1/mAK4n48t0KU6qUS/OZRBgDrHZv3RlJ+w= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= @@ -289,16 +289,16 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= From b2d87b3065b9b72ac916835a8ce71d2c24dcc885 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 08:35:15 +0000 Subject: [PATCH 327/426] fix(deps): update module go.opentelemetry.io/collector/confmap to v1.28.0 (main) (#4611) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 6901c61680..aa5c17219d 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v1.28.0 - go.opentelemetry.io/collector/confmap v1.27.0 + go.opentelemetry.io/collector/confmap v1.28.0 go.opentelemetry.io/collector/pipeline v0.121.0 go.opentelemetry.io/collector/service v0.121.0 go.uber.org/zap v1.27.0 @@ -114,7 +114,7 @@ require ( go.opentelemetry.io/collector/extension v1.27.0 // indirect go.opentelemetry.io/collector/extension/extensioncapabilities v0.121.0 // indirect go.opentelemetry.io/collector/extension/extensiontest v0.121.0 // indirect - go.opentelemetry.io/collector/featuregate v1.27.0 // indirect + go.opentelemetry.io/collector/featuregate v1.28.0 // indirect go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0 // indirect go.opentelemetry.io/collector/internal/telemetry v0.121.0 // indirect go.opentelemetry.io/collector/pdata v1.28.0 // indirect diff --git a/go.sum b/go.sum index 77c2b5e68a..dfe62c1e60 100644 --- a/go.sum +++ b/go.sum @@ -193,8 +193,8 @@ go.opentelemetry.io/collector/config/configretry v1.27.0 h1:mM0X/7eiWRVmYTZJ5QTt go.opentelemetry.io/collector/config/configretry v1.27.0/go.mod h1:8gzFQ0qzKLYvzP2sNPwsB9gwzKSEls649yANmt/d6yE= go.opentelemetry.io/collector/config/configtelemetry v0.121.0 h1:0nEcLHRjr6E9P0LXhy7uluPpOw78YZ4N0t6pZJ5ug0g= go.opentelemetry.io/collector/config/configtelemetry v0.121.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= -go.opentelemetry.io/collector/confmap v1.27.0 h1:OIjPcjij1NxkVQsQVmHro4+t1eYNFiUGib9+J9YBZhM= -go.opentelemetry.io/collector/confmap v1.27.0/go.mod h1:tmOa6iw3FJsEgfBHKALqvcdfRtf71JZGor0wSM5MoH8= +go.opentelemetry.io/collector/confmap v1.28.0 h1:pUQh4eOW0YQ1GFWTDP5pw/ZMQuppkz6oSoDDloAH/Sc= +go.opentelemetry.io/collector/confmap v1.28.0/go.mod h1:k/3fo+2RE6m+OKlJzx78Q8hstABYwYgvXO3u9zyTeHI= go.opentelemetry.io/collector/confmap/xconfmap v0.121.0 h1:pZ7SOl/i3kUIPdUwIeHHsYqzOHNLCwiyXZnwQ7rLO3E= go.opentelemetry.io/collector/confmap/xconfmap v0.121.0/go.mod h1:YI1Sp8mbYro/H3rqH4csTq68VUuie5WVb7LI1o5+tVc= go.opentelemetry.io/collector/connector v0.121.0 h1:Bhre1CU8+nvXhOO74ZjCQth6JIwuRgGmUVFU5I6fDhY= @@ -225,8 +225,8 @@ go.opentelemetry.io/collector/extension/extensiontest v0.121.0 h1:ce3IEWXBDOOSlj go.opentelemetry.io/collector/extension/extensiontest v0.121.0/go.mod h1:yrZhZhf2a3aD0/17drjHnzSTlr0XnNREVrOLYBlcP1o= go.opentelemetry.io/collector/extension/xextension v0.121.0 h1:RIhFXwm9+2sc6H2PsM9asGfEBlIDBrK+dyyFMx257bs= go.opentelemetry.io/collector/extension/xextension v0.121.0/go.mod h1:EiGx9nRD/7TU4++2/f5+2wdxUnDvjINCpWKLgfF2JRA= -go.opentelemetry.io/collector/featuregate v1.27.0 h1:4LLrccoMz/gJT5uym8ojBlMzY5tr4RzUUXzwlBuiRz0= -go.opentelemetry.io/collector/featuregate v1.27.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= +go.opentelemetry.io/collector/featuregate v1.28.0 h1:nkaMw0HyOSxojLwlezF2O/xJ9T/Jo1a0iEetesT9lr0= +go.opentelemetry.io/collector/featuregate v1.28.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0 h1:gefyTUyn1WHIPvcPUB7LEbPEVj1VB2wqjh2cvxrMzVg= go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0/go.mod h1:JM4FHRtacWUGEiZUpR2utoRfvgTdvYk+3OBJjyD9RzQ= go.opentelemetry.io/collector/internal/telemetry v0.121.0 h1:vSJg6eS2rpxL8gGFDQEO8OTsIYRO2sDKiyUyEHAFspU= From d9939d39371cefd0046fe9ad55aa7e4046edaf74 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 08:51:30 +0000 Subject: [PATCH 328/426] fix(deps): update module go.opentelemetry.io/collector/pipeline to v0.122.0 (main) (#4612) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index aa5c17219d..9ed63a572c 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v1.28.0 go.opentelemetry.io/collector/confmap v1.28.0 - go.opentelemetry.io/collector/pipeline v0.121.0 + go.opentelemetry.io/collector/pipeline v0.122.0 go.opentelemetry.io/collector/service v0.121.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 diff --git a/go.sum b/go.sum index dfe62c1e60..3b16eb2156 100644 --- a/go.sum +++ b/go.sum @@ -237,8 +237,8 @@ go.opentelemetry.io/collector/pdata/pprofile v0.121.0 h1:DFBelDRsZYxEaSoxSRtseAa go.opentelemetry.io/collector/pdata/pprofile v0.121.0/go.mod h1:j/fjrd7ybJp/PXkba92QLzx7hykUVmU8x/WJvI2JWSg= go.opentelemetry.io/collector/pdata/testdata v0.121.0 h1:FFz+rdb7o6JRZ82Zmp6WKEdKnEMaoF3jLb7F1F21ijg= go.opentelemetry.io/collector/pdata/testdata v0.121.0/go.mod h1:UhiSwmVpBbuKlPdmhBytiVTHipSz/JO6c4mbD4kWOPg= -go.opentelemetry.io/collector/pipeline v0.121.0 h1:SOiocdyWCJCjWAb96HIxsy9enp2qyQ1NRFo26qyHlCE= -go.opentelemetry.io/collector/pipeline v0.121.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= +go.opentelemetry.io/collector/pipeline v0.122.0 h1:DmiNzhj2IPpL6JisPo0Hs8vyS5AsUz+GlPh5wblJmTk= +go.opentelemetry.io/collector/pipeline v0.122.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= go.opentelemetry.io/collector/pipeline/xpipeline v0.121.0 h1:Mkw2Jk43TK2hzY6nLy1koO1XD/KUj8nzK2FB+/WDxoM= go.opentelemetry.io/collector/pipeline/xpipeline v0.121.0/go.mod h1:nTfAnIPgIwevodUp9z0gwfl2S+lVEvz3CjhOqU/Lk/8= go.opentelemetry.io/collector/processor v0.121.0 h1:OcLrJ2F17cU0oDtXEYbGvL8vbku/kRQgAafSZ3+8jLY= From 48fe74f8e825c8427835aa6668aad8caff642015 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 09:17:50 +0000 Subject: [PATCH 329/426] fix(deps): update module go.opentelemetry.io/collector/service to v0.122.0 (main) (#4613) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 94 +++++++++++++------------- go.sum | 210 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 153 insertions(+), 151 deletions(-) diff --git a/go.mod b/go.mod index 9ed63a572c..e1d52338ca 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( go.opentelemetry.io/collector/component v1.28.0 go.opentelemetry.io/collector/confmap v1.28.0 go.opentelemetry.io/collector/pipeline v0.122.0 - go.opentelemetry.io/collector/service v0.121.0 + go.opentelemetry.io/collector/service v0.122.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.24.0 @@ -67,7 +67,7 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -98,55 +98,55 @@ require ( github.com/vladimirvivien/gexe v0.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/collector/component/componentstatus v0.121.0 // indirect - go.opentelemetry.io/collector/component/componenttest v0.121.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.121.0 // indirect - go.opentelemetry.io/collector/connector v0.121.0 // indirect - go.opentelemetry.io/collector/connector/connectortest v0.121.0 // indirect - go.opentelemetry.io/collector/connector/xconnector v0.121.0 // indirect - go.opentelemetry.io/collector/consumer v1.27.0 // indirect - go.opentelemetry.io/collector/consumer/consumererror v0.121.0 // indirect - go.opentelemetry.io/collector/consumer/consumertest v0.121.0 // indirect - go.opentelemetry.io/collector/consumer/xconsumer v0.121.0 // indirect - go.opentelemetry.io/collector/exporter v0.121.0 // indirect - go.opentelemetry.io/collector/exporter/exportertest v0.121.0 // indirect - go.opentelemetry.io/collector/exporter/xexporter v0.121.0 // indirect - go.opentelemetry.io/collector/extension v1.27.0 // indirect - go.opentelemetry.io/collector/extension/extensioncapabilities v0.121.0 // indirect - go.opentelemetry.io/collector/extension/extensiontest v0.121.0 // indirect + go.opentelemetry.io/collector/component/componentstatus v0.122.0 // indirect + go.opentelemetry.io/collector/component/componenttest v0.122.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.122.0 // indirect + go.opentelemetry.io/collector/connector v0.122.0 // indirect + go.opentelemetry.io/collector/connector/connectortest v0.122.0 // indirect + go.opentelemetry.io/collector/connector/xconnector v0.122.0 // indirect + go.opentelemetry.io/collector/consumer v1.28.0 // indirect + go.opentelemetry.io/collector/consumer/consumererror v0.122.0 // indirect + go.opentelemetry.io/collector/consumer/consumertest v0.122.0 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.122.0 // indirect + go.opentelemetry.io/collector/exporter v0.122.0 // indirect + go.opentelemetry.io/collector/exporter/exportertest v0.122.0 // indirect + go.opentelemetry.io/collector/exporter/xexporter v0.122.0 // indirect + go.opentelemetry.io/collector/extension v1.28.0 // indirect + go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.0 // indirect + go.opentelemetry.io/collector/extension/extensiontest v0.122.0 // indirect go.opentelemetry.io/collector/featuregate v1.28.0 // indirect - go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0 // indirect - go.opentelemetry.io/collector/internal/telemetry v0.121.0 // indirect + go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0 // indirect + go.opentelemetry.io/collector/internal/telemetry v0.122.0 // indirect go.opentelemetry.io/collector/pdata v1.28.0 // indirect - go.opentelemetry.io/collector/pdata/pprofile v0.121.0 // indirect - go.opentelemetry.io/collector/pdata/testdata v0.121.0 // indirect - go.opentelemetry.io/collector/pipeline/xpipeline v0.121.0 // indirect - go.opentelemetry.io/collector/processor v0.121.0 // indirect - go.opentelemetry.io/collector/processor/processortest v0.121.0 // indirect - go.opentelemetry.io/collector/processor/xprocessor v0.121.0 // indirect - go.opentelemetry.io/collector/receiver v0.121.0 // indirect - go.opentelemetry.io/collector/receiver/receivertest v0.121.0 // indirect - go.opentelemetry.io/collector/receiver/xreceiver v0.121.0 // indirect - go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect - go.opentelemetry.io/contrib/config v0.14.0 // indirect - go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.122.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.122.0 // indirect + go.opentelemetry.io/collector/pipeline/xpipeline v0.122.0 // indirect + go.opentelemetry.io/collector/processor v0.122.0 // indirect + go.opentelemetry.io/collector/processor/processortest v0.122.0 // indirect + go.opentelemetry.io/collector/processor/xprocessor v0.122.0 // indirect + go.opentelemetry.io/collector/receiver v1.28.0 // indirect + go.opentelemetry.io/collector/receiver/receivertest v0.122.0 // indirect + go.opentelemetry.io/collector/receiver/xreceiver v0.122.0 // indirect + go.opentelemetry.io/contrib/bridges/otelzap v0.10.0 // indirect + go.opentelemetry.io/contrib/otelconf v0.15.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.35.0 // indirect go.opentelemetry.io/otel v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.56.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect - go.opentelemetry.io/otel/log v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.57.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 // indirect + go.opentelemetry.io/otel/log v0.11.0 // indirect go.opentelemetry.io/otel/metric v1.35.0 // indirect - go.opentelemetry.io/otel/sdk v1.34.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect + go.opentelemetry.io/otel/sdk v1.35.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.11.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/go.sum b/go.sum index 3b16eb2156..24a7f0975e 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/container-storage-interface/spec v1.11.0 h1:H/YKTOeUZwHtyPOr9raR+HgFmGluGCklulxDYxSdVNM= @@ -75,8 +77,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -181,122 +183,122 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/collector v0.121.0 h1:K23nHTjhqKDOYpBUDyeK0/Yjzs5Py8Ysvec7zyKXuK0= -go.opentelemetry.io/collector v0.121.0/go.mod h1:M4TlnmkjIgishm2DNCk9K3hMKTmAsY9w8cNFsp9EchM= +go.opentelemetry.io/collector v0.122.0 h1:eir4Fvv2tz5tUvPBTvFk8VmqeihYcTuYD6AXllvxxIg= +go.opentelemetry.io/collector v0.122.0/go.mod h1:8t7TFg4nQHskvaOZrbfqAprB3r6+SZ2GQ2NYua0HEtg= go.opentelemetry.io/collector/component v1.28.0 h1:SQAGxxuyZ+d5tOsuEka8m9oE+wAroaYQpJ8NTIbl6Lk= go.opentelemetry.io/collector/component v1.28.0/go.mod h1:te8gbcKU6Mgu7ewo/2VYDSbCkLrhOYYy2llayXCF0bI= -go.opentelemetry.io/collector/component/componentstatus v0.121.0 h1:G4KqBUuAqnQ1kB3fUxXPwspjwnhGZzdArlO7vc343og= -go.opentelemetry.io/collector/component/componentstatus v0.121.0/go.mod h1:ufRv8q15XNdbr9nNzdepMHlLl2aC3NHQgecCzp5VRns= -go.opentelemetry.io/collector/component/componenttest v0.121.0 h1:4q1/7WnP9LPKaY4HAd8/OkzhllZpRACKAOlWsqbrzqc= -go.opentelemetry.io/collector/component/componenttest v0.121.0/go.mod h1:H7bEXDPMYNeWcHal0xyKlVfRPByVxale7hCJ+Myjq3Q= -go.opentelemetry.io/collector/config/configretry v1.27.0 h1:mM0X/7eiWRVmYTZJ5QTtly10uJWHnctIFuYST6tc/zU= -go.opentelemetry.io/collector/config/configretry v1.27.0/go.mod h1:8gzFQ0qzKLYvzP2sNPwsB9gwzKSEls649yANmt/d6yE= -go.opentelemetry.io/collector/config/configtelemetry v0.121.0 h1:0nEcLHRjr6E9P0LXhy7uluPpOw78YZ4N0t6pZJ5ug0g= -go.opentelemetry.io/collector/config/configtelemetry v0.121.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= +go.opentelemetry.io/collector/component/componentstatus v0.122.0 h1:gzqsfL8IN+bwlByl76MNFIDtq0jc9Y671NoZQGAiupg= +go.opentelemetry.io/collector/component/componentstatus v0.122.0/go.mod h1:d4WiL3UHQFIh7WN4miV5aupTZK3kFRt4xfzhsyTEMN4= +go.opentelemetry.io/collector/component/componenttest v0.122.0 h1:TxMm4nXB9iByQhDP0QFZwYxG+BFXEB6qUUwVh5YYW7g= +go.opentelemetry.io/collector/component/componenttest v0.122.0/go.mod h1:zzRftQeGgVPxKzXkJEx3ghC4U3hgiDRuuNljsq3cLPI= +go.opentelemetry.io/collector/config/configretry v1.28.0 h1:UqdSd+909bM9nC0eGcQvbTUdPQbEVJYDVjScFie5xFc= +go.opentelemetry.io/collector/config/configretry v1.28.0/go.mod h1:QNnb+MCk7aS1k2EuGJMtlNCltzD7b8uC7Xel0Dxm1wQ= +go.opentelemetry.io/collector/config/configtelemetry v0.122.0 h1:jBPdzU0CVrlxttnfKa0s2kyMVJeHY/faBht6/FUQcWI= +go.opentelemetry.io/collector/config/configtelemetry v0.122.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= go.opentelemetry.io/collector/confmap v1.28.0 h1:pUQh4eOW0YQ1GFWTDP5pw/ZMQuppkz6oSoDDloAH/Sc= go.opentelemetry.io/collector/confmap v1.28.0/go.mod h1:k/3fo+2RE6m+OKlJzx78Q8hstABYwYgvXO3u9zyTeHI= -go.opentelemetry.io/collector/confmap/xconfmap v0.121.0 h1:pZ7SOl/i3kUIPdUwIeHHsYqzOHNLCwiyXZnwQ7rLO3E= -go.opentelemetry.io/collector/confmap/xconfmap v0.121.0/go.mod h1:YI1Sp8mbYro/H3rqH4csTq68VUuie5WVb7LI1o5+tVc= -go.opentelemetry.io/collector/connector v0.121.0 h1:Bhre1CU8+nvXhOO74ZjCQth6JIwuRgGmUVFU5I6fDhY= -go.opentelemetry.io/collector/connector v0.121.0/go.mod h1:njtHMkFOuZ5W5Ax2BnsqC8EThgTU7tF1k7OBpRs0+uQ= -go.opentelemetry.io/collector/connector/connectortest v0.121.0 h1:3MhdOd5Sbd4kE/gjY8WDc0lb5Y2V1IEeYfRss8P5tnU= -go.opentelemetry.io/collector/connector/connectortest v0.121.0/go.mod h1:Xu4oO85n1yi2+7RNq0MzjW9LYeW17mXn5qmTe1o/al8= -go.opentelemetry.io/collector/connector/xconnector v0.121.0 h1:bWgg0zRD/pTeRZb5mhhOMZMuaru/txA5M8loCBOIPho= -go.opentelemetry.io/collector/connector/xconnector v0.121.0/go.mod h1:1Y/ypNTUkWEkm+nUP8mWKVMIRnQ/UPUuetp7RgnSfN0= -go.opentelemetry.io/collector/consumer v1.27.0 h1:JoXdoCeFDJG3d9TYrKHvTT4eBhzKXDVTkWW5mDfnLiY= -go.opentelemetry.io/collector/consumer v1.27.0/go.mod h1:1B/+kTDUI6u3mCIOAkm5ityIpv5uC0Ll78IA50SNZ24= -go.opentelemetry.io/collector/consumer/consumererror v0.121.0 h1:yFcCqi4Djhl2oUxYIyi5FAeLit/m1ah0sAokZKsP3zM= -go.opentelemetry.io/collector/consumer/consumererror v0.121.0/go.mod h1:kHrvHQ8AuWVjhSFixR51iEozdnoGkX6AjDWyhr3gSDo= -go.opentelemetry.io/collector/consumer/consumertest v0.121.0 h1:EIJPAXQY0w9j1k/e5OzJqOYVEr6WljKpJBjgkkp/hWw= -go.opentelemetry.io/collector/consumer/consumertest v0.121.0/go.mod h1:Hmj+TizzsLU0EmS2n/rJYScOybNmm3mrAjis6ed7qTw= -go.opentelemetry.io/collector/consumer/xconsumer v0.121.0 h1:/FJ7L6+G++FvktXc/aBnnYDIKLoYsWLh0pKbvzFFwF8= -go.opentelemetry.io/collector/consumer/xconsumer v0.121.0/go.mod h1:KKy8Qg/vOnyseoi7A9/x1a1oEqSmf0WBHkJFlnQH0Ow= -go.opentelemetry.io/collector/exporter v0.121.0 h1:HkE/qvnhmPtI/O/ITloukHFt4Ywmz6YzyWyWAqNGoKI= -go.opentelemetry.io/collector/exporter v0.121.0/go.mod h1:Xi4UtotE9QdA7UGkJVxHyg4grycYIKVDp/F+henuv3k= -go.opentelemetry.io/collector/exporter/exportertest v0.121.0 h1:kjtZwZd0Mj5VZv3JGxuQBnqmfmOCcCdhpz0G4INd6o0= -go.opentelemetry.io/collector/exporter/exportertest v0.121.0/go.mod h1:xGIi17/Ffteh308BRruHXVzq51o7wxYcUch0zXzyrqA= -go.opentelemetry.io/collector/exporter/xexporter v0.121.0 h1:e5QIl51EutJrH8X4tfnQUgfz1ebXPlLUzTltlT40IAc= -go.opentelemetry.io/collector/exporter/xexporter v0.121.0/go.mod h1:PGrW5pOQkNpaz8xqtkITCNEkcJVxOHSptg2chVTtv+o= -go.opentelemetry.io/collector/extension v1.27.0 h1:7F+O8/+bcwo3Zk3B/+H8A75cz9dhqXUrbeiyiFajoy4= -go.opentelemetry.io/collector/extension v1.27.0/go.mod h1:Fe0nUGMcr0c6IIBD3QEa3XmdUYpfmm5wCjc3PYho8DM= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.121.0 h1:Xj9UY6KCfydV1RfPi3ycR94pQSoN4oT9b0rdwsDDOGg= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.121.0/go.mod h1:Wz7FanSxDq2aCbclOfqXTAm5CvWJCWeXzO6quzAGG04= -go.opentelemetry.io/collector/extension/extensiontest v0.121.0 h1:ce3IEWXBDOOSljd0niVbwHs7AhC8hOjC2RXGIoMOXog= -go.opentelemetry.io/collector/extension/extensiontest v0.121.0/go.mod h1:yrZhZhf2a3aD0/17drjHnzSTlr0XnNREVrOLYBlcP1o= -go.opentelemetry.io/collector/extension/xextension v0.121.0 h1:RIhFXwm9+2sc6H2PsM9asGfEBlIDBrK+dyyFMx257bs= -go.opentelemetry.io/collector/extension/xextension v0.121.0/go.mod h1:EiGx9nRD/7TU4++2/f5+2wdxUnDvjINCpWKLgfF2JRA= +go.opentelemetry.io/collector/confmap/xconfmap v0.122.0 h1:uRwR2/DEhLCwsdQyD5rTG/cAPUm5ixZb96y3rUaUo/g= +go.opentelemetry.io/collector/confmap/xconfmap v0.122.0/go.mod h1:76K9ypccfRyorlYYit8O82mX4hseQP8VJ/TYqCKI4fA= +go.opentelemetry.io/collector/connector v0.122.0 h1:VrILgvrE4PWuJzPfB2lj+wxqRK8+SnnFFB9Ft9G1Tok= +go.opentelemetry.io/collector/connector v0.122.0/go.mod h1:ppWh+4gDym2C/zZ4ygID7DMZxVJyyvy1is415attDjA= +go.opentelemetry.io/collector/connector/connectortest v0.122.0 h1:7kwexYryefADAP/eG9v3ycqIxgQh6qgmMlsjkgcBW34= +go.opentelemetry.io/collector/connector/connectortest v0.122.0/go.mod h1:UxShMFmkmjwimWqlkRiDoVxyYMxk3ZQaoWsWb7Oe9is= +go.opentelemetry.io/collector/connector/xconnector v0.122.0 h1:D0e/ZbDhIJA8harTulMilhSG/yqQmi/k/yaLbGiPeH8= +go.opentelemetry.io/collector/connector/xconnector v0.122.0/go.mod h1:gjFaSA5EZxOqzhoLrcf7Pj+U4sB60GcKIZYGaNvQ1jQ= +go.opentelemetry.io/collector/consumer v1.28.0 h1:3JzDm7EFAF9ws4O3vVou5n8egdGZtrRN3xVw6AjNtqE= +go.opentelemetry.io/collector/consumer v1.28.0/go.mod h1:Ge1HGm5aRYTW+SXggM+US9phb/BQR2of4FZ8r/3OH3Y= +go.opentelemetry.io/collector/consumer/consumererror v0.122.0 h1:IoCEQE0xqNVsH7wOwmBBLR0W/+p8QFjYwNlZTrhztvM= +go.opentelemetry.io/collector/consumer/consumererror v0.122.0/go.mod h1:8RPibMrh84PHzqGchjiKIRz4eqdylMg8boLwMJY3WjU= +go.opentelemetry.io/collector/consumer/consumertest v0.122.0 h1:nV/qmUNRJZX+Eof963k+ShYy06DtQxMvP62nrXM8JJk= +go.opentelemetry.io/collector/consumer/consumertest v0.122.0/go.mod h1:D7qDviTkrXfYigmSF4A8K7vQtb5ec/TVJsCNlVLIhxY= +go.opentelemetry.io/collector/consumer/xconsumer v0.122.0 h1:7IyhI81BOf0YfsoI83/s7/muf7frkmgiX/FsFfZApq0= +go.opentelemetry.io/collector/consumer/xconsumer v0.122.0/go.mod h1:+kN4ZwuJTLlLdtH+DkUyXqT/zQFMktbWFIdVqfmSWRY= +go.opentelemetry.io/collector/exporter v0.122.0 h1:Y1ZigdLwHrN1/VA+P3lYrnM2gAmo/tQxHVxdfg+489U= +go.opentelemetry.io/collector/exporter v0.122.0/go.mod h1:xtoCOeeGpZgcvMX8Od+HLBgDGqUstIii/NQXXjEkNR0= +go.opentelemetry.io/collector/exporter/exportertest v0.122.0 h1:NfhUI8OocfhLCpIuNlS9yx1Lt/Vmmn97Z8JnId+qVKw= +go.opentelemetry.io/collector/exporter/exportertest v0.122.0/go.mod h1:1ntDyuDvpiqJH/YyQ4uvfePESaJm0g2D77syBkLAmmg= +go.opentelemetry.io/collector/exporter/xexporter v0.122.0 h1:fd+IEFSNZoUa/3Z8eNLPKqOkeh7nEV6qTlqoFzt+uD0= +go.opentelemetry.io/collector/exporter/xexporter v0.122.0/go.mod h1:pRqtMIBLcnUsyMwaIjUz//0fKWj+9VXOA+tUGnS9DDQ= +go.opentelemetry.io/collector/extension v1.28.0 h1:E3j6/EtcahF2bX9DvRduLQ6tD7SuZdXM9DzAi7NSAeY= +go.opentelemetry.io/collector/extension v1.28.0/go.mod h1:3MW9IGCNNgjG/ngkALVH5epwbCwYuoZMTbh4523aYv0= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.0 h1:ecxODEslQT87P82n1bWzVaVyj57OAwxh56RxLL1fyxc= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.0/go.mod h1:0Sl5KgS06MdhvFog9JOHLl8SnZLmDQwgcA0IhYoAuxo= +go.opentelemetry.io/collector/extension/extensiontest v0.122.0 h1:daeCPXhb4HveyeYyX6G0IqjGuvWJprZeiq7pZiSdC+M= +go.opentelemetry.io/collector/extension/extensiontest v0.122.0/go.mod h1:JXSONLbyuX+uOy1gcQ3Jcp/48pfkh0RiZPy7XkyCBdU= +go.opentelemetry.io/collector/extension/xextension v0.122.0 h1:EoPcWm69j0OZCyKvZ0H0KfkLRKZyry678852ua7k+DI= +go.opentelemetry.io/collector/extension/xextension v0.122.0/go.mod h1:hdkdi0cGk3X1+9M0IS1LJ8dhlnEKhqHd2HMdc2ata5A= go.opentelemetry.io/collector/featuregate v1.28.0 h1:nkaMw0HyOSxojLwlezF2O/xJ9T/Jo1a0iEetesT9lr0= go.opentelemetry.io/collector/featuregate v1.28.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0 h1:gefyTUyn1WHIPvcPUB7LEbPEVj1VB2wqjh2cvxrMzVg= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.121.0/go.mod h1:JM4FHRtacWUGEiZUpR2utoRfvgTdvYk+3OBJjyD9RzQ= -go.opentelemetry.io/collector/internal/telemetry v0.121.0 h1:vSJg6eS2rpxL8gGFDQEO8OTsIYRO2sDKiyUyEHAFspU= -go.opentelemetry.io/collector/internal/telemetry v0.121.0/go.mod h1:B8og4U7fKoCBrumTxSTr6PKbXDc1t9H1a8bKBcZjHQk= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0 h1:Oup8r2FaIEi7si3Kz7ybSgeNh6TrQFNJ9I7bNNdgJ0o= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0/go.mod h1:02AWRtzi/v9P2ldMdQq5+OKKoqIVPdqZQ/B3KKNu/So= +go.opentelemetry.io/collector/internal/telemetry v0.122.0 h1:5RCl/CdT3+VaduRI5IphoH3xS49sHZmEY/y3N3CEZjs= +go.opentelemetry.io/collector/internal/telemetry v0.122.0/go.mod h1:FrmVXPmQMn3BuGIWg/pOdmHTMvXmlNzcbMusn8SSZn4= go.opentelemetry.io/collector/pdata v1.28.0 h1:xSZyvTOOc2Wmz4PoxrVqeQfodLgs9k7gowLAnzZN0eU= go.opentelemetry.io/collector/pdata v1.28.0/go.mod h1:asKE8MD/4SOKz1mCrGdAz4VO2U2HUNg8A6094uK7pq0= -go.opentelemetry.io/collector/pdata/pprofile v0.121.0 h1:DFBelDRsZYxEaSoxSRtseAazsHJfqfC/Yl64uPicl2g= -go.opentelemetry.io/collector/pdata/pprofile v0.121.0/go.mod h1:j/fjrd7ybJp/PXkba92QLzx7hykUVmU8x/WJvI2JWSg= -go.opentelemetry.io/collector/pdata/testdata v0.121.0 h1:FFz+rdb7o6JRZ82Zmp6WKEdKnEMaoF3jLb7F1F21ijg= -go.opentelemetry.io/collector/pdata/testdata v0.121.0/go.mod h1:UhiSwmVpBbuKlPdmhBytiVTHipSz/JO6c4mbD4kWOPg= +go.opentelemetry.io/collector/pdata/pprofile v0.122.0 h1:JcmYBmNNOKRO7mIBxJ79YKgrTowILCCcpxKorDBfFOs= +go.opentelemetry.io/collector/pdata/pprofile v0.122.0/go.mod h1:miIYvmTQov3C2/D7T0nRMndhavG4tPqz3llKMdLjSwg= +go.opentelemetry.io/collector/pdata/testdata v0.122.0 h1:ANXZ+h9yAy1N37ot407qnMtISjZIgjYk10atzD7wSKI= +go.opentelemetry.io/collector/pdata/testdata v0.122.0/go.mod h1:5WxeLDGisczRoS5lnxyt0PqGI3tr2QnhxUHupGrDY64= go.opentelemetry.io/collector/pipeline v0.122.0 h1:DmiNzhj2IPpL6JisPo0Hs8vyS5AsUz+GlPh5wblJmTk= go.opentelemetry.io/collector/pipeline v0.122.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= -go.opentelemetry.io/collector/pipeline/xpipeline v0.121.0 h1:Mkw2Jk43TK2hzY6nLy1koO1XD/KUj8nzK2FB+/WDxoM= -go.opentelemetry.io/collector/pipeline/xpipeline v0.121.0/go.mod h1:nTfAnIPgIwevodUp9z0gwfl2S+lVEvz3CjhOqU/Lk/8= -go.opentelemetry.io/collector/processor v0.121.0 h1:OcLrJ2F17cU0oDtXEYbGvL8vbku/kRQgAafSZ3+8jLY= -go.opentelemetry.io/collector/processor v0.121.0/go.mod h1:BoFEMvPn5/p53eWz+R9cibIxCXzaRZ/RtcBPtvqXNaQ= -go.opentelemetry.io/collector/processor/processortest v0.121.0 h1:1c3mEABELrxdC1obSQjIlfh5jZljJlzUravmzy1Mofo= -go.opentelemetry.io/collector/processor/processortest v0.121.0/go.mod h1:oL4S/eguZ6XTK6IxAQXhXD9yWuRrG5/Maiskbf9HL0o= -go.opentelemetry.io/collector/processor/xprocessor v0.121.0 h1:AiqDKzpEYZpiP9y3RRp4G9ym6fG2f9HByu3yWkSdd2E= -go.opentelemetry.io/collector/processor/xprocessor v0.121.0/go.mod h1:Puk+6YYKyqLVKqpftUXg0blMrd3BlH/Av+oiajp1sHQ= -go.opentelemetry.io/collector/receiver v0.121.0 h1:gQGAiSXX5ZjAqb3fZVlZc4DjT90at/HmnKzNG/XIdZw= -go.opentelemetry.io/collector/receiver v0.121.0/go.mod h1:CqvQRwGGOqq6PRI6qmkKzF7AYWwRZTpCX6w7U3wIAmQ= -go.opentelemetry.io/collector/receiver/receivertest v0.121.0 h1:kdwV0tkaawRwKoZ1hl2xeYo4Oqfoa5drNX5I2J+rKhk= -go.opentelemetry.io/collector/receiver/receivertest v0.121.0/go.mod h1:H7N4CLG4J8Do3NWeo9gj7VmJCtDstDeeCffPBgHu1WQ= -go.opentelemetry.io/collector/receiver/xreceiver v0.121.0 h1:F6IVdEArgicLVtDtZ2Ovmjv8o6+3AyxYaC3HdNIbakM= -go.opentelemetry.io/collector/receiver/xreceiver v0.121.0/go.mod h1:ZsI1dzGq9J8y0f8h8MYYnoyC8SRJ5u1OqVRX2EwdZwo= -go.opentelemetry.io/collector/semconv v0.121.0 h1:dtdgh5TsKWGZXIBMsyCMVrY1VgmyWlXHgWx/VH9tL1U= -go.opentelemetry.io/collector/semconv v0.121.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= -go.opentelemetry.io/collector/service v0.121.0 h1:fh4pTRwYfsmXry2tc03eIbchEQUE3KGbRn0d/0IghMI= -go.opentelemetry.io/collector/service v0.121.0/go.mod h1:39g0114ia8bxz/MnlJk12DvAJuIQKijFJg7PdD0ydQw= -go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25PkeyWmOcI+SjXWguNw= -go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= -go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= -go.opentelemetry.io/contrib/config v0.14.0/go.mod h1:77rDmFPqBae5jtQ2C78RuDTHz4P27C8LzoN0MZyumYQ= -go.opentelemetry.io/contrib/propagators/b3 v1.34.0 h1:9pQdCEvV/6RWQmag94D6rhU+A4rzUhYBEJ8bpscx5p8= -go.opentelemetry.io/contrib/propagators/b3 v1.34.0/go.mod h1:FwM71WS8i1/mAK4n48t0KU6qUS/OZRBgDrHZv3RlJ+w= +go.opentelemetry.io/collector/pipeline/xpipeline v0.122.0 h1:Zu6zvO/6epvsjZ74t7qAiMowqhScxHZURlBzBaJ00iY= +go.opentelemetry.io/collector/pipeline/xpipeline v0.122.0/go.mod h1:uBWsvO37xU8cPgG8znDMW7bIwzrwRQ0jQ0u05rFeB/g= +go.opentelemetry.io/collector/processor v0.122.0 h1:elkgJhXhzwrvycbMGQzLOGNwGURaQZNAx1VB8lh9uq8= +go.opentelemetry.io/collector/processor v0.122.0/go.mod h1:jWan7IwasdpUA9GQGyicw5MDJOfqoiTnez+xkT7GCu8= +go.opentelemetry.io/collector/processor/processortest v0.122.0 h1:UHJwvmIzGoi6U4p6UyaZUGOI3lx1seHh1b+ukVyZ3Wg= +go.opentelemetry.io/collector/processor/processortest v0.122.0/go.mod h1:iK3qMnIkby7f0QCz0876mD7Wpuhxertg6zvZL5lRtdI= +go.opentelemetry.io/collector/processor/xprocessor v0.122.0 h1:hXl4Ttp1Ycqf2rIDQnIW9bMmq01sF2Jb+aEWJ7rtaDU= +go.opentelemetry.io/collector/processor/xprocessor v0.122.0/go.mod h1:Kh9zGutW9Smqsi+FWimlTmLl9czi6WgG7JclMB44sqA= +go.opentelemetry.io/collector/receiver v1.28.0 h1:yvAUb+QTdkhIuUVY5wGUPyXqIylIttGpt+k+1b77jic= +go.opentelemetry.io/collector/receiver v1.28.0/go.mod h1:ceNMHvsSkFOHK80UkQd5kdrU3Qq7NA+dS7oc6C4zLRc= +go.opentelemetry.io/collector/receiver/receivertest v0.122.0 h1:qBy1XbddIQRvslmS1WXhTnjzOIwuLBTbp8CGN8atNKk= +go.opentelemetry.io/collector/receiver/receivertest v0.122.0/go.mod h1:zuB9o86N1UFgauDS9cHT8vHWQVggNRcyinwRZZv5Z9A= +go.opentelemetry.io/collector/receiver/xreceiver v0.122.0 h1:rAWEMR/TDu+a9ATGIec4m9swVT0KvimUQqZpOLgTCVM= +go.opentelemetry.io/collector/receiver/xreceiver v0.122.0/go.mod h1:LLMY2gDtQCieYEOa5h6heHv+FMkC+b1u/yUXRJvwrEo= +go.opentelemetry.io/collector/semconv v0.122.0 h1:MsPT+/vmQ1iVc4wEVgyRIxi4Pc0KUxc/mjoJsPrfH0k= +go.opentelemetry.io/collector/semconv v0.122.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= +go.opentelemetry.io/collector/service v0.122.0 h1:OPDNiuGTHYj0B3ozeC5IV6wNDmgp0j2RlyEsPbSS0o0= +go.opentelemetry.io/collector/service v0.122.0/go.mod h1:ffOT//Aa8i/cg3Vy//BeqKV9W7EYJ06n0MmrY2h/7C0= +go.opentelemetry.io/contrib/bridges/otelzap v0.10.0 h1:ojdSRDvjrnm30beHOmwsSvLpoRF40MlwNCA+Oo93kXU= +go.opentelemetry.io/contrib/bridges/otelzap v0.10.0/go.mod h1:oTTm4g7NEtHSV2i/0FeVdPaPgUIZPfQkFbq0vbzqnv0= +go.opentelemetry.io/contrib/otelconf v0.15.0 h1:BLNiIUsrNcqhSKpsa6CnhE6LdrpY1A8X0szMVsu99eo= +go.opentelemetry.io/contrib/otelconf v0.15.0/go.mod h1:OPH1seO5z9dp1P26gnLtoM9ht7JDvh3Ws6XRHuXqImY= +go.opentelemetry.io/contrib/propagators/b3 v1.35.0 h1:DpwKW04LkdFRFCIgM3sqwTJA/QREHMeMHYPWP1WeaPQ= +go.opentelemetry.io/contrib/propagators/b3 v1.35.0/go.mod h1:9+SNxwqvCWo1qQwUpACBY5YKNVxFJn5mlbXg/4+uKBg= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0/go.mod h1:leO2CSTg0Y+LyvmR7Wm4pUxE8KAmaM2GCVx7O+RATLA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 h1:opwv08VbCZ8iecIWs+McMdHRcAXzjAeda3uG2kI/hcA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0/go.mod h1:oOP3ABpW7vFHulLpE8aYtNBodrHhMTrvfxUXGvqm7Ac= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= -go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E= -go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 h1:GKCEAZLEpEf78cUvudQdTg0aET2ObOZRB2HtXA0qPAI= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0/go.mod h1:9/zqSWLCmHT/9Jo6fYeUDRRogOLL60ABLsHWS99lF8s= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 h1:czJDQwFrMbOr9Kk+BPo1y8WZIIFIK58SA1kykuVeiOU= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0/go.mod h1:lT7bmsxOe58Tq+JIOkTQMCGXdu47oA+VJKLZHbaBKbs= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= -go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= -go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0 h1:HMUytBT3uGhPKYY/u/G5MR9itrlSO2SMOsSD3Tk3k7A= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0/go.mod h1:hdDXsiNLmdW/9BF2jQpnHHlhFajpWCEYfM6e5m2OAZg= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 h1:C/Wi2F8wEmbxJ9Kuzw/nhP+Z9XaHYMkyDmXy6yR2cjw= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0/go.mod h1:0Lr9vmGKzadCTgsiBydxr6GEZ8SsZ7Ks53LzjWG5Ar4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 h1:0NIXxOCFx+SKbhCVxwl3ETG8ClLPAa0KuKV6p3yhxP8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0/go.mod h1:ChZSJbbfbl/DcRZNc9Gqh6DYGlfjw4PvO1pEOZH1ZsE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/prometheus v0.57.0 h1:AHh/lAP1BHrY5gBwk8ncc25FXWm/gmmY3BX258z5nuk= +go.opentelemetry.io/otel/exporters/prometheus v0.57.0/go.mod h1:QpFWz1QxqevfjwzYdbMb4Y1NnlJvqSGwyuU0B4iuc9c= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0 h1:k6KdfZk72tVW/QVZf60xlDziDvYAePj5QHwoQvrB2m8= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0/go.mod h1:5Y3ZJLqzi/x/kYtrSrPSx7TFI/SGsL7q2kME027tH6I= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 h1:PB3Zrjs1sG1GBX51SXyTSoOTqcDglmsk7nT6tkKPb/k= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0/go.mod h1:U2R3XyVPzn0WX7wOIypPuptulsMcPDPs/oiSVOMVnHY= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= +go.opentelemetry.io/otel/log v0.11.0 h1:c24Hrlk5WJ8JWcwbQxdBqxZdOK7PcP/LFtOtwpDTe3Y= +go.opentelemetry.io/otel/log v0.11.0/go.mod h1:U/sxQ83FPmT29trrifhQg+Zj2lo1/IPN1PF6RTFqdwc= go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= -go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= -go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= -go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= +go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk/log v0.11.0 h1:7bAOpjpGglWhdEzP8z0VXc4jObOiDEwr3IYbhBnjk2c= +go.opentelemetry.io/otel/sdk/log v0.11.0/go.mod h1:dndLTxZbwBstZoqsJB3kGsRPkpAgaJrWfQg3lhlHFFY= +go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= +go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= From 25232dc96b26b020c8e39cd4f6e8a2a35c98eda9 Mon Sep 17 00:00:00 2001 From: Christoph Muellner <33160506+chrismuellner@users.noreply.github.com> Date: Tue, 18 Mar 2025 10:42:05 +0100 Subject: [PATCH 330/426] Update dynakube samples to include optional fields (#4605) --- .../v1beta4/applicationMonitoring.yaml | 161 +++++++++++- .../dynakube/v1beta4/classicFullStack.yaml | 201 ++++++++++++++- .../v1beta4/cloudNativeFullStack.yaml | 241 +++++++++++++++++- .../dynakube/v1beta4/hostMonitoring.yaml | 217 +++++++++++++++- .../v1beta4/kubernetesObservability.yaml | 127 ++++++++- .../kubernetesSecurityPostureManagement.yaml | 186 +++++++++++++- .../dynakube/v1beta4/logMonitoring.yaml | 202 ++++++++++++++- 7 files changed, 1305 insertions(+), 30 deletions(-) diff --git a/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml b/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml index b77a74f4a8..a17d25df43 100644 --- a/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml @@ -4,15 +4,174 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for OneAgent + # oneAgent: + # Optional: Set a host group for OneAgent. + # + # hostGroup: "" + applicationMonitoring: {} + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Optional: The OneAgent version to be used. + # Example: ..., e.g. 1.200.0.20240101-000000 + # + # version: "" + + # Optional: Define resources requests and limits for the initContainer. + # + # initResources: + # requests: + # cpu: 30m + # memory: 30Mi + # limits: + # cpu: 100m + # memory: 60Mi + # Optional: The OneAgent image that is used to inject into pods + # + # codeModulesImage: "" + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - routing - kubernetes-monitoring - dynatrace-api + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta4/classicFullStack.yaml b/assets/samples/dynakube/v1beta4/classicFullStack.yaml index d0a9cddde5..160e61201e 100644 --- a/assets/samples/dynakube/v1beta4/classicFullStack.yaml +++ b/assets/samples/dynakube/v1beta4/classicFullStack.yaml @@ -4,15 +4,212 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for OneAgent + # oneAgent: - classicFullStack: {} + # Optional: Set a host group for OneAgent. + # + # hostGroup: "" + + classicFullStack: + # Optional: Specify the node selector that controls on which nodes OneAgent will be deployed. + # + # nodeSelector: {} + + # Optional: Assign a priority class to the OneAgent pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the OneAgent DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for OneAgent container. + # + # oneAgentResources: + # requests: + # cpu: 100m + # memory: 512Mi + # limits: + # cpu: 300m + # memory: 1.5Gi + + # Optional: Set additional arguments to the OneAgent installer. + # + # args: [] + + # Optional: Set additional environment variables for the OneAgent pods. + # + # env: [] + + # Optional: Disable automatic restarts of OneAgent pods in case a new version is available + # + # autoUpdate: true + + # Optional: Set the DNS Policy for OneAgent pods. + # + # dnsPolicy: "ClusterFirstWithHostNet" + # Optional: Add custom OneAgent annotations. + # + # annotations: + # custom: annotation + + # Optional: Add custom labels to OneAgent pods + # + # labels: + # custom: label + + # Optional: Use a custom OneAgent image. + # + # image: "" + + # Optional: The OneAgent version to be used. + # Example: ..., e.g. 1.200.0.20240101-000000 + # + # version: "" + + # Optional: The SecComp Profile that will be configured in order to run in secure computing mode. + # + # secCompProfile: "" + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - routing - kubernetes-monitoring - dynatrace-api + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml b/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml index e8b2c506fe..58ee638c71 100644 --- a/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml +++ b/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml @@ -4,15 +4,252 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for Log monitoring. + # + # logMonitoring: {} + # Optional: Specifies the rules and conditions for matching ingest attributes. + # + # ingestRuleMatchers: + # - attribute: "k8s.namespace.name" + # values: + # - "kube-system" + # - "dynatrace" + # - "default" + # - attribute: "k8s.pod.annotation", + # values: + # - "logs.dynatrace.com/ingest=true" + # - "category=security" + + # Configuration for OneAgent + # oneAgent: - cloudNativeFullStack: {} + # Optional: Set a host group for OneAgent. + # + # hostGroup: "" + + cloudNativeFullStack: + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Optional: Specify the node selector that controls on which nodes OneAgent will be deployed. + # + # nodeSelector: {} + + # Optional: Assign a priority class to the OneAgent pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the OneAgent DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for OneAgent container. + # + # oneAgentResources: + # requests: + # cpu: 100m + # memory: 512Mi + # limits: + # cpu: 300m + # memory: 1.5Gi + + # Optional: Set additional arguments to the OneAgent installer. + # + # args: [] + + # Optional: Set additional environment variables for the OneAgent pods. + # + # env: [] + + # Optional: Disable automatic restarts of OneAgent pods in case a new version is available + # + # autoUpdate: true + + # Optional: Set the DNS Policy for OneAgent pods. + # + # dnsPolicy: "ClusterFirstWithHostNet" + # Optional: Add custom OneAgent annotations. + # + # annotations: + # custom: annotation + + # Optional: Add custom labels to OneAgent pods + # + # labels: + # custom: label + + # Optional: Use a custom OneAgent image. + # + # image: "" + + # Optional: The OneAgent version to be used. + # Example: ..., e.g. 1.200.0.20240101-000000 + # + # version: "" + + # Optional: Define resources requests and limits for the initContainer. + # + # initResources: + # requests: + # cpu: 30m + # memory: 30Mi + # limits: + # cpu: 100m + # memory: 60Mi + + # Optional: The OneAgent image that is used to inject into pods + # + # codeModulesImage: "" + + # Optional: The SecComp Profile that will be configured in order to run in secure computing mode. + # + # secCompProfile: "" + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - routing - kubernetes-monitoring - dynatrace-api + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta4/hostMonitoring.yaml b/assets/samples/dynakube/v1beta4/hostMonitoring.yaml index 6dcbde71c1..9ae817f2ae 100644 --- a/assets/samples/dynakube/v1beta4/hostMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/hostMonitoring.yaml @@ -4,15 +4,228 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for Log monitoring. + # + # logMonitoring: {} + # Optional: Specifies the rules and conditions for matching ingest attributes. + # + # ingestRuleMatchers: + # - attribute: "k8s.namespace.name" + # values: + # - "kube-system" + # - "dynatrace" + # - "default" + # - attribute: "k8s.pod.annotation", + # values: + # - "logs.dynatrace.com/ingest=true" + # - "category=security" + + # Configuration for OneAgent + # oneAgent: - hostMonitoring: {} + # Optional: Set a host group for OneAgent. + # + # hostGroup: "" + + hostMonitoring: + # Optional: Specify the node selector that controls on which nodes OneAgent will be deployed. + # + # nodeSelector: {} + + # Optional: Assign a priority class to the OneAgent pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the OneAgent DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for OneAgent container. + # + # oneAgentResources: + # requests: + # cpu: 100m + # memory: 512Mi + # limits: + # cpu: 300m + # memory: 1.5Gi + + # Optional: Set additional arguments to the OneAgent installer. + # + # args: [] + + # Optional: Set additional environment variables for the OneAgent pods. + # + # env: [] + + # Optional: Disable automatic restarts of OneAgent pods in case a new version is available + # + # autoUpdate: true + # Optional: Set the DNS Policy for OneAgent pods. + # + # dnsPolicy: "ClusterFirstWithHostNet" + + # Optional: Add custom OneAgent annotations. + # + # annotations: + # custom: annotation + + # Optional: Add custom labels to OneAgent pods + # + # labels: + # custom: label + + # Optional: Use a custom OneAgent image. + # + # image: "" + + # Optional: The OneAgent version to be used. + # Example: ..., e.g. 1.200.0.20240101-000000 + # + # version: "" + + # Optional: The SecComp Profile that will be configured in order to run in secure computing mode. + # + # secCompProfile: "" + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - routing - kubernetes-monitoring - dynatrace-api + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml b/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml index f9a9783a9a..23a465f65e 100644 --- a/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml +++ b/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml @@ -6,10 +6,135 @@ metadata: # annotations: # feature.dynatrace.com/k8s-app-enabled: "true" spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - kubernetes-monitoring + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml index 4043d82b34..83d1b5da2d 100644 --- a/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml +++ b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml @@ -3,31 +3,195 @@ kind: DynaKube metadata: name: dynakube namespace: dynatrace + # annotations: + # feature.dynatrace.com/k8s-app-enabled: "true" spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] kspm: {} + # Configuration for ActiveGate instances. + # activeGate: - tlsSecretName: - + # Defines the ActiveGate capabilities + # capabilities: - kubernetes-monitoring - # The KSPM ActiveGate pipeline is enabled by default with ActiveGate >= 1.311. This custom properties are obsolete then. + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # # customProperties: # value: | # [kubernetes_monitoring] # kubernetes_configuration_dataset_pipeline_enabled = true # kubernetes_configuration_dataset_pipeline_include_node_config = true - templates: {} - # Required in combination with kspm enabled. - # As there is no image available in public registry yet, this field is required if you want to run kspm. + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. # - # kspmNodeConfigurationCollector: - # imageRef: - # repository: - # tag: + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] + + templates: + kspmNodeConfigurationCollector: + # Required: Configure the image for the Node Configuration Collector. + imageRef: + repository: public.ecr.aws/dynatrace/dynatrace-k8s-node-config-collector + tag: + + # Optional: Define the update strategy for the Node Configuration Collector daemonSet + # + # updateStrategy: {} + + # Optional: Add custom labels to NNode Configuration Collector pods + # + # labels: + # custom: label + + # Optional: Add custom annotations to Node Configuration Collector pods. + # + # annotations: + # custom: annotation + + # Optional: Specify the node selector that controls on which nodes OneAgent will be deployed. + # + # nodeSelector: {} + + # Optional: Define the nodeAffinity for the DaemonSet of the Node Configuration Collector + # + # nodeAffinity: {} + + # Optional: Assign a priority class to the Node Configuration Collector pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the Node Configuration Collector DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for Node Configuration Collector container. + # + # resources: {} + + # Optional: Set additional arguments to the Node Configuration Collector. + # + # args: [] + + # Optional: Set additional environment variables for the Node Configuration Collector pods. + # + # env: [] diff --git a/assets/samples/dynakube/v1beta4/logMonitoring.yaml b/assets/samples/dynakube/v1beta4/logMonitoring.yaml index c7cde36f5a..e996673ab4 100644 --- a/assets/samples/dynakube/v1beta4/logMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/logMonitoring.yaml @@ -4,25 +4,205 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap - # The `logMonitoring` section is used to configure log collection via the OneAgent Log module. - # it can be used with any other DynaKube mode, e.g. applicationMonitoring. - # Available with Dynatrace version 1.306+ and OneAgent 1.305+ + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for Log monitoring. + # logMonitoring: {} + # Optional: Specifies the rules and conditions for matching ingest attributes. + # + # ingestRuleMatchers: + # - attribute: "k8s.namespace.name" + # values: + # - "kube-system" + # - "dynatrace" + # - "default" + # - attribute: "k8s.pod.annotation", + # values: + # - "logs.dynatrace.com/ingest=true" + # - "category=security" + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - kubernetes-monitoring - templates: {} - # Required in combination with logMonitoring enabled. - # As there is no image available in public registry yet, this field is required if you want to run logMonitoring. + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [kubernetes_monitoring] + # kubernetes_configuration_dataset_pipeline_enabled = true + # kubernetes_configuration_dataset_pipeline_include_node_config = true + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. # - # logMonitoring: - # imageRef: - # repository: - # tag: + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] + + templates: + logMonitoring: + imageRef: + repository: public.ecr.aws/dynatrace/dynatrace-logmodule + tag: + + # Optional: Define the update strategy for the Log monitoring daemonSet + # + # updateStrategy: {} + + # Optional: Add custom labels to Log monitoring pods + # + # labels: + # custom: label + + # Optional: Add custom annotations to Log monitoring pods. + # + # annotations: + # custom: annotation + + # Optional: Specify the node selector that controls on which nodes Log monitoring will be deployed. + # + # nodeSelector: {} + + # Optional: Define the nodeAffinity for the Log monitoring DaemonSet + # + # nodeAffinity: {} + + # Optional: Assign a priority class to the Log monitoring pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the Log monitoring DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for Log monitoring container. + # + # resources: {} + + # Optional: Set additional arguments to Log monitoring + # + # args: [] + + # Optional: Set additional environment variables for the Log monitoring pods. + # + # env: [] From b927d01fdb84a9ec86ab32c90202d728baa35c2f Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Tue, 18 Mar 2025 10:58:29 +0100 Subject: [PATCH 331/426] Add bootstrapper-injection e2e test (#4607) --- doc/e2e/features.md | 9 ++ hack/make/tests/e2e.mk | 28 +++-- test/features/bootstrapper/without_csi.go | 118 ++++++++++++++++++ .../components/operator/installation.go | 19 +-- test/scenarios/no_csi/no_csi_test.go | 57 +++++++++ test/scenarios/standard/standard_test.go | 13 -- 6 files changed, 214 insertions(+), 30 deletions(-) create mode 100644 test/features/bootstrapper/without_csi.go create mode 100644 test/scenarios/no_csi/no_csi_test.go diff --git a/doc/e2e/features.md b/doc/e2e/features.md index 7d3646db8c..ffc5b9358f 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -88,6 +88,7 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/bootstrapper" ## Index - [func InstallWithCSI(t *testing.T) features.Feature](<#InstallWithCSI>) +- [func NoCSI(t *testing.T) features.Feature](<#NoCSI>) @@ -97,6 +98,14 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/bootstrapper" func InstallWithCSI(t *testing.T) features.Feature ``` + + +## func [NoCSI]() + +```go +func NoCSI(t *testing.T) features.Feature +``` + # classic ```go diff --git a/hack/make/tests/e2e.mk b/hack/make/tests/e2e.mk index 46f4d8047a..c698479b74 100644 --- a/hack/make/tests/e2e.mk +++ b/hack/make/tests/e2e.mk @@ -8,18 +8,20 @@ test/e2e/%/publish: test/e2e/%/debug: @make SKIPCLEANUP="--fail-fast" $(@D) -## Run standard, istio and release e2e tests +## Run standard, no-csi, istio and release e2e tests test/e2e: RC=0; \ make test/e2e/standard || RC=1; \ + make test/e2e/no-csi || RC=1; \ make test/e2e/istio || RC=1; \ make test/e2e/release || RC=1; \ exit $$RC -## Run standard, istio and release e2e tests +## Run standard, no-csi, istio and release e2e tests with /publish test/e2e-publish: RC=0; \ make test/e2e/standard/publish || RC=1; \ + make test/e2e/no-csi/publish || RC=1; \ make test/e2e/istio/publish || RC=1; \ make test/e2e/release/publish || RC=1; \ exit $$RC @@ -32,13 +34,17 @@ test/e2e/standard: manifests/crd/helm test/e2e/istio: manifests/crd/helm $(GOTESTCMD) -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 200m -count=1 ./test/scenarios/istio -args $(SKIPCLEANUP) +## Run no-csi e2e test only +test/e2e/no-csi: manifests/crd/helm + $(GOTESTCMD) -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 200m -count=1 ./test/scenarios/no_csi -args $(SKIPCLEANUP) + ## Run release e2e test only test/e2e/release: manifests/crd/helm $(GOTESTCMD) -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/release -args $(SKIPCLEANUP) ## Runs ActiveGate e2e test only test/e2e/activegate: manifests/crd/helm - go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "activegate" $(SKIPCLEANUP) + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "activegate" $(SKIPCLEANUP) ## Runs ActiveGate proxy e2e test only test/e2e/activegate/proxy: manifests/crd/helm @@ -46,7 +52,7 @@ test/e2e/activegate/proxy: manifests/crd/helm ## Runs ClassicFullStack e2e test only test/e2e/classic: manifests/crd/helm - go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "classic" $(SKIPCLEANUP) + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "classic" $(SKIPCLEANUP) ## Runs ClassicFullStack switch mode e2e test only test/e2e/classic/switchmodes: manifests/crd/helm @@ -98,11 +104,11 @@ test/e2e/cloudnative/upgrade: manifests/crd/helm ## Runs Application Monitoring metadata-enrichment e2e test only test/e2e/applicationmonitoring/metadataenrichment: manifests/crd/helm - go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "metadata-enrichment" $(SKIPCLEANUP) + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "metadata-enrichment" $(SKIPCLEANUP) ## Runs Application Monitoring label versio detection e2e test only test/e2e/applicationmonitoring/labelversion: manifests/crd/helm - go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "label-version" $(SKIPCLEANUP) + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "label-version" $(SKIPCLEANUP) ## Runs Application Monitoring readonly csi-volume e2e test only test/e2e/applicationmonitoring/readonlycsivolume: manifests/crd/helm @@ -110,12 +116,16 @@ test/e2e/applicationmonitoring/readonlycsivolume: manifests/crd/helm ## Runs Application Monitoring without CSI e2e test only test/e2e/applicationmonitoring/withoutcsi: manifests/crd/helm - go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "app-monitoring-without-csi" $(SKIPCLEANUP) + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "app-monitoring-without-csi" $(SKIPCLEANUP) ## Runs Application Monitoring bootstrapper with CSI e2e test only test/e2e/applicationmonitoring/bootstrapper-csi: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "node-image-pull-with-csi" $(SKIPCLEANUP) +## Runs Application Monitoring bootstrapper with no CSI e2e test only +test/e2e/applicationmonitoring/bootstrapper-no-csi: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "node-image-pull-with-no-csi" $(SKIPCLEANUP) + ## Runs public registry images e2e test only test/e2e/publicregistry: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "public-registry-images" $(SKIPCLEANUP) @@ -126,7 +136,7 @@ test/e2e/supportarchive: manifests/crd/helm ## Runs Edgeconnect e2e test only test/e2e/edgeconnect: manifests/crd/helm - go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "edgeconnect-.*" $(SKIPCLEANUP) + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "edgeconnect-.*" $(SKIPCLEANUP) ## Runs e2e tests on gke-autopilot test/e2e/gke-autopilot: manifests/crd/helm @@ -134,4 +144,4 @@ test/e2e/gke-autopilot: manifests/crd/helm ## Runs extensions related e2e tests test/e2e/extensions: manifests/crd/helm - go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "extensions-components-rollout" $(SKIPCLEANUP) + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "extensions-components-rollout" $(SKIPCLEANUP) diff --git a/test/features/bootstrapper/without_csi.go b/test/features/bootstrapper/without_csi.go new file mode 100644 index 0000000000..f7cb9d6bf7 --- /dev/null +++ b/test/features/bootstrapper/without_csi.go @@ -0,0 +1,118 @@ +//go:build e2e + +package bootstrapper + +import ( + "context" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook" + "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/volumes" + "github.com/Dynatrace/dynatrace-operator/test/helpers" + dynakubeComponents "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" + "github.com/Dynatrace/dynatrace-operator/test/helpers/sample" + "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" +) + +func NoCSI(t *testing.T) features.Feature { + builder := features.New("node-image-pull-with-no-csi") + secretConfig := tenant.GetSingleTenantSecret(t) + dk := *dynakubeComponents.New( + dynakubeComponents.WithApiUrl(secretConfig.ApiUrl), + dynakubeComponents.WithApplicationMonitoringSpec(&oneagent.ApplicationMonitoringSpec{AppInjectionSpec: oneagent.AppInjectionSpec{CodeModulesImage: bootstrapperImage}}), + dynakubeComponents.WithAnnotations(map[string]string{ + dynakube.AnnotationFeatureNodeImagePull: "true", + dynakube.AnnotationTechnologies: "php", + }), + ) + + dynakubeComponents.Install(builder, helpers.LevelAssess, &secretConfig, dk) + + sampleApp := sample.NewApp(t, &dk, sample.AsDeployment()) + builder.Assess("install sample app", sampleApp.Install()) + builder.Assess("check injection of sample app", checkInjection(sampleApp)) + + podSample := sample.NewApp(t, &dk, + sample.WithName("only-pod-sample"), + ) + builder.Assess("install additional pod", podSample.Install()) + builder.Assess("check injection of additional pod", checkInjection(podSample)) + + randomUserSample := sample.NewApp(t, &dk, + sample.WithName("random-user"), + sample.AsDeployment(), + sample.WithSecurityContext(corev1.PodSecurityContext{ + RunAsUser: ptr.To[int64](1234), + RunAsGroup: ptr.To[int64](1234), + }), + ) + builder.Assess("install sample app with random users set", randomUserSample.Install()) + builder.Assess("check injection of pods with random user", checkInjection(randomUserSample)) + + builder.Teardown(sampleApp.Uninstall()) + builder.Teardown(podSample.Uninstall()) + builder.Teardown(randomUserSample.Uninstall()) + dynakubeComponents.Delete(builder, helpers.LevelTeardown, dk) + + return builder.Feature() +} + +func checkInjection(deployment *sample.App) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + resource := envConfig.Client().Resources() + samplePods := deployment.GetPods(ctx, t, resource) + + require.NotNil(t, samplePods) + + for _, item := range samplePods.Items { + require.NotNil(t, item.Spec.InitContainers) + require.Equal(t, webhook.InstallContainerName, item.Spec.InitContainers[0].Name) + + args := item.Spec.InitContainers[0].Args + // TODO use bootstrapper repo consts in the future + require.Contains(t, args, "--source=/opt/dynatrace/oneagent") + require.Contains(t, args, "--target=/mnt/bin") + require.Contains(t, args, "--config-directory=/mnt/config") + require.Contains(t, args, "--input-directory=/mnt/input") + require.NotContains(t, args, "--work=") + require.NotContains(t, args, "--debug") + require.Contains(t, args, "--technology=php") + require.Contains(t, args, "--suppress-error") + + expectedVolume := corev1.Volume{ + Name: volumes.InputVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: consts.BootstrapperInitSecretName, + }, + }, + } + + // require.Contains doesn't work, I tried + found := false + for _, v := range item.Spec.Volumes { + if v.Name == expectedVolume.Name { + require.NotNil(t, v.Secret) + require.Equal(t, expectedVolume.Secret.SecretName, v.Secret.SecretName) + found = true + } + } + require.True(t, found) + + if item.Spec.SecurityContext != nil { + item.Spec.InitContainers[0].SecurityContext.RunAsUser = item.Spec.SecurityContext.RunAsUser + item.Spec.InitContainers[0].SecurityContext.RunAsGroup = item.Spec.SecurityContext.RunAsGroup + } + } + + return ctx + } +} diff --git a/test/helpers/components/operator/installation.go b/test/helpers/components/operator/installation.go index b346f9607e..d95eb7dfef 100644 --- a/test/helpers/components/operator/installation.go +++ b/test/helpers/components/operator/installation.go @@ -29,20 +29,20 @@ func InstallViaMake(withCSI bool) env.Func { if err != nil { return ctx, err } - ctx, err = VerifyInstall(ctx, envConfig) + ctx, err = VerifyInstall(ctx, envConfig, withCSI) return ctx, err } } -func InstallViaHelm(releaseTag string, withCsi bool, namespace string) env.Func { +func InstallViaHelm(releaseTag string, withCSI bool, namespace string) env.Func { return func(ctx context.Context, envConfig *envconf.Config) (context.Context, error) { - err := installViaHelm(releaseTag, withCsi, namespace) + err := installViaHelm(releaseTag, withCSI, namespace) if err != nil { return ctx, err } - return VerifyInstall(ctx, envConfig) + return VerifyInstall(ctx, envConfig, withCSI) } } @@ -60,7 +60,7 @@ func UninstallViaMake(withCSI bool) env.Func { } } -func VerifyInstall(ctx context.Context, envConfig *envconf.Config) (context.Context, error) { +func VerifyInstall(ctx context.Context, envConfig *envconf.Config, withCSI bool) (context.Context, error) { ctx, err := WaitForDeployment(DefaultNamespace)(ctx, envConfig) if err != nil { return ctx, err @@ -69,9 +69,12 @@ func VerifyInstall(ctx context.Context, envConfig *envconf.Config) (context.Cont if err != nil { return ctx, err } - ctx, err = csi.WaitForDaemonset(DefaultNamespace)(ctx, envConfig) - if err != nil { - return ctx, err + + if withCSI { + ctx, err = csi.WaitForDaemonset(DefaultNamespace)(ctx, envConfig) + if err != nil { + return ctx, err + } } return ctx, nil diff --git a/test/scenarios/no_csi/no_csi_test.go b/test/scenarios/no_csi/no_csi_test.go new file mode 100644 index 0000000000..d14736a587 --- /dev/null +++ b/test/scenarios/no_csi/no_csi_test.go @@ -0,0 +1,57 @@ +//go:build e2e + +package no_csi + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/test/features/activegate" + "github.com/Dynatrace/dynatrace-operator/test/features/applicationmonitoring" + "github.com/Dynatrace/dynatrace-operator/test/features/bootstrapper" + "github.com/Dynatrace/dynatrace-operator/test/features/classic" + "github.com/Dynatrace/dynatrace-operator/test/features/edgeconnect" + "github.com/Dynatrace/dynatrace-operator/test/features/extensions" + "github.com/Dynatrace/dynatrace-operator/test/helpers" + "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/environment" + "github.com/Dynatrace/dynatrace-operator/test/scenarios" + "sigs.k8s.io/e2e-framework/pkg/env" + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" +) + +var ( + testEnv env.Environment + cfg *envconf.Config +) + +func TestMain(m *testing.M) { + cfg = environment.GetStandardKubeClusterEnvConfig() + testEnv = env.NewWithConfig(cfg) + testEnv.Setup( + helpers.SetScheme, + operator.InstallViaMake(false), + ) + // If we cleaned up during a fail-fast (aka.: /debug) it wouldn't be possible to investigate the error. + if !cfg.FailFast() { + testEnv.Finish(operator.UninstallViaMake(false)) + } + testEnv.Run(m) +} + +func TestNoCSI(t *testing.T) { + feats := []features.Feature{ + activegate.Feature(t, nil), + applicationmonitoring.MetadataEnrichment(t), + applicationmonitoring.LabelVersionDetection(t), + applicationmonitoring.WithoutCSI(t), + extensions.Feature(t), + edgeconnect.NormalModeFeature(t), + edgeconnect.ProvisionerModeFeature(t), + edgeconnect.AutomationModeFeature(t), + classic.Feature(t), + bootstrapper.NoCSI(t), + } + + testEnv.Test(t, scenarios.FilterFeatures(*cfg, feats)...) +} diff --git a/test/scenarios/standard/standard_test.go b/test/scenarios/standard/standard_test.go index d9326695b2..be2219c927 100644 --- a/test/scenarios/standard/standard_test.go +++ b/test/scenarios/standard/standard_test.go @@ -5,17 +5,13 @@ package standard import ( "testing" - "github.com/Dynatrace/dynatrace-operator/test/features/activegate" "github.com/Dynatrace/dynatrace-operator/test/features/applicationmonitoring" "github.com/Dynatrace/dynatrace-operator/test/features/bootstrapper" - "github.com/Dynatrace/dynatrace-operator/test/features/classic" classicToCloud "github.com/Dynatrace/dynatrace-operator/test/features/classic/switch_modes" "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/codemodules" cloudnativeDefault "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/default" disabledAutoInjection "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/disabled_auto_injection" cloudToClassic "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/switch_modes" - "github.com/Dynatrace/dynatrace-operator/test/features/edgeconnect" - "github.com/Dynatrace/dynatrace-operator/test/features/extensions" "github.com/Dynatrace/dynatrace-operator/test/features/publicregistry" supportArchive "github.com/Dynatrace/dynatrace-operator/test/features/support_archive" "github.com/Dynatrace/dynatrace-operator/test/helpers" @@ -48,21 +44,12 @@ func TestMain(m *testing.M) { func TestStandard(t *testing.T) { feats := []features.Feature{ - activegate.Feature(t, nil), cloudnativeDefault.Feature(t, false), - applicationmonitoring.MetadataEnrichment(t), - applicationmonitoring.LabelVersionDetection(t), applicationmonitoring.ReadOnlyCSIVolume(t), - applicationmonitoring.WithoutCSI(t), codemodules.InstallFromImage(t), publicregistry.Feature(t), - extensions.Feature(t), disabledAutoInjection.Feature(t), supportArchive.Feature(t), - edgeconnect.NormalModeFeature(t), - edgeconnect.ProvisionerModeFeature(t), - edgeconnect.AutomationModeFeature(t), - classic.Feature(t), classicToCloud.Feature(t), cloudToClassic.Feature(t), bootstrapper.InstallWithCSI(t), From a9a118709a8fc0636d3f30b61f149cdef78d283f Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Tue, 18 Mar 2025 15:52:31 +0100 Subject: [PATCH 332/426] Make CSI Driver optional for cloudnative/hostmonitoring (#4606) --- config/crd/bases/dynatrace.com_dynakubes.yaml | 15 +++++ .../Common/crd/dynatrace-operator-crd.yaml | 15 +++++ doc/api/dynakube-api-ref.md | 3 + pkg/api/v1beta4/dynakube/oneagent/spec.go | 5 ++ pkg/api/validation/dynakube/csi_daemonset.go | 4 +- pkg/api/validation/dynakube/module_test.go | 64 ------------------- pkg/api/validation/dynakube/modules.go | 14 ---- pkg/api/validation/dynakube/validation.go | 1 - .../validation/dynakube/validation_test.go | 1 - 9 files changed, 40 insertions(+), 82 deletions(-) diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index a3262ed292..535db8124c 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -8703,6 +8703,11 @@ spec: description: The SecComp Profile that will be configured in order to run in secure computing mode. type: string + storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will be + stored. + type: string tolerations: description: Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). @@ -9094,6 +9099,11 @@ spec: description: The SecComp Profile that will be configured in order to run in secure computing mode. type: string + storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will be + stored. + type: string tolerations: description: Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). @@ -9374,6 +9384,11 @@ spec: description: The SecComp Profile that will be configured in order to run in secure computing mode. type: string + storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will be + stored. + type: string tolerations: description: Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 07704cdb89..483afd2de4 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -8715,6 +8715,11 @@ spec: description: The SecComp Profile that will be configured in order to run in secure computing mode. type: string + storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will be + stored. + type: string tolerations: description: Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). @@ -9106,6 +9111,11 @@ spec: description: The SecComp Profile that will be configured in order to run in secure computing mode. type: string + storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will be + stored. + type: string tolerations: description: Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). @@ -9386,6 +9396,11 @@ spec: description: The SecComp Profile that will be configured in order to run in secure computing mode. type: string + storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will be + stored. + type: string tolerations: description: Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). diff --git a/doc/api/dynakube-api-ref.md b/doc/api/dynakube-api-ref.md index ff320db168..01b7c25b9c 100644 --- a/doc/api/dynakube-api-ref.md +++ b/doc/api/dynakube-api-ref.md @@ -79,6 +79,7 @@ |`oneAgentResources`|Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR.
Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod.|-|object| |`priorityClassName`|Assign a priority class to the OneAgent pods. By default, no class is set.
For details, see Pod Priority and Preemption ().|-|string| |`secCompProfile`|The SecComp Profile that will be configured in order to run in secure computing mode.|-|string| +|`storageHostPath`|StorageHostPath is the writable directory on the host filesystem where OneAgent configurations will be stored.|-|string| |`tolerations`|Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations ().|-|array| |`version`|Use a specific OneAgent version. Defaults to the latest version from the Dynatrace cluster.|-|string| @@ -111,6 +112,7 @@ |`oneAgentResources`|Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR.
Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod.|-|object| |`priorityClassName`|Assign a priority class to the OneAgent pods. By default, no class is set.
For details, see Pod Priority and Preemption ().|-|string| |`secCompProfile`|The SecComp Profile that will be configured in order to run in secure computing mode.|-|string| +|`storageHostPath`|StorageHostPath is the writable directory on the host filesystem where OneAgent configurations will be stored.|-|string| |`tolerations`|Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations ().|-|array| |`version`|Use a specific OneAgent version. Defaults to the latest version from the Dynatrace cluster.|-|string| @@ -132,6 +134,7 @@ |`oneAgentResources`|Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR.
Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod.|-|object| |`priorityClassName`|Assign a priority class to the OneAgent pods. By default, no class is set.
For details, see Pod Priority and Preemption ().|-|string| |`secCompProfile`|The SecComp Profile that will be configured in order to run in secure computing mode.|-|string| +|`storageHostPath`|StorageHostPath is the writable directory on the host filesystem where OneAgent configurations will be stored.|-|string| |`tolerations`|Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations ().|-|array| |`version`|Use a specific OneAgent version. Defaults to the latest version from the Dynatrace cluster.|-|string| diff --git a/pkg/api/v1beta4/dynakube/oneagent/spec.go b/pkg/api/v1beta4/dynakube/oneagent/spec.go index a6bb62bedb..0e2a09e4c0 100644 --- a/pkg/api/v1beta4/dynakube/oneagent/spec.go +++ b/pkg/api/v1beta4/dynakube/oneagent/spec.go @@ -105,6 +105,11 @@ type HostInjectSpec struct { // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OneAgent SecComp Profile",order=17,xDescriptors="urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Namespace" SecCompProfile string `json:"secCompProfile,omitempty"` + // StorageHostPath is the writable directory on the host filesystem where OneAgent configurations will be stored. + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="StorageHostPath",order=28,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:hidden"} + StorageHostPath string `json:"storageHostPath,omitempty"` + // Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. // Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. // +kubebuilder:validation:Optional diff --git a/pkg/api/validation/dynakube/csi_daemonset.go b/pkg/api/validation/dynakube/csi_daemonset.go index 0549d526c4..6f21cf480e 100644 --- a/pkg/api/validation/dynakube/csi_daemonset.go +++ b/pkg/api/validation/dynakube/csi_daemonset.go @@ -12,7 +12,7 @@ const ( ) func disabledCSIForReadonlyCSIVolume(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { - isCSINotUsed := !dk.OneAgent().IsCSIAvailable() || (!isCSIRequired(dk) && !isCSIOptional(dk)) + isCSINotUsed := !dk.OneAgent().IsCSIAvailable() || !isCSIOptional(dk) if dk.FeatureReadOnlyCsiVolume() && isCSINotUsed { log.Info("requested dynakube uses readonly csi volume, but csi driver is not enabled", "name", dk.Name, "namespace", dk.Namespace) @@ -24,5 +24,5 @@ func disabledCSIForReadonlyCSIVolume(_ context.Context, _ *Validator, dk *dynaku // IsCSIDriverOptional checks if the DynaKube may use the csi-driver if available, otherwise fallbacks exist to provide similar functionality. func isCSIOptional(dk *dynakube.DynaKube) bool { - return dk.OneAgent().IsHostMonitoringMode() || dk.OneAgent().IsApplicationMonitoringMode() + return dk.OneAgent().IsCloudNativeFullstackMode() || dk.OneAgent().IsHostMonitoringMode() || dk.OneAgent().IsApplicationMonitoringMode() } diff --git a/pkg/api/validation/dynakube/module_test.go b/pkg/api/validation/dynakube/module_test.go index 82cd7f1bbc..4cef36bc9c 100644 --- a/pkg/api/validation/dynakube/module_test.go +++ b/pkg/api/validation/dynakube/module_test.go @@ -25,41 +25,6 @@ func TestIsModuleDisabled(t *testing.T) { } testCases := []testCase{ - { - title: "csi module disabled but also configured in dk => error", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}}}, - modules: installconfig.Modules{OneAgent: true, CSIDriver: false}, - moduleFunc: isCSIModuleDisabled, - expectedMessage: errorCSIModuleRequired, - }, - { - title: "csi module disabled but not configured => no error", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: nil}}}, - modules: installconfig.Modules{OneAgent: true, CSIDriver: false}, - moduleFunc: isCSIModuleDisabled, - expectedMessage: "", - }, - { - title: "csi module enabled and also configured => no error", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}}}, - modules: installconfig.Modules{OneAgent: true, CSIDriver: true}, - moduleFunc: isCSIModuleDisabled, - expectedMessage: "", - }, - { - title: "csi module disabled and app-monitoring configured => no error, as it's optional for app-monitoring", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}}}}, - modules: installconfig.Modules{OneAgent: true, CSIDriver: false}, - moduleFunc: isCSIModuleDisabled, - expectedMessage: "", - }, - { - title: "csi module disabled and host-monitoring configured => no error, as it's optional for host-monitoring", - dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{HostMonitoring: &oneagent.HostInjectSpec{}}}}, - modules: installconfig.Modules{OneAgent: true, CSIDriver: true}, - moduleFunc: isCSIModuleDisabled, - expectedMessage: "", - }, { title: "oa module disabled but also configured in dk => error", dk: dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}}}, @@ -174,32 +139,3 @@ func TestIsModuleDisabled(t *testing.T) { }) } } - -func TestIsCSIDriverRequired(t *testing.T) { - t.Run("DynaKube with cloud native", func(t *testing.T) { - dk := dynakube.DynaKube{Spec: dynakube.DynaKubeSpec{OneAgent: oneagent.Spec{CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}}}} - assert.True(t, isCSIRequired(&dk)) - }) - - t.Run("DynaKube with host monitoring", func(t *testing.T) { - dk := dynakube.DynaKube{ - Spec: dynakube.DynaKubeSpec{ - OneAgent: oneagent.Spec{ - HostMonitoring: &oneagent.HostInjectSpec{}, - }, - }, - } - assert.False(t, isCSIRequired(&dk)) - }) - - t.Run("DynaKube with application monitoring", func(t *testing.T) { - dk := dynakube.DynaKube{ - Spec: dynakube.DynaKubeSpec{ - OneAgent: oneagent.Spec{ - ApplicationMonitoring: &oneagent.ApplicationMonitoringSpec{}, - }, - }, - } - assert.False(t, isCSIRequired(&dk)) - }) -} diff --git a/pkg/api/validation/dynakube/modules.go b/pkg/api/validation/dynakube/modules.go index 66c070876b..7a16562273 100644 --- a/pkg/api/validation/dynakube/modules.go +++ b/pkg/api/validation/dynakube/modules.go @@ -8,7 +8,6 @@ import ( ) var ( - errorCSIModuleRequired = "CSI Driver was disabled during Operator install. It is a necessary resource for Cloud Native Fullstack to work. Redeploy the Operator via Helm with the CSI Driver enabled." errorOneAgentModuleDisabled = installconfig.GetModuleValidationErrorMessage("OneAgent") errorActiveGateModuleDisabled = installconfig.GetModuleValidationErrorMessage("ActiveGate") errorExtensionsModuleDisabled = installconfig.GetModuleValidationErrorMessage("Extensions") @@ -55,16 +54,3 @@ func isKSPMDisabled(_ context.Context, v *Validator, dk *dynakube.DynaKube) stri return "" } - -func isCSIModuleDisabled(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { - if isCSIRequired(dk) && !v.modules.CSIDriver { - return errorCSIModuleRequired - } - - return "" -} - -// isCSIRequired checks if the provided a DynaKube strictly needs the csi-driver, and no fallbacks exist to provide the same functionality. -func isCSIRequired(dk *dynakube.DynaKube) bool { - return dk.OneAgent().IsCloudNativeFullstackMode() -} diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index 2d9c716e1f..cbe01f0867 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -24,7 +24,6 @@ type Validator struct { var ( validatorErrorFuncs = []validatorFunc{ - isCSIModuleDisabled, isActiveGateModuleDisabled, isExtensionsModuleDisabled, isLogMonitoringModuleDisabled, diff --git a/pkg/api/validation/dynakube/validation_test.go b/pkg/api/validation/dynakube/validation_test.go index 6b7688ef15..d234eb10fe 100644 --- a/pkg/api/validation/dynakube/validation_test.go +++ b/pkg/api/validation/dynakube/validation_test.go @@ -106,7 +106,6 @@ func TestDynakubeValidator_Handle(t *testing.T) { setupDisabledCSIEnv(t) assertDenied(t, []string{ - errorCSIModuleRequired, errorNoApiUrl, errorConflictingNamespaceSelector, fmt.Sprintf(errorDuplicateActiveGateCapability, activegate.KubeMonCapability.DisplayName), From 6b75fe923be19f4531815e9d0f812e27b218d476 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 23:01:46 +0000 Subject: [PATCH 333/426] chore(deps): update actions/download-artifact action to v4.2.0 (main) (#4616) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/upload-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/upload-image/action.yaml b/.github/actions/upload-image/action.yaml index 106b6c9843..a2b8490d4f 100644 --- a/.github/actions/upload-image/action.yaml +++ b/.github/actions/upload-image/action.yaml @@ -29,7 +29,7 @@ runs: using: "composite" steps: - name: Download artifact - uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 + uses: actions/download-artifact@b14cf4c92620c250e1c074ab0a5800e37df86765 # v4.2.0 with: name: operator-${{ inputs.platform }} path: /tmp From 510325ad8c0ba0d3a8bc4beeb4bb6e984f7d9fba Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 03:37:50 +0000 Subject: [PATCH 334/426] chore(deps): update module github.com/vektra/mockery to v2.53.3 (main) (#4618) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index acf413fb6b..9900ef28b3 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -9,7 +9,7 @@ gci_version=v0.13.5 # renovate depName=golang.org/x/tools golang_tools_version=v0.31.0 # renovate depName=github.com/vektra/mockery -mockery_version=v2.53.2 +mockery_version=v2.53.3 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest From c1e723380ec0c3dc7c5106549e132bf60490829e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 05:29:53 +0000 Subject: [PATCH 335/426] fix(deps): update module go.opentelemetry.io/collector/component to v1.28.1 (main) (#4619) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index e1d52338ca..68d4944fe3 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/afero v1.14.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 - go.opentelemetry.io/collector/component v1.28.0 + go.opentelemetry.io/collector/component v1.28.1 go.opentelemetry.io/collector/confmap v1.28.0 go.opentelemetry.io/collector/pipeline v0.122.0 go.opentelemetry.io/collector/service v0.122.0 @@ -117,7 +117,7 @@ require ( go.opentelemetry.io/collector/featuregate v1.28.0 // indirect go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0 // indirect go.opentelemetry.io/collector/internal/telemetry v0.122.0 // indirect - go.opentelemetry.io/collector/pdata v1.28.0 // indirect + go.opentelemetry.io/collector/pdata v1.28.1 // indirect go.opentelemetry.io/collector/pdata/pprofile v0.122.0 // indirect go.opentelemetry.io/collector/pdata/testdata v0.122.0 // indirect go.opentelemetry.io/collector/pipeline/xpipeline v0.122.0 // indirect diff --git a/go.sum b/go.sum index 24a7f0975e..92cde8e0bf 100644 --- a/go.sum +++ b/go.sum @@ -185,8 +185,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/collector v0.122.0 h1:eir4Fvv2tz5tUvPBTvFk8VmqeihYcTuYD6AXllvxxIg= go.opentelemetry.io/collector v0.122.0/go.mod h1:8t7TFg4nQHskvaOZrbfqAprB3r6+SZ2GQ2NYua0HEtg= -go.opentelemetry.io/collector/component v1.28.0 h1:SQAGxxuyZ+d5tOsuEka8m9oE+wAroaYQpJ8NTIbl6Lk= -go.opentelemetry.io/collector/component v1.28.0/go.mod h1:te8gbcKU6Mgu7ewo/2VYDSbCkLrhOYYy2llayXCF0bI= +go.opentelemetry.io/collector/component v1.28.1 h1:JjwfvLR0UdadRDAANAdM4mOSwGmfGO3va2X+fdk4YdA= +go.opentelemetry.io/collector/component v1.28.1/go.mod h1:jwZRDML3tXo1whueZdRf+y6z3DeEYTLPBmb/O1ujB40= go.opentelemetry.io/collector/component/componentstatus v0.122.0 h1:gzqsfL8IN+bwlByl76MNFIDtq0jc9Y671NoZQGAiupg= go.opentelemetry.io/collector/component/componentstatus v0.122.0/go.mod h1:d4WiL3UHQFIh7WN4miV5aupTZK3kFRt4xfzhsyTEMN4= go.opentelemetry.io/collector/component/componenttest v0.122.0 h1:TxMm4nXB9iByQhDP0QFZwYxG+BFXEB6qUUwVh5YYW7g= @@ -233,8 +233,8 @@ go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0 h1:Oup8r2FaIEi7si go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0/go.mod h1:02AWRtzi/v9P2ldMdQq5+OKKoqIVPdqZQ/B3KKNu/So= go.opentelemetry.io/collector/internal/telemetry v0.122.0 h1:5RCl/CdT3+VaduRI5IphoH3xS49sHZmEY/y3N3CEZjs= go.opentelemetry.io/collector/internal/telemetry v0.122.0/go.mod h1:FrmVXPmQMn3BuGIWg/pOdmHTMvXmlNzcbMusn8SSZn4= -go.opentelemetry.io/collector/pdata v1.28.0 h1:xSZyvTOOc2Wmz4PoxrVqeQfodLgs9k7gowLAnzZN0eU= -go.opentelemetry.io/collector/pdata v1.28.0/go.mod h1:asKE8MD/4SOKz1mCrGdAz4VO2U2HUNg8A6094uK7pq0= +go.opentelemetry.io/collector/pdata v1.28.1 h1:ORl5WLpQJvjzBVpHu12lqKMdcf/qDBwRXMcUubhybiQ= +go.opentelemetry.io/collector/pdata v1.28.1/go.mod h1:asKE8MD/4SOKz1mCrGdAz4VO2U2HUNg8A6094uK7pq0= go.opentelemetry.io/collector/pdata/pprofile v0.122.0 h1:JcmYBmNNOKRO7mIBxJ79YKgrTowILCCcpxKorDBfFOs= go.opentelemetry.io/collector/pdata/pprofile v0.122.0/go.mod h1:miIYvmTQov3C2/D7T0nRMndhavG4tPqz3llKMdLjSwg= go.opentelemetry.io/collector/pdata/testdata v0.122.0 h1:ANXZ+h9yAy1N37ot407qnMtISjZIgjYk10atzD7wSKI= From c1bb875c1cef845dc46b0af580e3e4adb4587949 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 07:20:12 +0000 Subject: [PATCH 336/426] fix(deps): update module go.opentelemetry.io/collector/confmap to v1.28.1 (main) (#4620) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 68d4944fe3..d9f2b602b3 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v1.28.1 - go.opentelemetry.io/collector/confmap v1.28.0 + go.opentelemetry.io/collector/confmap v1.28.1 go.opentelemetry.io/collector/pipeline v0.122.0 go.opentelemetry.io/collector/service v0.122.0 go.uber.org/zap v1.27.0 @@ -114,7 +114,7 @@ require ( go.opentelemetry.io/collector/extension v1.28.0 // indirect go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.0 // indirect go.opentelemetry.io/collector/extension/extensiontest v0.122.0 // indirect - go.opentelemetry.io/collector/featuregate v1.28.0 // indirect + go.opentelemetry.io/collector/featuregate v1.28.1 // indirect go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0 // indirect go.opentelemetry.io/collector/internal/telemetry v0.122.0 // indirect go.opentelemetry.io/collector/pdata v1.28.1 // indirect diff --git a/go.sum b/go.sum index 92cde8e0bf..2c8c1fe77a 100644 --- a/go.sum +++ b/go.sum @@ -195,8 +195,8 @@ go.opentelemetry.io/collector/config/configretry v1.28.0 h1:UqdSd+909bM9nC0eGcQv go.opentelemetry.io/collector/config/configretry v1.28.0/go.mod h1:QNnb+MCk7aS1k2EuGJMtlNCltzD7b8uC7Xel0Dxm1wQ= go.opentelemetry.io/collector/config/configtelemetry v0.122.0 h1:jBPdzU0CVrlxttnfKa0s2kyMVJeHY/faBht6/FUQcWI= go.opentelemetry.io/collector/config/configtelemetry v0.122.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= -go.opentelemetry.io/collector/confmap v1.28.0 h1:pUQh4eOW0YQ1GFWTDP5pw/ZMQuppkz6oSoDDloAH/Sc= -go.opentelemetry.io/collector/confmap v1.28.0/go.mod h1:k/3fo+2RE6m+OKlJzx78Q8hstABYwYgvXO3u9zyTeHI= +go.opentelemetry.io/collector/confmap v1.28.1 h1:/zUmvpnERhFXrxVCVgubjJRgeOwdPbhTfUILZPUBfyw= +go.opentelemetry.io/collector/confmap v1.28.1/go.mod h1:2aJggo/KQl7uynFyMNNMbl7jvKkSD7CniOVEpCbjRng= go.opentelemetry.io/collector/confmap/xconfmap v0.122.0 h1:uRwR2/DEhLCwsdQyD5rTG/cAPUm5ixZb96y3rUaUo/g= go.opentelemetry.io/collector/confmap/xconfmap v0.122.0/go.mod h1:76K9ypccfRyorlYYit8O82mX4hseQP8VJ/TYqCKI4fA= go.opentelemetry.io/collector/connector v0.122.0 h1:VrILgvrE4PWuJzPfB2lj+wxqRK8+SnnFFB9Ft9G1Tok= @@ -227,8 +227,8 @@ go.opentelemetry.io/collector/extension/extensiontest v0.122.0 h1:daeCPXhb4Hveye go.opentelemetry.io/collector/extension/extensiontest v0.122.0/go.mod h1:JXSONLbyuX+uOy1gcQ3Jcp/48pfkh0RiZPy7XkyCBdU= go.opentelemetry.io/collector/extension/xextension v0.122.0 h1:EoPcWm69j0OZCyKvZ0H0KfkLRKZyry678852ua7k+DI= go.opentelemetry.io/collector/extension/xextension v0.122.0/go.mod h1:hdkdi0cGk3X1+9M0IS1LJ8dhlnEKhqHd2HMdc2ata5A= -go.opentelemetry.io/collector/featuregate v1.28.0 h1:nkaMw0HyOSxojLwlezF2O/xJ9T/Jo1a0iEetesT9lr0= -go.opentelemetry.io/collector/featuregate v1.28.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= +go.opentelemetry.io/collector/featuregate v1.28.1 h1:ZpvRAAFxxi4RLr1G0Fju28wA7NhTA20MNT60Ftv+ToY= +go.opentelemetry.io/collector/featuregate v1.28.1/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0 h1:Oup8r2FaIEi7si3Kz7ybSgeNh6TrQFNJ9I7bNNdgJ0o= go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0/go.mod h1:02AWRtzi/v9P2ldMdQq5+OKKoqIVPdqZQ/B3KKNu/So= go.opentelemetry.io/collector/internal/telemetry v0.122.0 h1:5RCl/CdT3+VaduRI5IphoH3xS49sHZmEY/y3N3CEZjs= From 44b81c139f08023adb85ccdcd7595be00c02ae53 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 08:39:09 +0000 Subject: [PATCH 337/426] fix(deps): update module go.opentelemetry.io/collector/pipeline to v0.122.1 (main) (#4621) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d9f2b602b3..8141b03205 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v1.28.1 go.opentelemetry.io/collector/confmap v1.28.1 - go.opentelemetry.io/collector/pipeline v0.122.0 + go.opentelemetry.io/collector/pipeline v0.122.1 go.opentelemetry.io/collector/service v0.122.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 diff --git a/go.sum b/go.sum index 2c8c1fe77a..0773d523b6 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,8 @@ go.opentelemetry.io/collector/pdata/pprofile v0.122.0 h1:JcmYBmNNOKRO7mIBxJ79YKg go.opentelemetry.io/collector/pdata/pprofile v0.122.0/go.mod h1:miIYvmTQov3C2/D7T0nRMndhavG4tPqz3llKMdLjSwg= go.opentelemetry.io/collector/pdata/testdata v0.122.0 h1:ANXZ+h9yAy1N37ot407qnMtISjZIgjYk10atzD7wSKI= go.opentelemetry.io/collector/pdata/testdata v0.122.0/go.mod h1:5WxeLDGisczRoS5lnxyt0PqGI3tr2QnhxUHupGrDY64= -go.opentelemetry.io/collector/pipeline v0.122.0 h1:DmiNzhj2IPpL6JisPo0Hs8vyS5AsUz+GlPh5wblJmTk= -go.opentelemetry.io/collector/pipeline v0.122.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= +go.opentelemetry.io/collector/pipeline v0.122.1 h1:f0uuiDmanVyKwfYo6cWveJsGbLXidV7i+Z7u8QJwWxI= +go.opentelemetry.io/collector/pipeline v0.122.1/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= go.opentelemetry.io/collector/pipeline/xpipeline v0.122.0 h1:Zu6zvO/6epvsjZ74t7qAiMowqhScxHZURlBzBaJ00iY= go.opentelemetry.io/collector/pipeline/xpipeline v0.122.0/go.mod h1:uBWsvO37xU8cPgG8znDMW7bIwzrwRQ0jQ0u05rFeB/g= go.opentelemetry.io/collector/processor v0.122.0 h1:elkgJhXhzwrvycbMGQzLOGNwGURaQZNAx1VB8lh9uq8= From e28b8c767716f86c8d3675a335a7ad044673e5a3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 09:42:50 +0000 Subject: [PATCH 338/426] fix(deps): update module go.opentelemetry.io/collector/service to v0.122.1 (main) (#4622) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 56 ++++++++++++------------ go.sum | 132 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 94 insertions(+), 94 deletions(-) diff --git a/go.mod b/go.mod index 8141b03205..3f8d6d8140 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( go.opentelemetry.io/collector/component v1.28.1 go.opentelemetry.io/collector/confmap v1.28.1 go.opentelemetry.io/collector/pipeline v0.122.1 - go.opentelemetry.io/collector/service v0.122.0 + go.opentelemetry.io/collector/service v0.122.1 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.24.0 @@ -98,35 +98,35 @@ require ( github.com/vladimirvivien/gexe v0.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/collector/component/componentstatus v0.122.0 // indirect - go.opentelemetry.io/collector/component/componenttest v0.122.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.122.0 // indirect - go.opentelemetry.io/collector/connector v0.122.0 // indirect - go.opentelemetry.io/collector/connector/connectortest v0.122.0 // indirect - go.opentelemetry.io/collector/connector/xconnector v0.122.0 // indirect - go.opentelemetry.io/collector/consumer v1.28.0 // indirect - go.opentelemetry.io/collector/consumer/consumererror v0.122.0 // indirect - go.opentelemetry.io/collector/consumer/consumertest v0.122.0 // indirect - go.opentelemetry.io/collector/consumer/xconsumer v0.122.0 // indirect - go.opentelemetry.io/collector/exporter v0.122.0 // indirect - go.opentelemetry.io/collector/exporter/exportertest v0.122.0 // indirect - go.opentelemetry.io/collector/exporter/xexporter v0.122.0 // indirect - go.opentelemetry.io/collector/extension v1.28.0 // indirect - go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.0 // indirect - go.opentelemetry.io/collector/extension/extensiontest v0.122.0 // indirect + go.opentelemetry.io/collector/component/componentstatus v0.122.1 // indirect + go.opentelemetry.io/collector/component/componenttest v0.122.1 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.122.1 // indirect + go.opentelemetry.io/collector/connector v0.122.1 // indirect + go.opentelemetry.io/collector/connector/connectortest v0.122.1 // indirect + go.opentelemetry.io/collector/connector/xconnector v0.122.1 // indirect + go.opentelemetry.io/collector/consumer v1.28.1 // indirect + go.opentelemetry.io/collector/consumer/consumererror v0.122.1 // indirect + go.opentelemetry.io/collector/consumer/consumertest v0.122.1 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.122.1 // indirect + go.opentelemetry.io/collector/exporter v0.122.1 // indirect + go.opentelemetry.io/collector/exporter/exportertest v0.122.1 // indirect + go.opentelemetry.io/collector/exporter/xexporter v0.122.1 // indirect + go.opentelemetry.io/collector/extension v1.28.1 // indirect + go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.1 // indirect + go.opentelemetry.io/collector/extension/extensiontest v0.122.1 // indirect go.opentelemetry.io/collector/featuregate v1.28.1 // indirect - go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0 // indirect - go.opentelemetry.io/collector/internal/telemetry v0.122.0 // indirect + go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.1 // indirect + go.opentelemetry.io/collector/internal/telemetry v0.122.1 // indirect go.opentelemetry.io/collector/pdata v1.28.1 // indirect - go.opentelemetry.io/collector/pdata/pprofile v0.122.0 // indirect - go.opentelemetry.io/collector/pdata/testdata v0.122.0 // indirect - go.opentelemetry.io/collector/pipeline/xpipeline v0.122.0 // indirect - go.opentelemetry.io/collector/processor v0.122.0 // indirect - go.opentelemetry.io/collector/processor/processortest v0.122.0 // indirect - go.opentelemetry.io/collector/processor/xprocessor v0.122.0 // indirect - go.opentelemetry.io/collector/receiver v1.28.0 // indirect - go.opentelemetry.io/collector/receiver/receivertest v0.122.0 // indirect - go.opentelemetry.io/collector/receiver/xreceiver v0.122.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.122.1 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.122.1 // indirect + go.opentelemetry.io/collector/pipeline/xpipeline v0.122.1 // indirect + go.opentelemetry.io/collector/processor v0.122.1 // indirect + go.opentelemetry.io/collector/processor/processortest v0.122.1 // indirect + go.opentelemetry.io/collector/processor/xprocessor v0.122.1 // indirect + go.opentelemetry.io/collector/receiver v1.28.1 // indirect + go.opentelemetry.io/collector/receiver/receivertest v0.122.1 // indirect + go.opentelemetry.io/collector/receiver/xreceiver v0.122.1 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.10.0 // indirect go.opentelemetry.io/contrib/otelconf v0.15.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.35.0 // indirect diff --git a/go.sum b/go.sum index 0773d523b6..b8b610d06e 100644 --- a/go.sum +++ b/go.sum @@ -183,82 +183,82 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/collector v0.122.0 h1:eir4Fvv2tz5tUvPBTvFk8VmqeihYcTuYD6AXllvxxIg= -go.opentelemetry.io/collector v0.122.0/go.mod h1:8t7TFg4nQHskvaOZrbfqAprB3r6+SZ2GQ2NYua0HEtg= +go.opentelemetry.io/collector v0.122.1 h1:CfjBnpaaE261Y1IeE+71VuGKC/AGGRz2R9kum9DpY1I= +go.opentelemetry.io/collector v0.122.1/go.mod h1:8t7TFg4nQHskvaOZrbfqAprB3r6+SZ2GQ2NYua0HEtg= go.opentelemetry.io/collector/component v1.28.1 h1:JjwfvLR0UdadRDAANAdM4mOSwGmfGO3va2X+fdk4YdA= go.opentelemetry.io/collector/component v1.28.1/go.mod h1:jwZRDML3tXo1whueZdRf+y6z3DeEYTLPBmb/O1ujB40= -go.opentelemetry.io/collector/component/componentstatus v0.122.0 h1:gzqsfL8IN+bwlByl76MNFIDtq0jc9Y671NoZQGAiupg= -go.opentelemetry.io/collector/component/componentstatus v0.122.0/go.mod h1:d4WiL3UHQFIh7WN4miV5aupTZK3kFRt4xfzhsyTEMN4= -go.opentelemetry.io/collector/component/componenttest v0.122.0 h1:TxMm4nXB9iByQhDP0QFZwYxG+BFXEB6qUUwVh5YYW7g= -go.opentelemetry.io/collector/component/componenttest v0.122.0/go.mod h1:zzRftQeGgVPxKzXkJEx3ghC4U3hgiDRuuNljsq3cLPI= -go.opentelemetry.io/collector/config/configretry v1.28.0 h1:UqdSd+909bM9nC0eGcQvbTUdPQbEVJYDVjScFie5xFc= -go.opentelemetry.io/collector/config/configretry v1.28.0/go.mod h1:QNnb+MCk7aS1k2EuGJMtlNCltzD7b8uC7Xel0Dxm1wQ= -go.opentelemetry.io/collector/config/configtelemetry v0.122.0 h1:jBPdzU0CVrlxttnfKa0s2kyMVJeHY/faBht6/FUQcWI= -go.opentelemetry.io/collector/config/configtelemetry v0.122.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= +go.opentelemetry.io/collector/component/componentstatus v0.122.1 h1:zMQC0y8ZBITa87GOwEANdOoAox5I4UgaIHxY79nwCbk= +go.opentelemetry.io/collector/component/componentstatus v0.122.1/go.mod h1:ZYwOgoXyPu4gGqfQ5DeaEpStpUCD/Clctz4rMd9qQYw= +go.opentelemetry.io/collector/component/componenttest v0.122.1 h1:HE4oeLub2FWVTUzCQG6SWwfnJfcK1FMknXhGQ2gOxnY= +go.opentelemetry.io/collector/component/componenttest v0.122.1/go.mod h1:o3Xq6z3C0aVhrd/fD56aKxShrILVnHnbgQVP5NoFuic= +go.opentelemetry.io/collector/config/configretry v1.28.1 h1:WVRw9neCAsWilZU9C4ZzXeQLw1L3dIRlCIqReqhzi70= +go.opentelemetry.io/collector/config/configretry v1.28.1/go.mod h1:QNnb+MCk7aS1k2EuGJMtlNCltzD7b8uC7Xel0Dxm1wQ= +go.opentelemetry.io/collector/config/configtelemetry v0.122.1 h1:WABfddVAhIn5ZrTdisn6fOBufyYT/xYhKg6U0yYWQLA= +go.opentelemetry.io/collector/config/configtelemetry v0.122.1/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= go.opentelemetry.io/collector/confmap v1.28.1 h1:/zUmvpnERhFXrxVCVgubjJRgeOwdPbhTfUILZPUBfyw= go.opentelemetry.io/collector/confmap v1.28.1/go.mod h1:2aJggo/KQl7uynFyMNNMbl7jvKkSD7CniOVEpCbjRng= -go.opentelemetry.io/collector/confmap/xconfmap v0.122.0 h1:uRwR2/DEhLCwsdQyD5rTG/cAPUm5ixZb96y3rUaUo/g= -go.opentelemetry.io/collector/confmap/xconfmap v0.122.0/go.mod h1:76K9ypccfRyorlYYit8O82mX4hseQP8VJ/TYqCKI4fA= -go.opentelemetry.io/collector/connector v0.122.0 h1:VrILgvrE4PWuJzPfB2lj+wxqRK8+SnnFFB9Ft9G1Tok= -go.opentelemetry.io/collector/connector v0.122.0/go.mod h1:ppWh+4gDym2C/zZ4ygID7DMZxVJyyvy1is415attDjA= -go.opentelemetry.io/collector/connector/connectortest v0.122.0 h1:7kwexYryefADAP/eG9v3ycqIxgQh6qgmMlsjkgcBW34= -go.opentelemetry.io/collector/connector/connectortest v0.122.0/go.mod h1:UxShMFmkmjwimWqlkRiDoVxyYMxk3ZQaoWsWb7Oe9is= -go.opentelemetry.io/collector/connector/xconnector v0.122.0 h1:D0e/ZbDhIJA8harTulMilhSG/yqQmi/k/yaLbGiPeH8= -go.opentelemetry.io/collector/connector/xconnector v0.122.0/go.mod h1:gjFaSA5EZxOqzhoLrcf7Pj+U4sB60GcKIZYGaNvQ1jQ= -go.opentelemetry.io/collector/consumer v1.28.0 h1:3JzDm7EFAF9ws4O3vVou5n8egdGZtrRN3xVw6AjNtqE= -go.opentelemetry.io/collector/consumer v1.28.0/go.mod h1:Ge1HGm5aRYTW+SXggM+US9phb/BQR2of4FZ8r/3OH3Y= -go.opentelemetry.io/collector/consumer/consumererror v0.122.0 h1:IoCEQE0xqNVsH7wOwmBBLR0W/+p8QFjYwNlZTrhztvM= -go.opentelemetry.io/collector/consumer/consumererror v0.122.0/go.mod h1:8RPibMrh84PHzqGchjiKIRz4eqdylMg8boLwMJY3WjU= -go.opentelemetry.io/collector/consumer/consumertest v0.122.0 h1:nV/qmUNRJZX+Eof963k+ShYy06DtQxMvP62nrXM8JJk= -go.opentelemetry.io/collector/consumer/consumertest v0.122.0/go.mod h1:D7qDviTkrXfYigmSF4A8K7vQtb5ec/TVJsCNlVLIhxY= -go.opentelemetry.io/collector/consumer/xconsumer v0.122.0 h1:7IyhI81BOf0YfsoI83/s7/muf7frkmgiX/FsFfZApq0= -go.opentelemetry.io/collector/consumer/xconsumer v0.122.0/go.mod h1:+kN4ZwuJTLlLdtH+DkUyXqT/zQFMktbWFIdVqfmSWRY= -go.opentelemetry.io/collector/exporter v0.122.0 h1:Y1ZigdLwHrN1/VA+P3lYrnM2gAmo/tQxHVxdfg+489U= -go.opentelemetry.io/collector/exporter v0.122.0/go.mod h1:xtoCOeeGpZgcvMX8Od+HLBgDGqUstIii/NQXXjEkNR0= -go.opentelemetry.io/collector/exporter/exportertest v0.122.0 h1:NfhUI8OocfhLCpIuNlS9yx1Lt/Vmmn97Z8JnId+qVKw= -go.opentelemetry.io/collector/exporter/exportertest v0.122.0/go.mod h1:1ntDyuDvpiqJH/YyQ4uvfePESaJm0g2D77syBkLAmmg= -go.opentelemetry.io/collector/exporter/xexporter v0.122.0 h1:fd+IEFSNZoUa/3Z8eNLPKqOkeh7nEV6qTlqoFzt+uD0= -go.opentelemetry.io/collector/exporter/xexporter v0.122.0/go.mod h1:pRqtMIBLcnUsyMwaIjUz//0fKWj+9VXOA+tUGnS9DDQ= -go.opentelemetry.io/collector/extension v1.28.0 h1:E3j6/EtcahF2bX9DvRduLQ6tD7SuZdXM9DzAi7NSAeY= -go.opentelemetry.io/collector/extension v1.28.0/go.mod h1:3MW9IGCNNgjG/ngkALVH5epwbCwYuoZMTbh4523aYv0= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.0 h1:ecxODEslQT87P82n1bWzVaVyj57OAwxh56RxLL1fyxc= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.0/go.mod h1:0Sl5KgS06MdhvFog9JOHLl8SnZLmDQwgcA0IhYoAuxo= -go.opentelemetry.io/collector/extension/extensiontest v0.122.0 h1:daeCPXhb4HveyeYyX6G0IqjGuvWJprZeiq7pZiSdC+M= -go.opentelemetry.io/collector/extension/extensiontest v0.122.0/go.mod h1:JXSONLbyuX+uOy1gcQ3Jcp/48pfkh0RiZPy7XkyCBdU= -go.opentelemetry.io/collector/extension/xextension v0.122.0 h1:EoPcWm69j0OZCyKvZ0H0KfkLRKZyry678852ua7k+DI= -go.opentelemetry.io/collector/extension/xextension v0.122.0/go.mod h1:hdkdi0cGk3X1+9M0IS1LJ8dhlnEKhqHd2HMdc2ata5A= +go.opentelemetry.io/collector/confmap/xconfmap v0.122.1 h1:E8sdJens/sq+evv/VHzbDP3B28uZIAPkKjtB4mVVTso= +go.opentelemetry.io/collector/confmap/xconfmap v0.122.1/go.mod h1:33HDN5uVKRihgLiShZZDzxN0qiTA1+t8hK41rrf1jls= +go.opentelemetry.io/collector/connector v0.122.1 h1:E0qzq1YyT4gfUr961bPGZhYObvBTsWlgqY37XzDPRJo= +go.opentelemetry.io/collector/connector v0.122.1/go.mod h1:ia6ams3PZGjAMXSXT0hm3cQb8MZ3x58zIR3+5eQhzs0= +go.opentelemetry.io/collector/connector/connectortest v0.122.1 h1:RgSAFzR/Wh/QF8DG1r/9/N7g7OJlu8nba4DBRvvTr00= +go.opentelemetry.io/collector/connector/connectortest v0.122.1/go.mod h1:IzWDkmJvf2HN3dmOR/g0xY5T8cmjB6KPLBCHx9sfVnw= +go.opentelemetry.io/collector/connector/xconnector v0.122.1 h1:yhMXzvi0gd/kbq4gaG+0ozeRfIJCHVunKS/JW2a8j5c= +go.opentelemetry.io/collector/connector/xconnector v0.122.1/go.mod h1:25VAcwl0MAAsKDcN3Xi7ZbLn9AVmX/zuWOSsxoqz1C0= +go.opentelemetry.io/collector/consumer v1.28.1 h1:3lHW2e0i7kEkbDqK1vErA8illqPpwDxMzgc5OUDsJ0Y= +go.opentelemetry.io/collector/consumer v1.28.1/go.mod h1:g0T16JPMYFN6T2noh+1YBxJSt5i5Zp+Y0Y6pvkMqsDQ= +go.opentelemetry.io/collector/consumer/consumererror v0.122.1 h1:/eL7rtfnKUMgjtiD+NXm6hd3QQ+tjD1oGc+ImPxFdIg= +go.opentelemetry.io/collector/consumer/consumererror v0.122.1/go.mod h1:sQ4liQ7KVpZAz0KXm7q1cCoeL6YY6C9Nxmut7Js42dY= +go.opentelemetry.io/collector/consumer/consumertest v0.122.1 h1:LKkLMdWwJCuOYyCMVzwc0OG9vncIqpl8Tp9+H8RikNg= +go.opentelemetry.io/collector/consumer/consumertest v0.122.1/go.mod h1:pYqWgx62ou3uUn8nlt2ohRyKod+7xLTf/uA3YfRwVkA= +go.opentelemetry.io/collector/consumer/xconsumer v0.122.1 h1:iK1hGbho/XICdBfGb4MnKwF9lnhLmv09yQ4YlVm+LGo= +go.opentelemetry.io/collector/consumer/xconsumer v0.122.1/go.mod h1:xYbRPP1oWcYUUDQJTlv78M/rlYb+qE4weiv++ObZRSU= +go.opentelemetry.io/collector/exporter v0.122.1 h1:Yr8gmIQWb9Zylr2Al69k0BhCNlWIae1xPZz01zDyAZM= +go.opentelemetry.io/collector/exporter v0.122.1/go.mod h1:CiIgKR/LG7oq+bogywL2zKkGtikiGyo3zTQaMGZNqDI= +go.opentelemetry.io/collector/exporter/exportertest v0.122.1 h1:izA26/JnJ819BOws089MJjo7oQB+uuM07Htfo8uE+Q4= +go.opentelemetry.io/collector/exporter/exportertest v0.122.1/go.mod h1:/usnN6Vl3jJL6Vo9U9x/FKmAv1l0DofnKIYAOzJmrVU= +go.opentelemetry.io/collector/exporter/xexporter v0.122.1 h1:SJt9kiCEyXAxyGWA4tBt1hqydmqVco9KDg9SkH4p7/o= +go.opentelemetry.io/collector/exporter/xexporter v0.122.1/go.mod h1:5cgaRnGaWp0VtPbrTIIU717Eu4rW7kj1L8KluFlPPp0= +go.opentelemetry.io/collector/extension v1.28.1 h1:2qiX/nuihDzHMmOxrVKZ5SURFL/oJBMlL6+kPDvb0+I= +go.opentelemetry.io/collector/extension v1.28.1/go.mod h1:IaovGuJib5XGgLejcBmpgwFS5/mCV4xnW/J2Towy5lM= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.1 h1:dl6IdeQ7kOCESkcidXL6mbsUm1JcHC+JepqdNoiWlDc= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.1/go.mod h1:BGX52Iu/y9Sunfm/7BTwPcgZiSO3N+4qRDKkFlcZXsw= +go.opentelemetry.io/collector/extension/extensiontest v0.122.1 h1:Rc5XZSY8HEb0x3RDnnNKk2VuvYkmx209dahs0JGFMJY= +go.opentelemetry.io/collector/extension/extensiontest v0.122.1/go.mod h1:fdsJ3X45rU5CeCWk8hscVrbr7u5MdO3DnnKCVWTMDEc= +go.opentelemetry.io/collector/extension/xextension v0.122.1 h1:U7Ryv25DC+wzJq6xcveZFmWEnOwwFSJAcH2nr2tw3vI= +go.opentelemetry.io/collector/extension/xextension v0.122.1/go.mod h1:gXcwe6qono7zK4/RyKn0j47qWz204IcRyMqa47GO360= go.opentelemetry.io/collector/featuregate v1.28.1 h1:ZpvRAAFxxi4RLr1G0Fju28wA7NhTA20MNT60Ftv+ToY= go.opentelemetry.io/collector/featuregate v1.28.1/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0 h1:Oup8r2FaIEi7si3Kz7ybSgeNh6TrQFNJ9I7bNNdgJ0o= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.0/go.mod h1:02AWRtzi/v9P2ldMdQq5+OKKoqIVPdqZQ/B3KKNu/So= -go.opentelemetry.io/collector/internal/telemetry v0.122.0 h1:5RCl/CdT3+VaduRI5IphoH3xS49sHZmEY/y3N3CEZjs= -go.opentelemetry.io/collector/internal/telemetry v0.122.0/go.mod h1:FrmVXPmQMn3BuGIWg/pOdmHTMvXmlNzcbMusn8SSZn4= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.1 h1:AphjgdUrg/SNIXAHJASVWFWQDYszn3zS9+P1tJHSdAU= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.1/go.mod h1:jfe5dOMrkoWOJK6D9yTQjDEaOhBOkjcy3sKX6KBBT9c= +go.opentelemetry.io/collector/internal/telemetry v0.122.1 h1:bB5yb/JECih7Nqrfu9+AtBasGioyiy3rBrAMLbcyaXQ= +go.opentelemetry.io/collector/internal/telemetry v0.122.1/go.mod h1:Qor+QXnQN+UYUdD2qtglBdH3y0xoXlcONnx2FnvjAL0= go.opentelemetry.io/collector/pdata v1.28.1 h1:ORl5WLpQJvjzBVpHu12lqKMdcf/qDBwRXMcUubhybiQ= go.opentelemetry.io/collector/pdata v1.28.1/go.mod h1:asKE8MD/4SOKz1mCrGdAz4VO2U2HUNg8A6094uK7pq0= -go.opentelemetry.io/collector/pdata/pprofile v0.122.0 h1:JcmYBmNNOKRO7mIBxJ79YKgrTowILCCcpxKorDBfFOs= -go.opentelemetry.io/collector/pdata/pprofile v0.122.0/go.mod h1:miIYvmTQov3C2/D7T0nRMndhavG4tPqz3llKMdLjSwg= -go.opentelemetry.io/collector/pdata/testdata v0.122.0 h1:ANXZ+h9yAy1N37ot407qnMtISjZIgjYk10atzD7wSKI= -go.opentelemetry.io/collector/pdata/testdata v0.122.0/go.mod h1:5WxeLDGisczRoS5lnxyt0PqGI3tr2QnhxUHupGrDY64= +go.opentelemetry.io/collector/pdata/pprofile v0.122.1 h1:25Fs0eL/J/M2ZEaVplesbI1H7pYx462zUUVxVOszpOg= +go.opentelemetry.io/collector/pdata/pprofile v0.122.1/go.mod h1:+jSjgb4zRnNmr1R/zgVLVyTVSm9irfGrvGTrk3lDxSE= +go.opentelemetry.io/collector/pdata/testdata v0.122.1 h1:9DO8nUUnPAGYMKmrep6wLAfOHprvKY4w/7LpE4jldPQ= +go.opentelemetry.io/collector/pdata/testdata v0.122.1/go.mod h1:hYdNrn8KxFwq1nf44YYRgNhDjJTBzoyEr/Qa26pN0t4= go.opentelemetry.io/collector/pipeline v0.122.1 h1:f0uuiDmanVyKwfYo6cWveJsGbLXidV7i+Z7u8QJwWxI= go.opentelemetry.io/collector/pipeline v0.122.1/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= -go.opentelemetry.io/collector/pipeline/xpipeline v0.122.0 h1:Zu6zvO/6epvsjZ74t7qAiMowqhScxHZURlBzBaJ00iY= -go.opentelemetry.io/collector/pipeline/xpipeline v0.122.0/go.mod h1:uBWsvO37xU8cPgG8znDMW7bIwzrwRQ0jQ0u05rFeB/g= -go.opentelemetry.io/collector/processor v0.122.0 h1:elkgJhXhzwrvycbMGQzLOGNwGURaQZNAx1VB8lh9uq8= -go.opentelemetry.io/collector/processor v0.122.0/go.mod h1:jWan7IwasdpUA9GQGyicw5MDJOfqoiTnez+xkT7GCu8= -go.opentelemetry.io/collector/processor/processortest v0.122.0 h1:UHJwvmIzGoi6U4p6UyaZUGOI3lx1seHh1b+ukVyZ3Wg= -go.opentelemetry.io/collector/processor/processortest v0.122.0/go.mod h1:iK3qMnIkby7f0QCz0876mD7Wpuhxertg6zvZL5lRtdI= -go.opentelemetry.io/collector/processor/xprocessor v0.122.0 h1:hXl4Ttp1Ycqf2rIDQnIW9bMmq01sF2Jb+aEWJ7rtaDU= -go.opentelemetry.io/collector/processor/xprocessor v0.122.0/go.mod h1:Kh9zGutW9Smqsi+FWimlTmLl9czi6WgG7JclMB44sqA= -go.opentelemetry.io/collector/receiver v1.28.0 h1:yvAUb+QTdkhIuUVY5wGUPyXqIylIttGpt+k+1b77jic= -go.opentelemetry.io/collector/receiver v1.28.0/go.mod h1:ceNMHvsSkFOHK80UkQd5kdrU3Qq7NA+dS7oc6C4zLRc= -go.opentelemetry.io/collector/receiver/receivertest v0.122.0 h1:qBy1XbddIQRvslmS1WXhTnjzOIwuLBTbp8CGN8atNKk= -go.opentelemetry.io/collector/receiver/receivertest v0.122.0/go.mod h1:zuB9o86N1UFgauDS9cHT8vHWQVggNRcyinwRZZv5Z9A= -go.opentelemetry.io/collector/receiver/xreceiver v0.122.0 h1:rAWEMR/TDu+a9ATGIec4m9swVT0KvimUQqZpOLgTCVM= -go.opentelemetry.io/collector/receiver/xreceiver v0.122.0/go.mod h1:LLMY2gDtQCieYEOa5h6heHv+FMkC+b1u/yUXRJvwrEo= -go.opentelemetry.io/collector/semconv v0.122.0 h1:MsPT+/vmQ1iVc4wEVgyRIxi4Pc0KUxc/mjoJsPrfH0k= -go.opentelemetry.io/collector/semconv v0.122.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= -go.opentelemetry.io/collector/service v0.122.0 h1:OPDNiuGTHYj0B3ozeC5IV6wNDmgp0j2RlyEsPbSS0o0= -go.opentelemetry.io/collector/service v0.122.0/go.mod h1:ffOT//Aa8i/cg3Vy//BeqKV9W7EYJ06n0MmrY2h/7C0= +go.opentelemetry.io/collector/pipeline/xpipeline v0.122.1 h1:WhMVlMRjQoiu2k9/Haudy7VoDT4gismQzl1ZDxwvHQY= +go.opentelemetry.io/collector/pipeline/xpipeline v0.122.1/go.mod h1:arZHihE9qPJ4WVWPUsSqUovhQdWZtOGLg2E/QKxbz7M= +go.opentelemetry.io/collector/processor v0.122.1 h1:AvZvEujq8+FYdJsm9lmAMwuuae5Y2/vKIkOJwsoxsxQ= +go.opentelemetry.io/collector/processor v0.122.1/go.mod h1:nYKctftba7SbdLml6LxgIrnYRXCShDe2bnNWjTIpF7g= +go.opentelemetry.io/collector/processor/processortest v0.122.1 h1:n4UOx1mq+kLaRiHGsu7vBLq+EGXfzWhSxyFweMjMl54= +go.opentelemetry.io/collector/processor/processortest v0.122.1/go.mod h1:8/NRWx18tNJMBwCQ8/YPWr4qsFUrwk27qE7/dXoJb1M= +go.opentelemetry.io/collector/processor/xprocessor v0.122.1 h1:Wfv4/7n4YK1HunAVTMS6yf0xmDjCkftJ6EECNcSwzfs= +go.opentelemetry.io/collector/processor/xprocessor v0.122.1/go.mod h1:9zMW3NQ9+DzcJ1cUq5BhZg3ajoUEMGhNY0ZdYjpX+VI= +go.opentelemetry.io/collector/receiver v1.28.1 h1:5Aw0qQVs+CcmY/YkiwPUq4+9BoLCMNv9GlL6uTOVIDw= +go.opentelemetry.io/collector/receiver v1.28.1/go.mod h1:i2Wj7MDpFnBagjFrglUssY9+tFsIThlnmK+a9JN2dzY= +go.opentelemetry.io/collector/receiver/receivertest v0.122.1 h1:QVkiAi7Pw+SrnY8zX+948W5TSsWLxuDvcuu7meOFbs4= +go.opentelemetry.io/collector/receiver/receivertest v0.122.1/go.mod h1:r++3FwxXK2hkTNaNVIwLPJkHP3iZdz9+dFsuocGpaLc= +go.opentelemetry.io/collector/receiver/xreceiver v0.122.1 h1:Mhh54HngMsJPg655MMsydJAt+rrmO3E/SIcaedP3ksQ= +go.opentelemetry.io/collector/receiver/xreceiver v0.122.1/go.mod h1:DdY1kn+y755wtelfTwv4/7WVK5caHwoW+X4oQ/OyMXc= +go.opentelemetry.io/collector/semconv v0.122.1 h1:WLzDi3QC4/+LpNMLY90zn5aMDJKyqg/ujW2O4T4sxHg= +go.opentelemetry.io/collector/semconv v0.122.1/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= +go.opentelemetry.io/collector/service v0.122.1 h1:JmogPurZ93XZJGIaortQnHmdo0/o8u01UiCL4cjNkZw= +go.opentelemetry.io/collector/service v0.122.1/go.mod h1:GwhQsH58lxxTCj8OUEIMruw6ACF5G8cs9CRl2l2nlz0= go.opentelemetry.io/contrib/bridges/otelzap v0.10.0 h1:ojdSRDvjrnm30beHOmwsSvLpoRF40MlwNCA+Oo93kXU= go.opentelemetry.io/contrib/bridges/otelzap v0.10.0/go.mod h1:oTTm4g7NEtHSV2i/0FeVdPaPgUIZPfQkFbq0vbzqnv0= go.opentelemetry.io/contrib/otelconf v0.15.0 h1:BLNiIUsrNcqhSKpsa6CnhE6LdrpY1A8X0szMVsu99eo= From 2f8f763ab979afa8d93306f4cde2ebfa7c985b7d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 10:39:33 +0000 Subject: [PATCH 339/426] chore(deps): update actions/setup-go action to v5.4.0 (main) (#4623) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- .github/actions/run-e2e/action.yaml | 2 +- .github/workflows/ci.yaml | 6 +++--- .github/workflows/release.yaml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index a091529a9d..e7d973c2ea 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -18,7 +18,7 @@ runs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - name: Set up Golang - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Prepare build parameters diff --git a/.github/actions/run-e2e/action.yaml b/.github/actions/run-e2e/action.yaml index 5f4254a17c..4423a4304e 100644 --- a/.github/actions/run-e2e/action.yaml +++ b/.github/actions/run-e2e/action.yaml @@ -50,7 +50,7 @@ runs: - name: Set up kubectl uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f # v4.0.0 - name: Set up go - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: go-version-file: "${{ github.workspace }}/target/go.mod" - name: Set up helm diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fbaca8e3de..2193660b9a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -54,7 +54,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Golang - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run Unit tests and Integration tests @@ -82,7 +82,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint @@ -102,7 +102,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Set up Helm diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 10d3273ed4..481b913d7a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -45,7 +45,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Golang - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Prepare SBOM # Needs setup-go, uses a binary installed via `go install` @@ -294,7 +294,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Golang - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: go-version-file: "${{ github.workspace }}/go.mod" - name: Generate release notes From 6ab54a99dc29a13e8f94ea34ff2e6e9470c38df2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 13:14:38 +0000 Subject: [PATCH 340/426] chore(deps): update github/codeql-action action to v3.28.12 (main) (#4625) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index be61997a27..d501b4c0f2 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/init@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/autobuild@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/analyze@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 7255650d2a..08b40d4146 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/upload-sarif@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12 with: sarif_file: results.sarif From 1f05169648ddfe050b3d994d4950e5074b261b1b Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Wed, 19 Mar 2025 14:56:15 +0100 Subject: [PATCH 341/426] Rename OTelC StatefulSet, rename OTelC template section. (#4614) --- config/crd/bases/dynatrace.com_dynakubes.yaml | 4 +-- .../Common/crd/dynatrace-operator-crd.yaml | 4 +-- doc/api/dynakube-api-ref.md | 30 +++++++++---------- pkg/api/v1beta3/dynakube/dynakube_types.go | 2 +- pkg/api/v1beta4/dynakube/dynakube_types.go | 2 +- pkg/api/v1beta4/dynakube/otelc_props.go | 2 +- .../dynakube/otelc/statefulset/env_test.go | 4 +-- .../dynakube/otelc/statefulset/reconciler.go | 2 +- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index 535db8124c..3fa148f9db 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -7112,7 +7112,7 @@ spec: type: object type: array type: object - openTelemetryCollector: + otelCollector: properties: annotations: additionalProperties: @@ -10533,7 +10533,7 @@ spec: type: object type: array type: object - openTelemetryCollector: + otelCollector: properties: annotations: additionalProperties: diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 483afd2de4..da5fcf4271 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -7124,7 +7124,7 @@ spec: type: object type: array type: object - openTelemetryCollector: + otelCollector: properties: annotations: additionalProperties: @@ -10545,7 +10545,7 @@ spec: type: object type: array type: object - openTelemetryCollector: + otelCollector: properties: annotations: additionalProperties: diff --git a/doc/api/dynakube-api-ref.md b/doc/api/dynakube-api-ref.md index 01b7c25b9c..1d6d82a509 100644 --- a/doc/api/dynakube-api-ref.md +++ b/doc/api/dynakube-api-ref.md @@ -97,6 +97,18 @@ |`secCompProfile`|The SecComp Profile that will be configured in order to run in secure computing mode for the LogMonitoring pods|-|string| |`tolerations`|Set tolerations for the LogMonitoring pods|-|array| +### .spec.templates.otelCollector + +|Parameter|Description|Default value|Data type| +|:-|:-|:-|:-| +|`annotations`|Adds additional annotations to the OtelCollector pods|-|object| +|`labels`|Adds additional labels for the OtelCollector pods|-|object| +|`replicas`|Number of replicas for your OtelCollector|-|integer| +|`resources`|Define resources' requests and limits for single OtelCollector pod|-|object| +|`tlsRefName`||-|string| +|`tolerations`|Set tolerations for the OtelCollector pods|-|array| +|`topologySpreadConstraints`|Adds TopologySpreadConstraints for the OtelCollector pods|-|array| + ### .spec.oneAgent.classicFullStack |Parameter|Description|Default value|Data type| @@ -167,17 +179,12 @@ |`repository`|Custom image repository|-|string| |`tag`|Indicates a tag of the image to use|-|string| -### .spec.templates.openTelemetryCollector +### .spec.templates.otelCollector.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Adds additional annotations to the OtelCollector pods|-|object| -|`labels`|Adds additional labels for the OtelCollector pods|-|object| -|`replicas`|Number of replicas for your OtelCollector|-|integer| -|`resources`|Define resources' requests and limits for single OtelCollector pod|-|object| -|`tlsRefName`||-|string| -|`tolerations`|Set tolerations for the OtelCollector pods|-|array| -|`topologySpreadConstraints`|Adds TopologySpreadConstraints for the OtelCollector pods|-|array| +|`repository`|Custom image repository|-|string| +|`tag`|Indicates a tag of the image to use|-|string| ### .spec.templates.extensionExecutionController @@ -206,13 +213,6 @@ |`resources`|Define resources' requests and limits for single NodeConfigurationCollector pod|-|object| |`tolerations`|Set tolerations for the NodeConfigurationCollector pods|-|array| -### .spec.templates.openTelemetryCollector.imageRef - -|Parameter|Description|Default value|Data type| -|:-|:-|:-|:-| -|`repository`|Custom image repository|-|string| -|`tag`|Indicates a tag of the image to use|-|string| - ### .spec.activeGate.persistentVolumeClaim.dataSourceRef |Parameter|Description|Default value|Data type| diff --git a/pkg/api/v1beta3/dynakube/dynakube_types.go b/pkg/api/v1beta3/dynakube/dynakube_types.go index 362656a3ba..0775e188bb 100644 --- a/pkg/api/v1beta3/dynakube/dynakube_types.go +++ b/pkg/api/v1beta3/dynakube/dynakube_types.go @@ -154,7 +154,7 @@ type TemplatesSpec struct { // +kubebuilder:validation:Optional KspmNodeConfigurationCollector kspm.NodeConfigurationCollectorSpec `json:"kspmNodeConfigurationCollector,omitempty"` // +kubebuilder:validation:Optional - OpenTelemetryCollector OpenTelemetryCollectorSpec `json:"openTelemetryCollector,omitempty"` + OpenTelemetryCollector OpenTelemetryCollectorSpec `json:"otelCollector,omitempty"` // +kubebuilder:validation:Optional ExtensionExecutionController ExtensionExecutionControllerSpec `json:"extensionExecutionController,omitempty"` } diff --git a/pkg/api/v1beta4/dynakube/dynakube_types.go b/pkg/api/v1beta4/dynakube/dynakube_types.go index 7779b12dc6..51d99d4169 100644 --- a/pkg/api/v1beta4/dynakube/dynakube_types.go +++ b/pkg/api/v1beta4/dynakube/dynakube_types.go @@ -162,7 +162,7 @@ type TemplatesSpec struct { // +kubebuilder:validation:Optional KspmNodeConfigurationCollector kspm.NodeConfigurationCollectorSpec `json:"kspmNodeConfigurationCollector,omitempty"` // +kubebuilder:validation:Optional - OpenTelemetryCollector OpenTelemetryCollectorSpec `json:"openTelemetryCollector,omitempty"` + OpenTelemetryCollector OpenTelemetryCollectorSpec `json:"otelCollector,omitempty"` // +kubebuilder:validation:Optional ExtensionExecutionController ExtensionExecutionControllerSpec `json:"extensionExecutionController,omitempty"` } diff --git a/pkg/api/v1beta4/dynakube/otelc_props.go b/pkg/api/v1beta4/dynakube/otelc_props.go index a9ef0c1cc3..2c7ba5787a 100644 --- a/pkg/api/v1beta4/dynakube/otelc_props.go +++ b/pkg/api/v1beta4/dynakube/otelc_props.go @@ -1,7 +1,7 @@ package dynakube func (dk *DynaKube) OtelCollectorStatefulsetName() string { - return dk.Name + "-extensions-collector" + return dk.Name + "-otel-collector" } func (dk *DynaKube) IsAGCertificateNeeded() bool { diff --git a/pkg/controllers/dynakube/otelc/statefulset/env_test.go b/pkg/controllers/dynakube/otelc/statefulset/env_test.go index f0716af98d..bcb14b332a 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env_test.go @@ -19,7 +19,7 @@ func TestEnvironmentVariables(t *testing.T) { statefulSet := getStatefulset(t, dk) assert.Equal(t, corev1.EnvVar{Name: envShards, Value: fmt.Sprintf("%d", getReplicas(dk))}, statefulSet.Spec.Template.Spec.Containers[0].Env[0]) - assert.Equal(t, corev1.EnvVar{Name: envPodNamePrefix, Value: dk.Name + "-extensions-collector"}, statefulSet.Spec.Template.Spec.Containers[0].Env[1]) + assert.Equal(t, corev1.EnvVar{Name: envPodNamePrefix, Value: dk.Name + "-otel-collector"}, statefulSet.Spec.Template.Spec.Containers[0].Env[1]) assert.Equal(t, corev1.EnvVar{Name: envPodName, ValueFrom: &corev1.EnvVarSource{ FieldRef: &corev1.ObjectFieldSelector{ FieldPath: "metadata.labels['statefulset.kubernetes.io/pod-name']", @@ -69,7 +69,7 @@ func TestEnvironmentVariables(t *testing.T) { assert.Len(t, statefulSet.Spec.Template.Spec.Containers[0].Env, 12) assert.Equal(t, corev1.EnvVar{Name: envShards, Value: fmt.Sprintf("%d", getReplicas(dk))}, statefulSet.Spec.Template.Spec.Containers[0].Env[0]) - assert.Equal(t, corev1.EnvVar{Name: envPodNamePrefix, Value: dk.Name + "-extensions-collector"}, statefulSet.Spec.Template.Spec.Containers[0].Env[1]) + assert.Equal(t, corev1.EnvVar{Name: envPodNamePrefix, Value: dk.Name + "-otel-collector"}, statefulSet.Spec.Template.Spec.Containers[0].Env[1]) assert.Equal(t, corev1.EnvVar{Name: envPodName, ValueFrom: &corev1.EnvVarSource{ FieldRef: &corev1.ObjectFieldSelector{ FieldPath: "metadata.labels['statefulset.kubernetes.io/pod-name']", diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go index 88d8444bbe..385053e9f7 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go @@ -76,7 +76,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { func (r *Reconciler) createOrUpdateStatefulset(ctx context.Context) error { if r.dk.TelemetryIngest().IsEnabled() { if !r.checkDataIngestTokenExists(ctx) { - msg := "data ingest token is missing, but it's required for otel controller" + msg := "data ingest token is missing, but it's required for telemetery ingest" conditions.SetDataIngestTokenMissing(r.dk.Conditions(), dynakube.TokenConditionType, msg) log.Error(errors.New(msg), "could not create or update statefulset") From b88df560124341db53c37d1c86d75ac4623d2945 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Wed, 19 Mar 2025 15:28:27 +0100 Subject: [PATCH 342/426] Validate all node-image-pull scenarios (#4615) --- pkg/api/validation/dynakube/oneagent.go | 8 ++-- pkg/api/validation/dynakube/oneagent_test.go | 40 ++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index af718ea8ff..8758e4a9b0 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -19,7 +19,7 @@ const ( errorImageFieldSetWithoutCSIFlag = `The DynaKube specification attempts to enable ApplicationMonitoring mode and retrieve the respective image, but the CSI driver and/or node image pull is not enabled.` - errorBootstrapperNodeImagePullRequiresCodeModulesImage = `The DynaKube specification enables node image pull, but the code modules image is not set.` + errorImagePullRequiresCodeModulesImage = `The DynaKube specification enables node image pull, but the code modules image is not set.` errorNodeSelectorConflict = `The Dynakube specification conflicts with another Dynakube's OneAgent or Standalone-LogMonitoring. Only one Agent per node is supported. Use a nodeSelector to avoid this conflict. Conflicting DynaKubes: %s` @@ -156,8 +156,10 @@ func imageFieldSetWithoutCSIFlag(_ context.Context, v *Validator, dk *dynakube.D } func missingCodeModulesImage(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { - if dk.FeatureBootstrapperInjection() && len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) == 0 { - return errorBootstrapperNodeImagePullRequiresCodeModulesImage + if dk.OneAgent().IsAppInjectionNeeded() && + dk.FeatureNodeImagePull() && + len(dk.OneAgent().GetCustomCodeModulesImage()) == 0 { + return errorImagePullRequiresCodeModulesImage } return "" diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index 39f4172924..fcbe40bd0c 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -356,6 +356,46 @@ func TestImageFieldSetWithoutCSIFlag(t *testing.T) { }, }) }) + + t.Run("spec with cloudnative enabled, csi driver and node image pull enabled and image not set", func(t *testing.T) { + assertDenied(t, []string{errorImagePullRequiresCodeModulesImage}, &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Annotations: map[string]string{ + dynakube.AnnotationFeatureNodeImagePull: "true", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{}, + }, + }, + }, + }) + }) + + t.Run("spec with appmon enabled, csi driver and node image pull enabled and image not set", func(t *testing.T) { + assertDenied(t, []string{errorImagePullRequiresCodeModulesImage}, &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: testName, + Namespace: testNamespace, + Annotations: map[string]string{ + dynakube.AnnotationFeatureNodeImagePull: "true", + }, + }, + Spec: dynakube.DynaKubeSpec{ + APIURL: testApiUrl, + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{ + AppInjectionSpec: oneagent.AppInjectionSpec{}, + }, + }, + }, + }) + }) } func createDynakube(oaEnvVar ...string) *dynakube.DynaKube { From 8ef6a93db103eb53d2a28675895937129159de38 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 23:02:58 +0000 Subject: [PATCH 343/426] chore(deps): update actions/download-artifact action to v4.2.1 (main) (#4627) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/upload-image/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/upload-image/action.yaml b/.github/actions/upload-image/action.yaml index a2b8490d4f..fe75fc2283 100644 --- a/.github/actions/upload-image/action.yaml +++ b/.github/actions/upload-image/action.yaml @@ -29,7 +29,7 @@ runs: using: "composite" steps: - name: Download artifact - uses: actions/download-artifact@b14cf4c92620c250e1c074ab0a5800e37df86765 # v4.2.0 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: name: operator-${{ inputs.platform }} path: /tmp From 4f3e48d968046c5dee9ccec220c5c98a2f87cfc9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Mar 2025 02:30:28 +0000 Subject: [PATCH 344/426] chore(deps): update actions/upload-artifact action to v4.6.2 (main) (#4628) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 2 +- .github/actions/preflight/action.yaml | 2 +- .github/workflows/openssf-scorecards.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index e7d973c2ea..7e3c22dd37 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -49,7 +49,7 @@ runs: labels: ${{ inputs.labels }} outputs: type=docker,dest=/tmp/operator-${{ inputs.platform }}.tar - name: Upload artifact - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: operator-${{ inputs.platform }} path: /tmp/operator-${{ inputs.platform }}.tar diff --git a/.github/actions/preflight/action.yaml b/.github/actions/preflight/action.yaml index 6fa5fc039e..c243dc44ce 100644 --- a/.github/actions/preflight/action.yaml +++ b/.github/actions/preflight/action.yaml @@ -34,7 +34,7 @@ runs: run: | hack/build/ci/preflight.sh "${{ env.PREFLIGHT_VERSION }}" "${{ env.IMAGE_URI}}" "${{ inputs.report-name }}" - name: Upload report - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: preflight-report path: ${{ inputs.report-name }} diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 08b40d4146..fc51bce893 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -48,7 +48,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: SARIF file path: results.sarif From c950ef3892983adcae3886d99a06635733844d1a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Mar 2025 06:08:29 +0000 Subject: [PATCH 345/426] fix(deps): update module github.com/docker/cli to v28.0.2+incompatible (main) (#4629) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3f8d6d8140..e1378553b3 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.4 require ( github.com/Dynatrace/dynatrace-bootstrapper v1.0.1 github.com/container-storage-interface/spec v1.11.0 - github.com/docker/cli v28.0.1+incompatible + github.com/docker/cli v28.0.2+incompatible github.com/evanphx/json-patch v5.9.11+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.3 diff --git a/go.sum b/go.sum index b8b610d06e..87a21bbf0a 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl3hgCPOKzs= -github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v28.0.2+incompatible h1:cRPZ77FK3/IXTAIQQj1vmhlxiLS5m+MIUDwS6f57lrE= +github.com/docker/cli v28.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= From 5bfbbf7f685faf8d34ca55221204a67a02ca65f9 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:35:02 +0100 Subject: [PATCH 346/426] Make Job installer work on OCP (#4631) --- .../chart/default/templates/Common/csi/role-csi.yaml | 6 ++++++ .../chart/default/tests/Common/csi/role-csi_test.yaml | 8 +++++++- pkg/controllers/csi/provisioner/controller.go | 2 ++ pkg/injection/codemodule/installer/job/bootstrapper.go | 10 ++++++++-- .../codemodule/installer/job/bootstrapper_test.go | 3 +++ pkg/util/kubeobjects/job/builder.go | 7 +++++++ 6 files changed, 33 insertions(+), 3 deletions(-) diff --git a/config/helm/chart/default/templates/Common/csi/role-csi.yaml b/config/helm/chart/default/templates/Common/csi/role-csi.yaml index c933e13804..f7d9055868 100644 --- a/config/helm/chart/default/templates/Common/csi/role-csi.yaml +++ b/config/helm/chart/default/templates/Common/csi/role-csi.yaml @@ -37,6 +37,12 @@ rules: - get - list - watch + - apiGroups: + - dynatrace.com + resources: + - dynakubes/finalizers + verbs: + - update - apiGroups: - batch resources: diff --git a/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml b/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml index fc521097fc..b42a1c664d 100644 --- a/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml @@ -53,7 +53,13 @@ tests: - list - watch - apiGroups: - - "batch" + - dynatrace.com + resources: + - dynakubes/finalizers + verbs: + - update + - apiGroups: + - batch resources: - jobs verbs: diff --git a/pkg/controllers/csi/provisioner/controller.go b/pkg/controllers/csi/provisioner/controller.go index d7f42765c5..29784ba311 100644 --- a/pkg/controllers/csi/provisioner/controller.go +++ b/pkg/controllers/csi/provisioner/controller.go @@ -33,6 +33,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/url" "github.com/pkg/errors" "github.com/spf13/afero" + batchv1 "k8s.io/api/batch/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/mount-utils" ctrl "sigs.k8s.io/controller-runtime" @@ -86,6 +87,7 @@ func NewOneAgentProvisioner(mgr manager.Manager, opts dtcsi.CSIOptions) *OneAgen func (provisioner *OneAgentProvisioner) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&dynakube.DynaKube{}). + Owns(&batchv1.Job{}). Named("provisioner-controller"). Complete(provisioner) } diff --git a/pkg/injection/codemodule/installer/job/bootstrapper.go b/pkg/injection/codemodule/installer/job/bootstrapper.go index 678697c4ea..07d308d708 100644 --- a/pkg/injection/codemodule/installer/job/bootstrapper.go +++ b/pkg/injection/codemodule/installer/job/bootstrapper.go @@ -17,6 +17,8 @@ const ( volumeName = "dynatrace-codemodules" codeModuleSource = "/opt/dynatrace/oneagent" + provisionerServiceAccount = "dynatrace-oneagent-csi-driver" // TODO: Get it from env + activeDeadlineSeconds int64 = 600 // 10 min, after which the Job will be put into a Failed state ttlSecondsAfterFinished int32 = 10 // 10 sec after the Job is put into a Succeeded or Failed state the Job and related Pods will be terminated ) @@ -48,8 +50,11 @@ func (inst *Installer) buildJob(name, targetDir string) (*batchv1.Job, error) { }, }, SecurityContext: &corev1.SecurityContext{ // TODO: Use the SecurityContext from the `provisioner` container - RunAsUser: ptr.To(int64(0)), - ReadOnlyRootFilesystem: ptr.To(true), + RunAsUser: ptr.To(int64(0)), + RunAsNonRoot: ptr.To(false), + Privileged: ptr.To(true), + AllowPrivilegeEscalation: ptr.To(true), + ReadOnlyRootFilesystem: ptr.To(true), SELinuxOptions: &corev1.SELinuxOptions{ Level: "s0", }, @@ -85,6 +90,7 @@ func (inst *Installer) buildJob(name, targetDir string) (*batchv1.Job, error) { jobutil.SetAutomountServiceAccountToken(false), jobutil.SetActiveDeadlineSeconds(activeDeadlineSeconds), jobutil.SetTTLSecondsAfterFinished(ttlSecondsAfterFinished), + jobutil.SetServiceAccount(provisionerServiceAccount), ) } diff --git a/pkg/injection/codemodule/installer/job/bootstrapper_test.go b/pkg/injection/codemodule/installer/job/bootstrapper_test.go index 98d002084a..4dbece7bd0 100644 --- a/pkg/injection/codemodule/installer/job/bootstrapper_test.go +++ b/pkg/injection/codemodule/installer/job/bootstrapper_test.go @@ -113,6 +113,9 @@ func TestBuildJob(t *testing.T) { require.NotNil(t, job.Spec.Template.Spec.Volumes[0].HostPath) assert.Equal(t, dataDir, job.Spec.Template.Spec.Volumes[0].HostPath.Path) + require.Equal(t, provisionerServiceAccount, job.Spec.Template.Spec.ServiceAccountName) + require.Equal(t, provisionerServiceAccount, job.Spec.Template.Spec.DeprecatedServiceAccount) + require.Len(t, job.Spec.Template.Spec.ImagePullSecrets, len(pullSecrets)) for i, ps := range pullSecrets { diff --git a/pkg/util/kubeobjects/job/builder.go b/pkg/util/kubeobjects/job/builder.go index ba6e73f541..f69602f309 100644 --- a/pkg/util/kubeobjects/job/builder.go +++ b/pkg/util/kubeobjects/job/builder.go @@ -78,6 +78,13 @@ func SetPodAnnotations(annotations map[string]string) builder.Option[*batchv1.Jo } } +func SetServiceAccount(serviceAccountName string) builder.Option[*batchv1.Job] { + return func(s *batchv1.Job) { + s.Spec.Template.Spec.ServiceAccountName = serviceAccountName + s.Spec.Template.Spec.DeprecatedServiceAccount = serviceAccountName + } +} + func SetTTLSecondsAfterFinished(ttl int32) builder.Option[*batchv1.Job] { return func(s *batchv1.Job) { s.Spec.TTLSecondsAfterFinished = ptr.To(ttl) From cda66470279910aa6e4b2a0c73301164f69e85f9 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 20 Mar 2025 15:09:11 +0100 Subject: [PATCH 347/426] Add watch permission for provisioner (#4634) --- config/helm/chart/default/templates/Common/csi/role-csi.yaml | 1 + config/helm/chart/default/tests/Common/csi/role-csi_test.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/config/helm/chart/default/templates/Common/csi/role-csi.yaml b/config/helm/chart/default/templates/Common/csi/role-csi.yaml index f7d9055868..1d6227f0c2 100644 --- a/config/helm/chart/default/templates/Common/csi/role-csi.yaml +++ b/config/helm/chart/default/templates/Common/csi/role-csi.yaml @@ -52,6 +52,7 @@ rules: - list - create - delete + - watch - apiGroups: - "" resources: diff --git a/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml b/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml index b42a1c664d..55f67bd121 100644 --- a/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml +++ b/config/helm/chart/default/tests/Common/csi/role-csi_test.yaml @@ -67,6 +67,7 @@ tests: - list - create - delete + - watch - apiGroups: - "" resources: From 7ed30d99bd43f2858caefad6012da77c0e0c09ec Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 21 Mar 2025 11:31:24 +0100 Subject: [PATCH 348/426] Make standalone logmon privileged with FF (#4633) (#4636) --- .../dynakube/logmonitoring/daemonset/container.go | 5 +++++ .../logmonitoring/daemonset/container_test.go | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go index d4f7d37d29..5e881de3dd 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/container.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/container.go @@ -79,5 +79,10 @@ func getBaseSecurityContext(dk dynakube.DynaKube) corev1.SecurityContext { securityContext.SeccompProfile = &corev1.SeccompProfile{LocalhostProfile: &seccomp} } + if dk.OneAgent().IsPrivilegedNeeded() { + securityContext.Privileged = ptr.To(true) + securityContext.AllowPrivilegeEscalation = ptr.To(true) + } + return securityContext } diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go index 71860734a4..e4ed2f6f96 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/container_test.go @@ -135,4 +135,18 @@ func TestSecurityContext(t *testing.T) { mainContainer.SecurityContext.Capabilities = nil assert.Equal(t, *initContainer.SecurityContext, *mainContainer.SecurityContext) }) + + t.Run("ocp scenario, OA needs to be privileged", func(t *testing.T) { + dk := dynakube.DynaKube{} + dk.Annotations = map[string]string{ + dynakube.AnnotationFeatureRunOneAgentContainerPrivileged: "true", + } + + sc := getBaseSecurityContext(dk) + + require.NotNil(t, sc) + require.NotEmpty(t, sc) + assert.True(t, *sc.Privileged) + assert.True(t, *sc.AllowPrivilegeEscalation) + }) } From 43ab7bf0a809fdb6c990714770738087f21d0201 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Fri, 21 Mar 2025 14:42:39 +0100 Subject: [PATCH 349/426] Automatically activates ActiveGate capabilities for telemetry ingest (#4624) --- pkg/api/v1beta4/dynakube/otelc_props.go | 12 +++--------- .../dynakube/activegate/capability/capability.go | 6 +++--- .../activegate/capability/capability_test.go | 8 ++++---- pkg/controllers/dynakube/otelc/secret/reconciler.go | 2 +- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/pkg/api/v1beta4/dynakube/otelc_props.go b/pkg/api/v1beta4/dynakube/otelc_props.go index 2c7ba5787a..d237e883fb 100644 --- a/pkg/api/v1beta4/dynakube/otelc_props.go +++ b/pkg/api/v1beta4/dynakube/otelc_props.go @@ -5,21 +5,15 @@ func (dk *DynaKube) OtelCollectorStatefulsetName() string { } func (dk *DynaKube) IsAGCertificateNeeded() bool { - if dk.isInClusterActiveGate() && dk.ActiveGate().HasCaCert() { + if dk.ActiveGate().IsEnabled() && dk.ActiveGate().HasCaCert() { return true } return false } -func (dk *DynaKube) IsCACertificateNeeded() bool { - if !dk.isInClusterActiveGate() && dk.Spec.TrustedCAs != "" { - return true - } - return false -} -func (dk *DynaKube) isInClusterActiveGate() bool { - if dk.ActiveGate().IsEnabled() && dk.ActiveGate().IsApiEnabled() { +func (dk *DynaKube) IsCACertificateNeeded() bool { + if !dk.ActiveGate().IsEnabled() && dk.Spec.TrustedCAs != "" { return true } diff --git a/pkg/controllers/dynakube/activegate/capability/capability.go b/pkg/controllers/dynakube/activegate/capability/capability.go index 540018d5f4..924063a02f 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability.go +++ b/pkg/controllers/dynakube/activegate/capability/capability.go @@ -100,12 +100,12 @@ func NewMultiCapability(dk *dynakube.DynaKube) Capability { if dk.IsExtensionsEnabled() { capabilityNames = append(capabilityNames, "extension_controller") - capabilityDisplayNames = append(capabilityDisplayNames, "extension_controller") + capabilityDisplayNames = append(capabilityDisplayNames, "extension-controller") } if dk.IsOTLPingestEnabled() || dk.TelemetryIngest().IsEnabled() { - capabilityNames = append(capabilityNames, "log_analytics_collector_enabled", "generic_ingest_enabled", "otlp_ingest") - capabilityDisplayNames = append(capabilityDisplayNames, "log_analytics_collector_enabled", "generic_ingest_enabled", "otlp_ingest") + capabilityNames = append(capabilityNames, "log_analytics_collector", "generic_ingest", "otlp_ingest") + capabilityDisplayNames = append(capabilityDisplayNames, "log_analytics-collector", "generic-ingest", "otlp-ingest") } mc.argName = strings.Join(capabilityNames, ",") diff --git a/pkg/controllers/dynakube/activegate/capability/capability_test.go b/pkg/controllers/dynakube/activegate/capability/capability_test.go index 327cbf2b3b..bbfa135af8 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability_test.go +++ b/pkg/controllers/dynakube/activegate/capability/capability_test.go @@ -21,10 +21,10 @@ const ( expectedArgNameWithDebugging = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,debugging" expectedArgNameWithExtensions = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller" expectedArgNameWithExtensionsOnly = "extension_controller" - expectedArgNameWithOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector_enabled,generic_ingest_enabled,otlp_ingest" - expectedArgNameWithOTLPingestOnly = "log_analytics_collector_enabled,generic_ingest_enabled,otlp_ingest" - expectedArgNameWithExtensionsAndOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller,log_analytics_collector_enabled,generic_ingest_enabled,otlp_ingest" - expectedArgNameWithTelemetryIngest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector_enabled,generic_ingest_enabled,otlp_ingest" + expectedArgNameWithOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest,otlp_ingest" + expectedArgNameWithOTLPingestOnly = "log_analytics_collector,generic_ingest,otlp_ingest" + expectedArgNameWithExtensionsAndOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller,log_analytics_collector,generic_ingest,otlp_ingest" + expectedArgNameWithTelemetryIngest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest,otlp_ingest" ) var capabilities = []activegate.CapabilityDisplayName{ diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler.go b/pkg/controllers/dynakube/otelc/secret/reconciler.go index 044a24eb9a..465c514ba2 100644 --- a/pkg/controllers/dynakube/otelc/secret/reconciler.go +++ b/pkg/controllers/dynakube/otelc/secret/reconciler.go @@ -83,7 +83,7 @@ func (r *Reconciler) ensureTelemetryIngestApiCredentialsSecret(ctx context.Conte } func (r *Reconciler) getDtEndpoint() ([]byte, error) { - if r.dk.ActiveGate().IsApiEnabled() { + if r.dk.ActiveGate().IsEnabled() { tenantUUID, err := r.dk.TenantUUID() if err != nil { return nil, err From 8b91951f362a048d2fa924277eeeb6d35f2e48f3 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:00:04 +0100 Subject: [PATCH 350/426] Sets proxy env variables for otel collector (#4630) --- .../otelc/configuration/reconciler.go | 1 + .../dynakube/otelc/statefulset/env.go | 43 +++ .../dynakube/otelc/statefulset/env_test.go | 244 +++++++++++++++++- pkg/otelcgen/exporters.go | 4 +- pkg/otelcgen/otelcgen.go | 35 ++- pkg/otelcgen/otelcgen_test.go | 1 + pkg/otelcgen/services.go | 3 +- pkg/otelcgen/testdata/exporters_only.yaml | 2 +- pkg/otelcgen/testdata/full_config.yaml | 5 +- pkg/otelcgen/testdata/services_only.yaml | 3 - .../testdata/services_statsd_only.yaml | 1 - .../testdata/services_zipkin_only.yaml | 1 - 12 files changed, 316 insertions(+), 27 deletions(-) diff --git a/pkg/controllers/dynakube/otelc/configuration/reconciler.go b/pkg/controllers/dynakube/otelc/configuration/reconciler.go index 6ff6404eb5..9e56452a29 100644 --- a/pkg/controllers/dynakube/otelc/configuration/reconciler.go +++ b/pkg/controllers/dynakube/otelc/configuration/reconciler.go @@ -110,6 +110,7 @@ func (r *Reconciler) getData() (map[string]string, error) { options = append(options, otelcgen.WithCA(otelcconsts.ActiveGateTLSCertVolumePath)) } else if r.dk.IsCACertificateNeeded() { options = append(options, otelcgen.WithCA(otelcconsts.TrustedCAVolumePath)) + options = append(options, otelcgen.WithSystemCAs(true)) } if r.dk.TelemetryIngest().IsEnabled() && r.dk.TelemetryIngest().Spec.TlsRefName != "" { diff --git a/pkg/controllers/dynakube/otelc/statefulset/env.go b/pkg/controllers/dynakube/otelc/statefulset/env.go index 9ab5ba611d..727c2a225e 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env.go @@ -2,10 +2,14 @@ package statefulset import ( "strconv" + "strings" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" + agconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/consts" otelcConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" corev1 "k8s.io/api/core/v1" ) @@ -36,6 +40,9 @@ const ( // See https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html. envCertDir = "SSL_CERT_DIR" envEECcontrollerTLS = "EXTENSIONS_CONTROLLER_TLS" + envHttpProxy = "HTTP_PROXY" + envHttpsProxy = "HTTPS_PROXY" + envNoProxy = "NO_PROXY" // Volume names and paths customEecTLSCertificatePath = "/tls/custom/eec" @@ -65,6 +72,12 @@ func getEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { {Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, } + if dk.HasProxy() { + envs = append(envs, getDynakubeProxyEnvValue(envHttpsProxy, dk.Spec.Proxy)) + envs = append(envs, getDynakubeProxyEnvValue(envHttpProxy, dk.Spec.Proxy)) + envs = append(envs, corev1.EnvVar{Name: envNoProxy, Value: getDynakubeNoProxyEnvValue(dk)}) + } + if dk.IsExtensionsEnabled() { envs = append( envs, @@ -107,3 +120,33 @@ func getEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { return envs } + +func getDynakubeProxyEnvValue(envVar string, src *value.Source) corev1.EnvVar { + if src.ValueFrom != "" { + return corev1.EnvVar{ + Name: envVar, + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: src.ValueFrom}, + Key: dynakube.ProxyKey, + }, + }, + } + } + + return corev1.EnvVar{Name: envVar, Value: src.Value} +} + +func getDynakubeNoProxyEnvValue(dk *dynakube.DynaKube) string { + noProxyValues := []string{} + + if dk.IsExtensionsEnabled() { + noProxyValues = append(noProxyValues, dk.ExtensionsServiceNameFQDN()) + } + + if dk.ActiveGate().IsEnabled() { + noProxyValues = append(noProxyValues, capability.BuildServiceName(dk.Name, agconsts.MultiActiveGateName)+"."+dk.Namespace) + } + + return strings.Join(noProxyValues, ",") +} diff --git a/pkg/controllers/dynakube/otelc/statefulset/env_test.go b/pkg/controllers/dynakube/otelc/statefulset/env_test.go index bcb14b332a..b796b567b3 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env_test.go @@ -4,11 +4,15 @@ import ( "fmt" "testing" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" otelcConsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" "github.com/stretchr/testify/assert" + "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" ) @@ -63,9 +67,8 @@ func TestEnvironmentVariables(t *testing.T) { dk := getTestDynakube() dk.Spec.TelemetryIngest = &telemetryingest.Spec{} - dataIngestToken := getTokens(dk.Name, dk.Namespace) - configMap := getConfigConfigMap(dk.Name, dk.Namespace) - statefulSet := getStatefulset(t, dk, &dataIngestToken, &configMap) + statefulSet := getWorkload(t, dk) + assert.Len(t, statefulSet.Spec.Template.Spec.Containers[0].Env, 12) assert.Equal(t, corev1.EnvVar{Name: envShards, Value: fmt.Sprintf("%d", getReplicas(dk))}, statefulSet.Spec.Template.Spec.Containers[0].Env[0]) @@ -106,3 +109,238 @@ func TestEnvironmentVariables(t *testing.T) { }}, statefulSet.Spec.Template.Spec.Containers[0].Env[11]) }) } + +func TestProxyEnvsNoProxy(t *testing.T) { + tests := []struct { + name string + extensions *dynakube.ExtensionsSpec + telemetryIngest *telemetryingest.Spec + activeGate *activegate.Spec + }{ + { + name: "extensions without proxy", + extensions: &dynakube.ExtensionsSpec{}, + telemetryIngest: nil, + }, + { + name: "telemetryIngest, public AG, without proxy", + extensions: nil, + telemetryIngest: &telemetryingest.Spec{}, + activeGate: nil, + }, + { + name: "telemetryIngest, local AG, without proxy", + extensions: nil, + telemetryIngest: &telemetryingest.Spec{}, + activeGate: getProxyTestActiveGate(), + }, + { + name: "telemetryIngest, extensions, local AG, without proxy", + extensions: &dynakube.ExtensionsSpec{}, + telemetryIngest: &telemetryingest.Spec{}, + activeGate: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.Extensions = tt.extensions + dk.Spec.TelemetryIngest = tt.telemetryIngest + dk.Spec.Proxy = nil + + if tt.activeGate != nil { + dk.Spec.ActiveGate = *tt.activeGate + } + + statefulSet := getWorkload(t, dk) + + assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envHttpsProxy}) + assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envHttpProxy}) + assert.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envNoProxy}) + }) + } +} + +func TestProxyEnvsProxySecret(t *testing.T) { + const testProxySecretName = "test-proxy-secret" + + tests := []struct { + name string + extensions *dynakube.ExtensionsSpec + telemetryIngest *telemetryingest.Spec + activeGate *activegate.Spec + proxy *value.Source + + expectedNoProxy string + }{ + { + name: "extensions with proxy secret", + extensions: &dynakube.ExtensionsSpec{}, + telemetryIngest: nil, + proxy: &value.Source{ + ValueFrom: testProxySecretName, + }, + expectedNoProxy: "dynakube-extensions-controller.dynatrace,dynakube-activegate.dynatrace", + }, + { + name: "telemetryIngest, public AG, with proxy secret", + extensions: nil, + telemetryIngest: &telemetryingest.Spec{}, + activeGate: nil, + proxy: &value.Source{ + ValueFrom: testProxySecretName, + }, + expectedNoProxy: "", + }, + { + name: "telemetryIngest, local AG, with proxy secret", + extensions: nil, + telemetryIngest: &telemetryingest.Spec{}, + activeGate: getProxyTestActiveGate(), + proxy: &value.Source{ + ValueFrom: testProxySecretName, + }, + expectedNoProxy: "dynakube-activegate.dynatrace", + }, + { + name: "telemetryIngest, extensions, local AG, with proxy secret", + extensions: &dynakube.ExtensionsSpec{}, + telemetryIngest: &telemetryingest.Spec{}, + activeGate: nil, + proxy: &value.Source{ + ValueFrom: testProxySecretName, + }, + expectedNoProxy: "dynakube-extensions-controller.dynatrace,dynakube-activegate.dynatrace", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.Extensions = tt.extensions + dk.Spec.TelemetryIngest = tt.telemetryIngest + dk.Spec.Proxy = tt.proxy + + if tt.activeGate != nil { + dk.Spec.ActiveGate = *tt.activeGate + } + + statefulSet := getWorkload(t, dk) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{ + Name: envHttpsProxy, + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: tt.proxy.ValueFrom}, + Key: dynakube.ProxyKey, + }, + }, + }) + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{ + Name: envHttpProxy, + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: tt.proxy.ValueFrom}, + Key: dynakube.ProxyKey, + }, + }, + }) + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envNoProxy, Value: tt.expectedNoProxy}) + }) + } +} + +func TestProxyEnvsProxyValue(t *testing.T) { + const testProxyValue = "http://test.proxy.com:8888" + + tests := []struct { + name string + extensions *dynakube.ExtensionsSpec + telemetryIngest *telemetryingest.Spec + activeGate *activegate.Spec + proxy *value.Source + + expectedNoProxy string + }{ + { + name: "extensions with proxy value", + extensions: &dynakube.ExtensionsSpec{}, + telemetryIngest: nil, + proxy: &value.Source{ + Value: testProxyValue, + }, + expectedNoProxy: "dynakube-extensions-controller.dynatrace,dynakube-activegate.dynatrace", + }, + { + name: "telemetryIngest, public AG, with proxy value", + extensions: nil, + telemetryIngest: &telemetryingest.Spec{}, + activeGate: nil, + proxy: &value.Source{ + Value: testProxyValue, + }, + expectedNoProxy: "", + }, + { + name: "telemetryIngest, local AG, with proxy value", + extensions: nil, + telemetryIngest: &telemetryingest.Spec{}, + activeGate: getProxyTestActiveGate(), + proxy: &value.Source{ + Value: testProxyValue, + }, + expectedNoProxy: "dynakube-activegate.dynatrace", + }, + { + name: "telemetryIngest, extensions, local AG, with proxy value", + extensions: &dynakube.ExtensionsSpec{}, + telemetryIngest: &telemetryingest.Spec{}, + activeGate: nil, + proxy: &value.Source{ + Value: testProxyValue, + }, + expectedNoProxy: "dynakube-extensions-controller.dynatrace,dynakube-activegate.dynatrace", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.Extensions = tt.extensions + dk.Spec.TelemetryIngest = tt.telemetryIngest + dk.Spec.Proxy = tt.proxy + + if tt.activeGate != nil { + dk.Spec.ActiveGate = *tt.activeGate + } + + statefulSet := getWorkload(t, dk) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{ + Name: envHttpsProxy, + Value: tt.proxy.Value, + }) + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{ + Name: envHttpProxy, + Value: tt.proxy.Value, + }) + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envNoProxy, Value: tt.expectedNoProxy}) + }) + } +} + +func getWorkload(t *testing.T, dk *dynakube.DynaKube) *v1.StatefulSet { + dataIngestToken := getTokens(dk.Name, dk.Namespace) + configMap := getConfigConfigMap(dk.Name, dk.Namespace) + + return getStatefulset(t, dk, &dataIngestToken, &configMap) +} + +func getProxyTestActiveGate() *activegate.Spec { + return &activegate.Spec{ + CapabilityProperties: activegate.CapabilityProperties{}, + Capabilities: []activegate.CapabilityDisplayName{"otlp-ingest"}, + UseEphemeralVolume: false, + } +} diff --git a/pkg/otelcgen/exporters.go b/pkg/otelcgen/exporters.go index 13a189fec3..0cee344c00 100644 --- a/pkg/otelcgen/exporters.go +++ b/pkg/otelcgen/exporters.go @@ -17,6 +17,9 @@ func (c *Config) buildExporters() map[component.ID]component.Config { serverConfig.TLSSetting = &TLSSetting{ CAFile: c.caFile, } + if c.includeSystemCACertsPool { + serverConfig.TLSSetting.IncludeSystemCACertsPool = &c.includeSystemCACertsPool + } } if c.apiToken != "" { @@ -25,7 +28,6 @@ func (c *Config) buildExporters() map[component.ID]component.Config { } return map[component.ID]component.Config{ - debug: nil, otlphttp: serverConfig, } } diff --git a/pkg/otelcgen/otelcgen.go b/pkg/otelcgen/otelcgen.go index bc9f9bcb09..70905926c2 100644 --- a/pkg/otelcgen/otelcgen.go +++ b/pkg/otelcgen/otelcgen.go @@ -28,9 +28,10 @@ type TimerHistogramMapping struct { // "go.opentelemetry.io/collector/config/configtls.TLSSetting" // with reduced number of attributes to reduce the number of dependencies. type TLSSetting struct { - CAFile string `mapstructure:"ca_file,omitempty"` - KeyFile string `mapstructure:"key_file,omitempty"` - CertFile string `mapstructure:"cert_file,omitempty"` + IncludeSystemCACertsPool *bool `mapstructure:"include_system_ca_certs_pool,omitempty"` + CAFile string `mapstructure:"ca_file,omitempty"` + KeyFile string `mapstructure:"key_file,omitempty"` + CertFile string `mapstructure:"cert_file,omitempty"` } // ServerConfig is based on "go.opentelemetry.io/collector/config/confighttp.ServerConfig" and @@ -85,15 +86,17 @@ type Config struct { // Extensions is a map of ComponentID to extensions. Extensions map[component.ID]component.Config `mapstructure:"extensions"` - tlsKey string - tlsCert string - caFile string - podIP string - endpoint string - apiToken string + tlsKey string + tlsCert string + caFile string + podIP string + endpoint string + apiToken string + + Service ServiceConfig `mapstructure:"service"` protocols Protocols - Service ServiceConfig `mapstructure:"service"` + includeSystemCACertsPool bool } type Option func(c *Config) error @@ -120,7 +123,9 @@ func (c *Config) Marshal() ([]byte, error) { return nil, err } - return yaml.Marshal(conf.ToStringMap()) + sm := conf.ToStringMap() + + return yaml.Marshal(sm) } func (c *Config) buildTLSSetting() *TLSSetting { @@ -238,6 +243,14 @@ func WithCA(caFile string) Option { } } +func WithSystemCAs(useSystemCAs bool) Option { + return func(c *Config) error { + c.includeSystemCACertsPool = useSystemCAs + + return nil + } +} + func WithApiToken(apiToken string) Option { return func(c *Config) error { c.apiToken = apiToken diff --git a/pkg/otelcgen/otelcgen_test.go b/pkg/otelcgen/otelcgen_test.go index 1d9b2c4fb7..0f690a3206 100644 --- a/pkg/otelcgen/otelcgen_test.go +++ b/pkg/otelcgen/otelcgen_test.go @@ -14,6 +14,7 @@ func TestNewConfigFull(t *testing.T) { "test", Protocols{OtlpProtocol, JaegerProtocol, StatsdProtocol, ZipkinProtocol}, WithCA("/run/opensignals/cacerts/certs"), + WithSystemCAs(true), WithApiToken("test-token"), WithTLS("/run/opensignals/tls/tls.crt", "/run/opensignals/tls/tls.key"), WithReceivers(), diff --git a/pkg/otelcgen/services.go b/pkg/otelcgen/services.go index a84c979ee9..f30b9f2059 100644 --- a/pkg/otelcgen/services.go +++ b/pkg/otelcgen/services.go @@ -14,7 +14,6 @@ var ( traces = pipeline.MustNewID("traces") metrics = pipeline.MustNewID("metrics") logs = pipeline.MustNewID("logs") - debug = component.MustNewID("debug") allowedPipelinesLogsReceiversIDs = []component.ID{OtlpID} @@ -88,7 +87,7 @@ func (c *Config) buildPipelinesReceivers(allowed []component.ID) []component.ID func buildExporters() []component.ID { return []component.ID{ - otlphttp, debug, + otlphttp, } } diff --git a/pkg/otelcgen/testdata/exporters_only.yaml b/pkg/otelcgen/testdata/exporters_only.yaml index 7a55098a1f..0fd8925728 100644 --- a/pkg/otelcgen/testdata/exporters_only.yaml +++ b/pkg/otelcgen/testdata/exporters_only.yaml @@ -1,10 +1,10 @@ connectors: {} exporters: - debug: otlphttp: endpoint: "test" tls: ca_file: "/run/opensignals/cacerts/certs" + headers: Authorization: "Api-Token test-token" extensions: {} diff --git a/pkg/otelcgen/testdata/full_config.yaml b/pkg/otelcgen/testdata/full_config.yaml index 7a041adf3c..c25af689b8 100644 --- a/pkg/otelcgen/testdata/full_config.yaml +++ b/pkg/otelcgen/testdata/full_config.yaml @@ -1,10 +1,10 @@ connectors: {} exporters: - debug: otlphttp: endpoint: "exporters-test-endpoint" tls: ca_file: "/run/opensignals/cacerts/certs" + include_system_ca_certs_pool: true headers: Authorization: "Api-Token test-token" extensions: @@ -197,7 +197,6 @@ service: logs: exporters: - otlphttp - - debug receivers: - otlp processors: @@ -208,7 +207,6 @@ service: metrics: exporters: - otlphttp - - debug receivers: - otlp - statsd @@ -221,7 +219,6 @@ service: traces: exporters: - otlphttp - - debug receivers: - otlp - jaeger diff --git a/pkg/otelcgen/testdata/services_only.yaml b/pkg/otelcgen/testdata/services_only.yaml index e45b6a4c61..e6681c54a2 100644 --- a/pkg/otelcgen/testdata/services_only.yaml +++ b/pkg/otelcgen/testdata/services_only.yaml @@ -10,7 +10,6 @@ service: logs: exporters: - otlphttp - - debug receivers: - otlp processors: @@ -21,7 +20,6 @@ service: metrics: exporters: - otlphttp - - debug receivers: - otlp - statsd @@ -34,7 +32,6 @@ service: traces: exporters: - otlphttp - - debug receivers: - otlp - jaeger diff --git a/pkg/otelcgen/testdata/services_statsd_only.yaml b/pkg/otelcgen/testdata/services_statsd_only.yaml index 6ac5c6ac89..f1f8265ef4 100644 --- a/pkg/otelcgen/testdata/services_statsd_only.yaml +++ b/pkg/otelcgen/testdata/services_statsd_only.yaml @@ -10,7 +10,6 @@ service: metrics: exporters: - otlphttp - - debug receivers: - statsd processors: diff --git a/pkg/otelcgen/testdata/services_zipkin_only.yaml b/pkg/otelcgen/testdata/services_zipkin_only.yaml index b737bc766f..3984c6e43a 100644 --- a/pkg/otelcgen/testdata/services_zipkin_only.yaml +++ b/pkg/otelcgen/testdata/services_zipkin_only.yaml @@ -10,7 +10,6 @@ service: traces: exporters: - otlphttp - - debug receivers: - zipkin processors: From 611058efac6752764d1ef6d9c9e689f9fac089d7 Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Fri, 21 Mar 2025 18:22:35 +0100 Subject: [PATCH 351/426] Add LogMonitoring e2e test (#4594) --- doc/e2e/features.md | 20 +++ hack/make/tests/e2e.mk | 4 + .../logmonitoring/configsecret/conditions.go | 2 +- .../logmonitoring/configsecret/reconciler.go | 16 +-- .../configsecret/reconciler_test.go | 10 +- .../logmonitoring/daemonset/conditions.go | 2 +- .../logmonitoring/daemonset/reconciler.go | 10 +- .../daemonset/reconciler_test.go | 10 +- .../logmonsettings/conditions.go | 2 +- .../logmonsettings/reconciler.go | 10 +- test/features/consts/consts.go | 2 + test/features/logmonitoring/logmonitoring.go | 125 ++++++++++++++++++ test/helpers/components/dynakube/options.go | 18 +++ test/helpers/kubeobjects/daemonset/wait.go | 6 + test/scenarios/no_csi/no_csi_test.go | 2 + 15 files changed, 208 insertions(+), 31 deletions(-) create mode 100644 test/features/logmonitoring/logmonitoring.go diff --git a/doc/e2e/features.md b/doc/e2e/features.md index ffc5b9358f..1ea5092c4b 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -427,6 +427,8 @@ const ( DevRegistryPullSecretName = "devregistry" EecImageRepo = "478983378254.dkr.ecr.us-east-1.amazonaws.com/dynatrace/dynatrace-eec" EecImageTag = "1.303.0.20240930-183404" + LogMonitoringImageRepo = "public.ecr.aws/dynatrace/dynatrace-logmodule" + LogMonitoringImageTag = "1.309.59.20250319-140247" ) ``` @@ -484,6 +486,24 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/extensions" func Feature(t *testing.T) features.Feature ``` +# logmonitoring + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/logmonitoring" +``` + +## Index + +- [func Feature(t *testing.T) features.Feature](<#Feature>) + + + +## func [Feature]() + +```go +func Feature(t *testing.T) features.Feature +``` + # publicregistry ```go diff --git a/hack/make/tests/e2e.mk b/hack/make/tests/e2e.mk index c698479b74..3e821cc203 100644 --- a/hack/make/tests/e2e.mk +++ b/hack/make/tests/e2e.mk @@ -145,3 +145,7 @@ test/e2e/gke-autopilot: manifests/crd/helm ## Runs extensions related e2e tests test/e2e/extensions: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "extensions-components-rollout" $(SKIPCLEANUP) + +## Runs LogMonitoring related e2e tests +test/e2e/logmonitoring: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "logmonitoring-components-rollout" $(SKIPCLEANUP) diff --git a/pkg/controllers/dynakube/logmonitoring/configsecret/conditions.go b/pkg/controllers/dynakube/logmonitoring/configsecret/conditions.go index 0ded47ba63..2b0f8d9b89 100644 --- a/pkg/controllers/dynakube/logmonitoring/configsecret/conditions.go +++ b/pkg/controllers/dynakube/logmonitoring/configsecret/conditions.go @@ -1,5 +1,5 @@ package configsecret const ( - lmcConditionType = "LogMonitoringConfig" + LmcConditionType = "LogMonitoringConfig" ) diff --git a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go index 65a8ac79d9..b47d789317 100644 --- a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler.go @@ -44,7 +44,7 @@ func NewReconciler(clt client.Client, func (r *Reconciler) Reconcile(ctx context.Context) error { if !r.dk.LogMonitoring().IsStandalone() { - if meta.FindStatusCondition(*r.dk.Conditions(), lmcConditionType) == nil { + if meta.FindStatusCondition(*r.dk.Conditions(), LmcConditionType) == nil { return nil // no condition == nothing is there to clean up } @@ -55,7 +55,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { log.Error(err, "failed to clean-up LogMonitoring config-secret") } - meta.RemoveStatusCondition(r.dk.Conditions(), lmcConditionType) + meta.RemoveStatusCondition(r.dk.Conditions(), LmcConditionType) return nil // clean-up shouldn't cause a failure } @@ -73,14 +73,14 @@ func (r *Reconciler) reconcileSecret(ctx context.Context) error { changed, err := query.CreateOrUpdate(ctx, newSecret) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), lmcConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), LmcConditionType, err) return err } else if changed { - conditions.SetSecretOutdated(r.dk.Conditions(), lmcConditionType, newSecret.Name) // needed so the timestamp updates, will never actually show up in the status + conditions.SetSecretOutdated(r.dk.Conditions(), LmcConditionType, newSecret.Name) // needed so the timestamp updates, will never actually show up in the status } - conditions.SetSecretCreated(r.dk.Conditions(), lmcConditionType, newSecret.Name) + conditions.SetSecretCreated(r.dk.Conditions(), LmcConditionType, newSecret.Name) return nil } @@ -99,7 +99,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) k8ssecret.SetLabels(coreLabels), ) if err != nil { - conditions.SetSecretGenFailed(r.dk.Conditions(), lmcConditionType, err) + conditions.SetSecretGenFailed(r.dk.Conditions(), LmcConditionType, err) return nil, err } @@ -113,14 +113,14 @@ func (r *Reconciler) getSecretData(ctx context.Context) (map[string][]byte, erro Namespace: r.dk.Namespace, }, connectioninfo.TenantTokenKey, log) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), lmcConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), LmcConditionType, err) return nil, err } tenantUUID, err := r.dk.TenantUUID() if err != nil { - conditions.SetSecretGenFailed(r.dk.Conditions(), lmcConditionType, err) + conditions.SetSecretGenFailed(r.dk.Conditions(), LmcConditionType, err) return nil, err } diff --git a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go index de57f24816..888586c5e4 100644 --- a/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/configsecret/reconciler_test.go @@ -37,7 +37,7 @@ func TestReconcile(t *testing.T) { t.Run("Only clean up if not standalone", func(t *testing.T) { dk := createDynakube(true) dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} - conditions.SetSecretCreated(dk.Conditions(), lmcConditionType, "testing") + conditions.SetSecretCreated(dk.Conditions(), LmcConditionType, "testing") mockK8sClient := createK8sClientWithConfigSecret() @@ -50,7 +50,7 @@ func TestReconcile(t *testing.T) { err = mockK8sClient.Get(context.Background(), client.ObjectKey{Name: GetSecretName((dk.Name)), Namespace: dk.Namespace}, &secret) require.True(t, k8serrors.IsNotFound(err)) - condition := meta.FindStatusCondition(*dk.Conditions(), lmcConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), LmcConditionType) require.Nil(t, condition) }) @@ -66,7 +66,7 @@ func TestReconcile(t *testing.T) { checkSecretForValue(t, mockK8sClient, dk) - condition := meta.FindStatusCondition(*dk.Conditions(), lmcConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), LmcConditionType) require.NotNil(t, condition) oldTransitionTime := condition.LastTransitionTime require.NotEmpty(t, oldTransitionTime) @@ -82,7 +82,7 @@ func TestReconcile(t *testing.T) { dk := createDynakube(false) mockK8sClient := createK8sClientWithOneAgentTenantSecret(dk, tokenValue) - conditions.SetSecretCreated(dk.Conditions(), lmcConditionType, "this is a test") + conditions.SetSecretCreated(dk.Conditions(), LmcConditionType, "this is a test") reconciler := NewReconciler(mockK8sClient, mockK8sClient, dk) err := reconciler.Reconcile(ctx) @@ -110,7 +110,7 @@ func TestReconcile(t *testing.T) { require.Error(t, err) require.Len(t, *dk.Conditions(), 1) - condition := meta.FindStatusCondition(*dk.Conditions(), lmcConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), LmcConditionType) assert.Equal(t, conditions.KubeApiErrorReason, condition.Reason) assert.Equal(t, metav1.ConditionFalse, condition.Status) }) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/conditions.go b/pkg/controllers/dynakube/logmonitoring/daemonset/conditions.go index 5183d59171..18d466cb85 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/conditions.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/conditions.go @@ -1,5 +1,5 @@ package daemonset const ( - conditionType = "LogMonitoringDaemonSet" + ConditionType = "LogMonitoringDaemonSet" ) diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go index 63ecdc1934..34d626bcc4 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler.go @@ -41,7 +41,7 @@ var KubernetesSettingsNotAvailableError = errors.New("the status of the DynaKube func (r *Reconciler) Reconcile(ctx context.Context) error { if !r.dk.LogMonitoring().IsStandalone() { - if meta.FindStatusCondition(*r.dk.Conditions(), conditionType) == nil { + if meta.FindStatusCondition(*r.dk.Conditions(), ConditionType) == nil { return nil // no condition == nothing is there to clean up } @@ -52,7 +52,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { log.Error(err, "failed to clean-up LogMonitoring config-secret") } - meta.RemoveStatusCondition(r.dk.Conditions(), conditionType) + meta.RemoveStatusCondition(r.dk.Conditions(), ConditionType) return nil // clean-up shouldn't cause a failure } @@ -70,14 +70,14 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { updated, err := daemonset.Query(r.client, r.apiReader, log).WithOwner(r.dk).CreateOrUpdate(ctx, ds) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), conditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), ConditionType, err) return err } if updated { - conditions.SetDaemonSetOutdated(r.dk.Conditions(), conditionType, r.dk.LogMonitoring().GetDaemonSetName()) // needed to reset the timestamp - conditions.SetDaemonSetCreated(r.dk.Conditions(), conditionType, r.dk.LogMonitoring().GetDaemonSetName()) + conditions.SetDaemonSetOutdated(r.dk.Conditions(), ConditionType, r.dk.LogMonitoring().GetDaemonSetName()) // needed to reset the timestamp + conditions.SetDaemonSetCreated(r.dk.Conditions(), ConditionType, r.dk.LogMonitoring().GetDaemonSetName()) } return nil diff --git a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go index 881ab6ac9a..4be62af0ca 100644 --- a/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go +++ b/pkg/controllers/dynakube/logmonitoring/daemonset/reconciler_test.go @@ -36,7 +36,7 @@ func TestReconcile(t *testing.T) { t.Run("Only clean up if not standalone", func(t *testing.T) { dk := createDynakube(true) dk.Spec.OneAgent.CloudNativeFullStack = &oneagent.CloudNativeFullStackSpec{} - conditions.SetDaemonSetCreated(dk.Conditions(), conditionType, "testing") + conditions.SetDaemonSetCreated(dk.Conditions(), ConditionType, "testing") previousDaemonSet := appsv1.DaemonSet{} previousDaemonSet.Name = dk.LogMonitoring().GetDaemonSetName() @@ -55,7 +55,7 @@ func TestReconcile(t *testing.T) { }, &daemonset) require.True(t, k8serrors.IsNotFound(err)) - condition := meta.FindStatusCondition(*dk.Conditions(), conditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), ConditionType) require.Nil(t, condition) }) @@ -69,7 +69,7 @@ func TestReconcile(t *testing.T) { err := reconciler.Reconcile(ctx) require.NoError(t, err) - condition := meta.FindStatusCondition(*dk.Conditions(), conditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), ConditionType) require.NotNil(t, condition) oldTransitionTime := condition.LastTransitionTime require.NotEmpty(t, oldTransitionTime) @@ -95,7 +95,7 @@ func TestReconcile(t *testing.T) { previousDaemonSet.Namespace = dk.Namespace mockK8sClient := fake.NewClient(&previousDaemonSet) - conditions.SetDaemonSetCreated(dk.Conditions(), conditionType, "this is a test") + conditions.SetDaemonSetCreated(dk.Conditions(), ConditionType, "this is a test") reconciler := NewReconciler(mockK8sClient, mockK8sClient, dk) err := reconciler.Reconcile(ctx) @@ -123,7 +123,7 @@ func TestReconcile(t *testing.T) { require.Error(t, err) require.Len(t, *dk.Conditions(), 1) - condition := meta.FindStatusCondition(*dk.Conditions(), conditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), ConditionType) assert.Equal(t, conditions.KubeApiErrorReason, condition.Reason) assert.Equal(t, metav1.ConditionFalse, condition.Status) }) diff --git a/pkg/controllers/dynakube/logmonitoring/logmonsettings/conditions.go b/pkg/controllers/dynakube/logmonitoring/logmonsettings/conditions.go index 6b4d889450..597e2da073 100644 --- a/pkg/controllers/dynakube/logmonitoring/logmonsettings/conditions.go +++ b/pkg/controllers/dynakube/logmonitoring/logmonsettings/conditions.go @@ -9,7 +9,7 @@ const ( settingsExistReason = "LogMonSettingsExist" settingsErrorReason = "LogMonSettingsError" - conditionType = "LogMonitoringSettings" + ConditionType = "LogMonitoringSettings" ) func setLogMonitoringSettingExists(conditions *[]metav1.Condition, conditionType string) { diff --git a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go index f1b10b86b5..a93a02789a 100644 --- a/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go +++ b/pkg/controllers/dynakube/logmonitoring/logmonsettings/reconciler.go @@ -34,12 +34,12 @@ func NewReconciler(dtc dtclient.Client, dk *dynakube.DynaKube) controllers.Recon } func (r *reconciler) Reconcile(ctx context.Context) error { - if !conditions.IsOutdated(r.timeProvider, r.dk, conditionType) { + if !conditions.IsOutdated(r.timeProvider, r.dk, ConditionType) { return nil } if !r.dk.LogMonitoring().IsEnabled() { - meta.RemoveStatusCondition(r.dk.Conditions(), conditionType) + meta.RemoveStatusCondition(r.dk.Conditions(), ConditionType) return nil } else if r.dk.Status.KubernetesClusterMEID == "" { @@ -61,7 +61,7 @@ func (r *reconciler) checkLogMonitoringSettings(ctx context.Context) error { logMonitoringSettings, err := r.dtc.GetSettingsForLogModule(ctx, r.dk.Status.KubernetesClusterMEID) if err != nil { - setLogMonitoringSettingError(r.dk.Conditions(), conditionType, err.Error()) + setLogMonitoringSettingError(r.dk.Conditions(), ConditionType, err.Error()) return errors.WithMessage(err, "error trying to check if setting exists") } @@ -69,7 +69,7 @@ func (r *reconciler) checkLogMonitoringSettings(ctx context.Context) error { if logMonitoringSettings.TotalCount > 0 { log.Info("there are already settings", "settings", logMonitoringSettings) - setLogMonitoringSettingExists(r.dk.Conditions(), conditionType) + setLogMonitoringSettingExists(r.dk.Conditions(), ConditionType) return nil } @@ -82,7 +82,7 @@ func (r *reconciler) checkLogMonitoringSettings(ctx context.Context) error { objectId, err := r.dtc.CreateLogMonitoringSetting(ctx, r.dk.Status.KubernetesClusterMEID, r.dk.Status.KubernetesClusterName, matchers) if err != nil { - setLogMonitoringSettingError(r.dk.Conditions(), conditionType, err.Error()) + setLogMonitoringSettingError(r.dk.Conditions(), ConditionType, err.Error()) return err } diff --git a/test/features/consts/consts.go b/test/features/consts/consts.go index 4d5aff03c8..74d27c9971 100644 --- a/test/features/consts/consts.go +++ b/test/features/consts/consts.go @@ -8,4 +8,6 @@ const ( DevRegistryPullSecretName = "devregistry" EecImageRepo = "478983378254.dkr.ecr.us-east-1.amazonaws.com/dynatrace/dynatrace-eec" EecImageTag = "1.303.0.20240930-183404" + LogMonitoringImageRepo = "public.ecr.aws/dynatrace/dynatrace-logmodule" + LogMonitoringImageTag = "1.309.59.20250319-140247" ) diff --git a/test/features/logmonitoring/logmonitoring.go b/test/features/logmonitoring/logmonitoring.go new file mode 100644 index 0000000000..d69180a514 --- /dev/null +++ b/test/features/logmonitoring/logmonitoring.go @@ -0,0 +1,125 @@ +//go:build e2e + +package logmonitoring + +import ( + "os" + "path" + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/configsecret" + lmdaemonset "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/daemonset" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/logmonitoring/logmonsettings" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/test/features/consts" + "github.com/Dynatrace/dynatrace-operator/test/helpers" + "github.com/Dynatrace/dynatrace-operator/test/helpers/components/activegate" + componentDynakube "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/daemonset" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/secret" + "github.com/Dynatrace/dynatrace-operator/test/helpers/platform" + "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" + "github.com/Dynatrace/dynatrace-operator/test/project" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/net/context" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" +) + +func Feature(t *testing.T) features.Feature { + builder := features.New("logmonitoring-components-rollout") + + secretConfig := tenant.GetSingleTenantSecret(t) + + options := []componentDynakube.Option{ + componentDynakube.WithApiUrl(secretConfig.ApiUrl), + componentDynakube.WithCustomPullSecret(consts.DevRegistryPullSecretName), + componentDynakube.WithLogMonitoring(), + componentDynakube.WithLogMonitoringImageRefSpec(consts.LogMonitoringImageRepo, consts.LogMonitoringImageTag), + componentDynakube.WithActiveGate(), + componentDynakube.WithActiveGateTLSSecret(consts.AgSecretName), + } + + isOpenshift, err := platform.NewResolver().IsOpenshift() + require.NoError(t, err) + if isOpenshift { + options = append(options, componentDynakube.WithAnnotations(map[string]string{ + dynakube.AnnotationFeatureRunOneAgentContainerPrivileged: "true", + })) + } + + testDynakube := *componentDynakube.New(options...) + + agCrt, err := os.ReadFile(path.Join(project.TestDataDir(), consts.AgCertificate)) + require.NoError(t, err) + + agP12, err := os.ReadFile(path.Join(project.TestDataDir(), consts.AgCertificateAndPrivateKey)) + require.NoError(t, err) + + agSecret := secret.New(consts.AgSecretName, testDynakube.Namespace, + map[string][]byte{ + dynakube.TLSCertKey: agCrt, + consts.AgCertificateAndPrivateKeyField: agP12, + }) + builder.Assess("create AG TLS secret", secret.Create(agSecret)) + + componentDynakube.Install(builder, helpers.LevelAssess, &secretConfig, testDynakube) + + builder.Assess("active gate pod is running", checkActiveGateContainer(&testDynakube)) + + builder.Assess("log agent started", daemonset.WaitForDaemonset(testDynakube.LogMonitoring().GetDaemonSetName(), testDynakube.Namespace)) + + builder.Assess("log monitoring conditions", checkConditions(testDynakube.Name, testDynakube.Namespace)) + + componentDynakube.Delete(builder, helpers.LevelTeardown, testDynakube) + + builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(testDynakube.Name, testDynakube.Namespace)) + + builder.WithTeardown("deleted ag secret", secret.Delete(agSecret)) + + return builder.Feature() +} + +func checkActiveGateContainer(dk *dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + resources := envConfig.Client().Resources() + + var activeGatePod corev1.Pod + require.NoError(t, resources.WithNamespace(dk.Namespace).Get(ctx, activegate.GetActiveGatePodName(dk, "activegate"), dk.Namespace, &activeGatePod)) + + require.NotNil(t, activeGatePod.Spec) + require.NotEmpty(t, activeGatePod.Spec.Containers) + + return ctx + } +} + +func checkConditions(name string, namespace string) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + dk := &dynakube.DynaKube{} + err := envConfig.Client().Resources().Get(ctx, name, namespace, dk) + require.NoError(t, err) + + condition := meta.FindStatusCondition(*dk.Conditions(), configsecret.LmcConditionType) + require.NotNil(t, condition) + assert.Equal(t, metav1.ConditionTrue, condition.Status) + assert.Equal(t, conditions.SecretCreatedReason, condition.Reason) + + condition = meta.FindStatusCondition(*dk.Conditions(), lmdaemonset.ConditionType) + require.NotNil(t, condition) + assert.Equal(t, metav1.ConditionTrue, condition.Status) + assert.Equal(t, conditions.DaemonSetSetCreatedReason, condition.Reason) + + condition = meta.FindStatusCondition(*dk.Conditions(), logmonsettings.ConditionType) + if condition != nil { + assert.NotEqual(t, metav1.ConditionFalse, condition.Status) + } + + return ctx + } +} diff --git a/test/helpers/components/dynakube/options.go b/test/helpers/components/dynakube/options.go index a6b51d74f5..9f1d246ce1 100644 --- a/test/helpers/components/dynakube/options.go +++ b/test/helpers/components/dynakube/options.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/value" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -182,3 +183,20 @@ func WithCustomPullSecret(secretName string) Option { dk.Spec.CustomPullSecret = secretName } } + +func WithLogMonitoring() Option { + return func(dk *dynakube.DynaKube) { + dk.Spec.LogMonitoring = &logmonitoring.Spec{} + } +} + +func WithLogMonitoringImageRefSpec(repo, tag string) Option { + return func(dk *dynakube.DynaKube) { + dk.Spec.Templates.LogMonitoring = &logmonitoring.TemplateSpec{ + ImageRef: image.Ref{ + Repository: repo, + Tag: tag, + }, + } + } +} diff --git a/test/helpers/kubeobjects/daemonset/wait.go b/test/helpers/kubeobjects/daemonset/wait.go index e3dce7825a..339e2b1b33 100644 --- a/test/helpers/kubeobjects/daemonset/wait.go +++ b/test/helpers/kubeobjects/daemonset/wait.go @@ -6,6 +6,7 @@ import ( "context" "time" + "github.com/Dynatrace/dynatrace-operator/test/helpers" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/e2e-framework/klient/k8s" @@ -13,6 +14,7 @@ import ( "sigs.k8s.io/e2e-framework/klient/wait/conditions" "sigs.k8s.io/e2e-framework/pkg/env" "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" ) func WaitFor(name string, namespace string) env.Func { @@ -33,3 +35,7 @@ func WaitFor(name string, namespace string) env.Func { return ctx, err } } + +func WaitForDaemonset(name string, namespace string) features.Func { + return helpers.ToFeatureFunc(WaitFor(name, namespace), true) +} diff --git a/test/scenarios/no_csi/no_csi_test.go b/test/scenarios/no_csi/no_csi_test.go index d14736a587..2c3f4d6e4d 100644 --- a/test/scenarios/no_csi/no_csi_test.go +++ b/test/scenarios/no_csi/no_csi_test.go @@ -11,6 +11,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/test/features/classic" "github.com/Dynatrace/dynatrace-operator/test/features/edgeconnect" "github.com/Dynatrace/dynatrace-operator/test/features/extensions" + "github.com/Dynatrace/dynatrace-operator/test/features/logmonitoring" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/environment" @@ -51,6 +52,7 @@ func TestNoCSI(t *testing.T) { edgeconnect.AutomationModeFeature(t), classic.Feature(t), bootstrapper.NoCSI(t), + logmonitoring.Feature(t), } testEnv.Test(t, scenarios.FilterFeatures(*cfg, feats)...) From eb0860cc4b40cf16b11dfa32d1fe7330c2e3eb0a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 21 Mar 2025 21:35:43 +0000 Subject: [PATCH 352/426] chore(deps): update module github.com/daixiang0/gci to v0.13.6 (main) (#4637) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 9900ef28b3..1c3a39072a 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -5,7 +5,7 @@ controller_gen_version=v0.17.2 # renovate depName=github.com/golangci/golangci-lint golang_ci_cmd_version=v1.64.8 # renovate depName=github.com/daixiang0/gci -gci_version=v0.13.5 +gci_version=v0.13.6 # renovate depName=golang.org/x/tools golang_tools_version=v0.31.0 # renovate depName=github.com/vektra/mockery From 1a8c943b4b9cece52ce6a600e990450f840077a7 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Mon, 24 Mar 2025 10:42:48 +0100 Subject: [PATCH 353/426] Makes `terminationGracePeriodSeconds` configurable for ActiveGate (#4642) Co-authored-by: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> --- config/crd/bases/dynatrace.com_dynakubes.yaml | 5 +++ .../Common/crd/dynatrace-operator-crd.yaml | 5 +++ doc/api/dynakube-api-ref.md | 1 + pkg/api/v1beta4/dynakube/activegate/props.go | 3 ++ pkg/api/v1beta4/dynakube/activegate/spec.go | 4 +++ .../activegate/zz_generated.deepcopy.go | 5 +++ .../internal/statefulset/statefulset.go | 24 ++++++------- .../internal/statefulset/statefulset_test.go | 36 +++++++++++++++++++ 8 files changed, 71 insertions(+), 12 deletions(-) diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index 3fa148f9db..70884149e1 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -8073,6 +8073,11 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + terminationGracePeriodSeconds: + description: Configures the terminationGracePeriodSeconds parameter + of the ActiveGate pod. Kubernetes defaults and rules apply. + format: int64 + type: integer tlsSecretName: description: |- The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index da5fcf4271..4b0417758e 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -8085,6 +8085,11 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + terminationGracePeriodSeconds: + description: Configures the terminationGracePeriodSeconds parameter + of the ActiveGate pod. Kubernetes defaults and rules apply. + format: int64 + type: integer tlsSecretName: description: |- The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. diff --git a/doc/api/dynakube-api-ref.md b/doc/api/dynakube-api-ref.md index 1d6d82a509..d85e4309e3 100644 --- a/doc/api/dynakube-api-ref.md +++ b/doc/api/dynakube-api-ref.md @@ -38,6 +38,7 @@ |`priorityClassName`|If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that
name. If not specified the setting will be removed from the StatefulSet.|-|string| |`replicas`|Amount of replicas for your ActiveGates|-|integer| |`resources`|Define resources requests and limits for single ActiveGate pods|-|object| +|`terminationGracePeriodSeconds`|Configures the terminationGracePeriodSeconds parameter of the ActiveGate pod. Kubernetes defaults and rules apply.|-|integer| |`tlsSecretName`|The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used.
server.p12: certificate+key pair in pkcs12 format
password: passphrase to read server.p12|-|string| |`tolerations`|Set tolerations for the ActiveGate pods|-|array| |`topologySpreadConstraints`|Adds TopologySpreadConstraints for the ActiveGate pods|-|array| diff --git a/pkg/api/v1beta4/dynakube/activegate/props.go b/pkg/api/v1beta4/dynakube/activegate/props.go index e6d70e5f3f..49fde94e5a 100644 --- a/pkg/api/v1beta4/dynakube/activegate/props.go +++ b/pkg/api/v1beta4/dynakube/activegate/props.go @@ -152,3 +152,6 @@ func (ag *Spec) GetDefaultImage(version string) string { func (ag *Spec) GetCustomImage() string { return ag.Image } + +// GetTerminationGracePeriodSeconds provides the configured value for the terminatGracePeriodSeconds parameter of the pod. +func (ag *Spec) GetTerminationGracePeriodSeconds() *int64 { return ag.TerminationGracePeriodSeconds } diff --git a/pkg/api/v1beta4/dynakube/activegate/spec.go b/pkg/api/v1beta4/dynakube/activegate/spec.go index f4323e6624..2dcbdbda81 100644 --- a/pkg/api/v1beta4/dynakube/activegate/spec.go +++ b/pkg/api/v1beta4/dynakube/activegate/spec.go @@ -86,6 +86,10 @@ type Spec struct { // +kubebuilder:validation:Optional PersistentVolumeClaim *corev1.PersistentVolumeClaimSpec `json:"persistentVolumeClaim,omitempty"` + // Configures the terminationGracePeriodSeconds parameter of the ActiveGate pod. Kubernetes defaults and rules apply. + // +kubebuild:validation:Optional + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"` + name string apiUrl string diff --git a/pkg/api/v1beta4/dynakube/activegate/zz_generated.deepcopy.go b/pkg/api/v1beta4/dynakube/activegate/zz_generated.deepcopy.go index 910cebcf43..4db276bb51 100644 --- a/pkg/api/v1beta4/dynakube/activegate/zz_generated.deepcopy.go +++ b/pkg/api/v1beta4/dynakube/activegate/zz_generated.deepcopy.go @@ -99,6 +99,11 @@ func (in *Spec) DeepCopyInto(out *Spec) { *out = new(v1.PersistentVolumeClaimSpec) (*in).DeepCopyInto(*out) } + if in.TerminationGracePeriodSeconds != nil { + in, out := &in.TerminationGracePeriodSeconds, &out.TerminationGracePeriodSeconds + *out = new(int64) + **out = **in + } in.CapabilityProperties.DeepCopyInto(&out.CapabilityProperties) if in.Capabilities != nil { in, out := &in.Capabilities, &out.Capabilities diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index 62a2144815..83311547c9 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -119,18 +119,18 @@ func (statefulSetBuilder Builder) addUserAnnotations(sts *appsv1.StatefulSet) { func (statefulSetBuilder Builder) addTemplateSpec(sts *appsv1.StatefulSet) { podSpec := corev1.PodSpec{ - Containers: statefulSetBuilder.buildBaseContainer(), - NodeSelector: statefulSetBuilder.capability.Properties().NodeSelector, - ServiceAccountName: statefulSetBuilder.dynakube.ActiveGate().GetServiceAccountName(), - Affinity: statefulSetBuilder.nodeAffinity(), - Tolerations: statefulSetBuilder.capability.Properties().Tolerations, - SecurityContext: statefulSetBuilder.buildPodSecurityContext(), - ImagePullSecrets: statefulSetBuilder.dynakube.ImagePullSecretReferences(), - PriorityClassName: statefulSetBuilder.dynakube.Spec.ActiveGate.PriorityClassName, - DNSPolicy: statefulSetBuilder.dynakube.Spec.ActiveGate.DNSPolicy, - - TopologySpreadConstraints: statefulSetBuilder.buildTopologySpreadConstraints(statefulSetBuilder.capability), - Volumes: statefulSetBuilder.buildVolumes(), + Containers: statefulSetBuilder.buildBaseContainer(), + NodeSelector: statefulSetBuilder.capability.Properties().NodeSelector, + ServiceAccountName: statefulSetBuilder.dynakube.ActiveGate().GetServiceAccountName(), + Affinity: statefulSetBuilder.nodeAffinity(), + Tolerations: statefulSetBuilder.capability.Properties().Tolerations, + SecurityContext: statefulSetBuilder.buildPodSecurityContext(), + ImagePullSecrets: statefulSetBuilder.dynakube.ImagePullSecretReferences(), + PriorityClassName: statefulSetBuilder.dynakube.Spec.ActiveGate.PriorityClassName, + DNSPolicy: statefulSetBuilder.dynakube.Spec.ActiveGate.DNSPolicy, + TerminationGracePeriodSeconds: statefulSetBuilder.dynakube.ActiveGate().GetTerminationGracePeriodSeconds(), + TopologySpreadConstraints: statefulSetBuilder.buildTopologySpreadConstraints(statefulSetBuilder.capability), + Volumes: statefulSetBuilder.buildVolumes(), } sts.Spec.Template.Spec = podSpec } diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index db5332f136..aa1967d83a 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -637,3 +637,39 @@ func TestVolumeMounts(t *testing.T) { require.Contains(t, sts.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) }) } + +func TestTerminationGracePeriodSeconds(t *testing.T) { + tests := []struct { + name string + gracePeriodSeconds *int64 + }{ + { + name: "gracePeriodSeconds is zero", + gracePeriodSeconds: ptr.To(int64(0)), + }, + { + name: "gracePeriodSeconds is positive", + gracePeriodSeconds: ptr.To(int64(1)), + }, + { + name: "gracePeriodSeconds is negative", + gracePeriodSeconds: ptr.To(int64(-1)), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + dk := getTestDynakube() + dk.ActiveGate().TerminationGracePeriodSeconds = test.gracePeriodSeconds + assert.Equal(t, *test.gracePeriodSeconds, *dk.ActiveGate().GetTerminationGracePeriodSeconds()) + }) + } +} + +func TestTerminationGracePeriodSecondsNil(t *testing.T) { + t.Run("gracePeriodSeconds is nil", func(t *testing.T) { + dk := getTestDynakube() + dk.ActiveGate().TerminationGracePeriodSeconds = nil + assert.Nil(t, dk.ActiveGate().GetTerminationGracePeriodSeconds()) + }) +} From c2691b77213ea461cf3c229f6eabeb0608dccec8 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Mon, 24 Mar 2025 15:29:42 +0100 Subject: [PATCH 354/426] Sets PVC Hash on ActiveGate StatefulSet (#4645) Co-authored-by: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> --- .../internal/statefulset/statefulset.go | 3 ++ .../internal/statefulset/statefulset_test.go | 28 +++++++++++-------- pkg/util/kubeobjects/statefulset/builder.go | 11 ++------ pkg/util/kubeobjects/statefulset/consts.go | 7 +++++ pkg/util/kubeobjects/statefulset/query.go | 4 +-- 5 files changed, 31 insertions(+), 22 deletions(-) create mode 100644 pkg/util/kubeobjects/statefulset/consts.go diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index 83311547c9..9109098a6a 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -12,6 +12,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/deploymentmetadata" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/statefulset" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" "github.com/Dynatrace/dynatrace-operator/pkg/util/prioritymap" appsv1 "k8s.io/api/apps/v1" @@ -303,6 +304,8 @@ func (statefulSetBuilder Builder) addPersistentVolumeClaim(sts *appsv1.StatefulS } sts.Spec.PersistentVolumeClaimRetentionPolicy = defaultPVCRetentionPolicy() } + + statefulset.SetPVCAnnotation()(sts) } func defaultPVCSpec() corev1.PersistentVolumeClaimSpec { diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index aa1967d83a..15999b25a6 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -18,6 +18,7 @@ import ( agutil "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/statefulset" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/exp/slices" @@ -491,7 +492,7 @@ func TestSecurityContexts(t *testing.T) { } func TestTempVolume(t *testing.T) { - myPVCspec := corev1.PersistentVolumeClaimSpec{ + myPVCSpec := corev1.PersistentVolumeClaimSpec{ StorageClassName: ptr.To("test"), VolumeName: "foo-pv", } @@ -540,39 +541,39 @@ func TestTempVolume(t *testing.T) { }, { name: "custom PVC and no EmptyDir when PersistentVolumeClaim != nil, TelemetryIngest enabled, UseEphemeralVolume = false", - pvc: &myPVCspec, + pvc: &myPVCSpec, telemetryIngest: &telemetryingest.Spec{}, useEphemeral: false, emptyDirExpected: false, pvcExpected: true, - expectedPvcSpec: myPVCspec, + expectedPvcSpec: myPVCSpec, }, { name: "custom PVC and no EmptyDir when PersistentVolumeClaim != nil, TelemetryIngest enabled, UseEphemeralVolume = true", - pvc: &myPVCspec, + pvc: &myPVCSpec, telemetryIngest: &telemetryingest.Spec{}, useEphemeral: true, emptyDirExpected: false, pvcExpected: true, - expectedPvcSpec: myPVCspec, + expectedPvcSpec: myPVCSpec, }, { name: "custom PVC and no EmptyDir when PersistentVolumeClaim != nil, TelemetryIngest not enabled, UseEphemeralVolume = false", - pvc: &myPVCspec, + pvc: &myPVCSpec, telemetryIngest: nil, useEphemeral: false, emptyDirExpected: false, pvcExpected: true, - expectedPvcSpec: myPVCspec, + expectedPvcSpec: myPVCSpec, }, { name: "custom PVC and no EmptyDir when PersistentVolumeClaim != nil, TelemetryIngest not enabled, UseEphemeralVolume = true", - pvc: &myPVCspec, + pvc: &myPVCSpec, telemetryIngest: nil, useEphemeral: true, emptyDirExpected: false, pvcExpected: true, - expectedPvcSpec: myPVCspec, + expectedPvcSpec: myPVCSpec, }, } @@ -608,11 +609,14 @@ func TestTempVolume(t *testing.T) { if test.pvcExpected { require.Len(t, sts.Spec.VolumeClaimTemplates, 1) - require.Equal(t, test.expectedPvcSpec, sts.Spec.VolumeClaimTemplates[0].Spec) - require.Equal(t, consts.GatewayTmpVolumeName, sts.Spec.VolumeClaimTemplates[0].Name) - require.Equal(t, defaultPVCRetentionPolicy(), sts.Spec.PersistentVolumeClaimRetentionPolicy) + assert.Equal(t, test.expectedPvcSpec, sts.Spec.VolumeClaimTemplates[0].Spec) + assert.Equal(t, consts.GatewayTmpVolumeName, sts.Spec.VolumeClaimTemplates[0].Name) + assert.Equal(t, defaultPVCRetentionPolicy(), sts.Spec.PersistentVolumeClaimRetentionPolicy) + + assert.Contains(t, sts.Annotations, statefulset.AnnotationPVCHash) } else { require.Empty(t, sts.Spec.VolumeClaimTemplates) + assert.NotContains(t, sts.Annotations, statefulset.AnnotationPVCHash) } }) } diff --git a/pkg/util/kubeobjects/statefulset/builder.go b/pkg/util/kubeobjects/statefulset/builder.go index 160040eb35..d8a285b207 100644 --- a/pkg/util/kubeobjects/statefulset/builder.go +++ b/pkg/util/kubeobjects/statefulset/builder.go @@ -1,7 +1,6 @@ package statefulset import ( - "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/internal/builder" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" @@ -11,10 +10,6 @@ import ( "k8s.io/utils/ptr" ) -const ( - pvcAnnotationHash = api.InternalFlagPrefix + "pvc-hash" -) - var ( // Mandatory fields, provided in constructor as named params setName = builder.SetName[*appsv1.StatefulSet] @@ -32,7 +27,7 @@ func Build(owner metav1.Object, name string, container corev1.Container, options } neededOpts = append(neededOpts, options...) - neededOpts = append(neededOpts, setPVCAnnotation()) + neededOpts = append(neededOpts, SetPVCAnnotation()) return builder.Build(owner, &appsv1.StatefulSet{}, neededOpts...) } @@ -125,14 +120,14 @@ func SetRollingUpdateStrategyType() builder.Option[*appsv1.StatefulSet] { } } -func setPVCAnnotation() builder.Option[*appsv1.StatefulSet] { +func SetPVCAnnotation() builder.Option[*appsv1.StatefulSet] { return func(s *appsv1.StatefulSet) { if s.Spec.VolumeClaimTemplates != nil { if s.ObjectMeta.Annotations == nil { s.ObjectMeta.Annotations = map[string]string{} } - s.ObjectMeta.Annotations[pvcAnnotationHash], _ = hasher.GenerateHash(s.Spec.VolumeClaimTemplates) + s.ObjectMeta.Annotations[AnnotationPVCHash], _ = hasher.GenerateHash(s.Spec.VolumeClaimTemplates) } } } diff --git a/pkg/util/kubeobjects/statefulset/consts.go b/pkg/util/kubeobjects/statefulset/consts.go new file mode 100644 index 0000000000..885d16756e --- /dev/null +++ b/pkg/util/kubeobjects/statefulset/consts.go @@ -0,0 +1,7 @@ +package statefulset + +import "github.com/Dynatrace/dynatrace-operator/pkg/api" + +const ( + AnnotationPVCHash = api.InternalFlagPrefix + "pvc-hash" +) diff --git a/pkg/util/kubeobjects/statefulset/query.go b/pkg/util/kubeobjects/statefulset/query.go index 39a841f4d8..c5c76401c8 100644 --- a/pkg/util/kubeobjects/statefulset/query.go +++ b/pkg/util/kubeobjects/statefulset/query.go @@ -35,8 +35,8 @@ func isEqual(current, desired *appsv1.StatefulSet) bool { } func mustRecreate(current, desired *appsv1.StatefulSet) bool { - currentHash := current.Annotations[pvcAnnotationHash] - desiredHash := desired.Annotations[pvcAnnotationHash] + currentHash := current.Annotations[AnnotationPVCHash] + desiredHash := desired.Annotations[AnnotationPVCHash] return labels.NotEqual(current.Spec.Selector.MatchLabels, desired.Spec.Selector.MatchLabels) || currentHash != desiredHash } From c6a4cbc6558fe463bf8f4b77eb6123a2c72c073a Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Mon, 24 Mar 2025 15:39:42 +0100 Subject: [PATCH 355/426] Update dynatrace-bootstrapper to v1.0.2 (#4647) --- go.mod | 2 +- go.sum | 4 ++-- pkg/webhook/mutation/pod/v2/attributes.go | 14 ++++++-------- pkg/webhook/mutation/pod/v2/attributes_test.go | 12 +++++++----- pkg/webhook/mutation/pod/v2/init.go | 5 +++-- pkg/webhook/mutation/pod/v2/init_test.go | 11 ++++++----- pkg/webhook/mutation/pod/v2/metadata/containers.go | 2 +- .../mutation/pod/v2/oneagent/containers_test.go | 2 +- pkg/webhook/mutation/pod/v2/oneagent/init.go | 14 +++++--------- pkg/webhook/mutation/pod/v2/oneagent/volumes.go | 3 ++- 10 files changed, 34 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index e1378553b3..78756def48 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Dynatrace/dynatrace-operator go 1.23.4 require ( - github.com/Dynatrace/dynatrace-bootstrapper v1.0.1 + github.com/Dynatrace/dynatrace-bootstrapper v1.0.2 github.com/container-storage-interface/spec v1.11.0 github.com/docker/cli v28.0.2+incompatible github.com/evanphx/json-patch v5.9.11+incompatible diff --git a/go.sum b/go.sum index 87a21bbf0a..c5889e7f68 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/Dynatrace/dynatrace-bootstrapper v1.0.1 h1:AokYM0BuvMdn/UBC66d4Ug2TgGbFuPi1pk6idKbngwo= -github.com/Dynatrace/dynatrace-bootstrapper v1.0.1/go.mod h1:umzzdF2rIRhUBpYHVHLGVjfvMJVa/SK8RXbLvtyA6Ts= +github.com/Dynatrace/dynatrace-bootstrapper v1.0.2 h1:IdjAJwJ7sT+q0TTyQxGcJlUif5Y7lVYJWJUQ/u/h0Tw= +github.com/Dynatrace/dynatrace-bootstrapper v1.0.2/go.mod h1:iNHaw8wmanlJCBkKG7LzAJjWDZCo3xxZmwxM33Zm4GU= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= diff --git a/pkg/webhook/mutation/pod/v2/attributes.go b/pkg/webhook/mutation/pod/v2/attributes.go index 81b58ae3dd..200d52fed1 100644 --- a/pkg/webhook/mutation/pod/v2/attributes.go +++ b/pkg/webhook/mutation/pod/v2/attributes.go @@ -4,8 +4,8 @@ import ( "fmt" "strings" - containerattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/container" - podattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/pod" + containerattr "github.com/Dynatrace/dynatrace-bootstrapper/cmd/configure/attributes/container" + podattr "github.com/Dynatrace/dynatrace-bootstrapper/cmd/configure/attributes/pod" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/mounts" @@ -19,16 +19,14 @@ func (wh *Injector) addPodAttributes(request *dtwebhook.MutationRequest) error { attrs := podattr.Attributes{ PodInfo: podattr.PodInfo{ PodName: createEnvVarRef(consts.K8sPodNameEnv), - PodUid: createEnvVarRef(consts.K8sPodUIDEnv), + PodUID: createEnvVarRef(consts.K8sPodUIDEnv), + NodeName: createEnvVarRef(consts.K8sNodeNameEnv), NamespaceName: request.Pod.Namespace, }, ClusterInfo: podattr.ClusterInfo{ - ClusterUId: request.DynaKube.Status.KubeSystemUUID, + ClusterUID: request.DynaKube.Status.KubeSystemUUID, DTClusterEntity: request.DynaKube.Status.KubernetesClusterMEID, - }, - UserDefined: map[string]string{ - "k8s.cluster.name": request.DynaKube.Status.KubernetesClusterName, // TODO: make it part of podattr.Attributes - "k8s.node.name": createEnvVarRef(consts.K8sNodeNameEnv), // TODO: make it part of podattr.Attributes + ClusterName: request.DynaKube.Status.KubernetesClusterName, }, } diff --git a/pkg/webhook/mutation/pod/v2/attributes_test.go b/pkg/webhook/mutation/pod/v2/attributes_test.go index 753e36464d..b2e8367782 100644 --- a/pkg/webhook/mutation/pod/v2/attributes_test.go +++ b/pkg/webhook/mutation/pod/v2/attributes_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" - containerattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/container" - podattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/pod" + containerattr "github.com/Dynatrace/dynatrace-bootstrapper/cmd/configure/attributes/container" + podattr "github.com/Dynatrace/dynatrace-bootstrapper/cmd/configure/attributes/pod" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" @@ -39,9 +39,11 @@ func TestAddPodAttributes(t *testing.T) { require.NoError(t, err) assert.Equal(t, request.DynaKube.Status.KubernetesClusterMEID, attr.DTClusterEntity) - assert.Equal(t, request.DynaKube.Status.KubeSystemUUID, attr.ClusterUId) + assert.Equal(t, request.DynaKube.Status.KubernetesClusterName, attr.ClusterName) + assert.Equal(t, request.DynaKube.Status.KubeSystemUUID, attr.ClusterUID) assert.Contains(t, attr.PodName, consts.K8sPodNameEnv) - assert.Contains(t, attr.PodUid, consts.K8sPodUIDEnv) + assert.Contains(t, attr.PodUID, consts.K8sPodUIDEnv) + assert.Contains(t, attr.NodeName, consts.K8sNodeNameEnv) assert.Equal(t, request.Pod.Namespace, attr.NamespaceName) require.Len(t, request.InstallContainer.Env, 3) @@ -69,7 +71,7 @@ func TestAddPodAttributes(t *testing.T) { } } - assert.Len(t, attr.UserDefined, metaAnnotationCount+2) // TODO: this +2 should be removed once k8s.node.name and k8s.cluster.name are part of the actual Attributes + assert.Len(t, attr.UserDefined, metaAnnotationCount) require.Len(t, request.Pod.Annotations, 3+metaAnnotationCount) assert.Equal(t, strings.ToLower(request.Pod.OwnerReferences[0].Kind), request.Pod.Annotations[metacommon.AnnotationWorkloadKind]) assert.Equal(t, request.Pod.OwnerReferences[0].Name, request.Pod.Annotations[metacommon.AnnotationWorkloadName]) diff --git a/pkg/webhook/mutation/pod/v2/init.go b/pkg/webhook/mutation/pod/v2/init.go index a44976df96..bea039e770 100644 --- a/pkg/webhook/mutation/pod/v2/init.go +++ b/pkg/webhook/mutation/pod/v2/init.go @@ -1,7 +1,8 @@ package v2 import ( - "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure" + "github.com/Dynatrace/dynatrace-bootstrapper/cmd" + "github.com/Dynatrace/dynatrace-bootstrapper/cmd/configure" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" @@ -25,7 +26,7 @@ func createInitContainerBase(pod *corev1.Pod, dk dynakube.DynaKube) *corev1.Cont } if areErrorsSuppressed(pod, dk) { - args = append(args, arg.Arg{Name: "suppress-error"}) // TODO: import arg from bootstrapper package + args = append(args, arg.Arg{Name: cmd.SuppressErrorsFlag}) } initContainer := &corev1.Container{ diff --git a/pkg/webhook/mutation/pod/v2/init_test.go b/pkg/webhook/mutation/pod/v2/init_test.go index b43c3c7241..719abcb76d 100644 --- a/pkg/webhook/mutation/pod/v2/init_test.go +++ b/pkg/webhook/mutation/pod/v2/init_test.go @@ -3,6 +3,7 @@ package v2 import ( "testing" + "github.com/Dynatrace/dynatrace-bootstrapper/cmd" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/mounts" volumeutils "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/volumes" @@ -124,7 +125,7 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer := createInitContainerBase(pod, *dk) - assert.NotContains(t, initContainer.Args, "--suppress-error") + assert.NotContains(t, initContainer.Args, "--"+cmd.SuppressErrorsFlag) }) t.Run("should not set suppress-error arg - according to pod", func(t *testing.T) { @@ -135,7 +136,7 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer := createInitContainerBase(pod, *dk) - assert.NotContains(t, initContainer.Args, "--suppress-error") + assert.NotContains(t, initContainer.Args, "--"+cmd.SuppressErrorsFlag) }) t.Run("should set suppress-error arg - default", func(t *testing.T) { @@ -146,7 +147,7 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer := createInitContainerBase(pod, *dk) - assert.Contains(t, initContainer.Args, "--suppress-error") + assert.Contains(t, initContainer.Args, "--"+cmd.SuppressErrorsFlag) }) t.Run("should set suppress-error arg - unknown value", func(t *testing.T) { @@ -157,7 +158,7 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer := createInitContainerBase(pod, *dk) - assert.Contains(t, initContainer.Args, "--suppress-error") + assert.Contains(t, initContainer.Args, "--"+cmd.SuppressErrorsFlag) dk = getTestDynakube() dk.Annotations = map[string]string{} @@ -166,7 +167,7 @@ func TestCreateInitContainerBase(t *testing.T) { initContainer = createInitContainerBase(pod, *dk) - assert.Contains(t, initContainer.Args, "--suppress-error") + assert.Contains(t, initContainer.Args, "--"+cmd.SuppressErrorsFlag) }) } diff --git a/pkg/webhook/mutation/pod/v2/metadata/containers.go b/pkg/webhook/mutation/pod/v2/metadata/containers.go index d7339ea95a..badf586f64 100644 --- a/pkg/webhook/mutation/pod/v2/metadata/containers.go +++ b/pkg/webhook/mutation/pod/v2/metadata/containers.go @@ -4,7 +4,7 @@ import ( "maps" "strings" - podattr "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/attributes/pod" + podattr "github.com/Dynatrace/dynatrace-bootstrapper/cmd/configure/attributes/pod" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" metacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/metadata" diff --git a/pkg/webhook/mutation/pod/v2/oneagent/containers_test.go b/pkg/webhook/mutation/pod/v2/oneagent/containers_test.go index 856ceaf954..1b5bba10ac 100644 --- a/pkg/webhook/mutation/pod/v2/oneagent/containers_test.go +++ b/pkg/webhook/mutation/pod/v2/oneagent/containers_test.go @@ -3,7 +3,7 @@ package oneagent import ( "testing" - "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure" + "github.com/Dynatrace/dynatrace-bootstrapper/cmd/configure" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" diff --git a/pkg/webhook/mutation/pod/v2/oneagent/init.go b/pkg/webhook/mutation/pod/v2/oneagent/init.go index 065a54847c..fc2e391989 100644 --- a/pkg/webhook/mutation/pod/v2/oneagent/init.go +++ b/pkg/webhook/mutation/pod/v2/oneagent/init.go @@ -1,8 +1,9 @@ package oneagent import ( - "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure" - "github.com/Dynatrace/dynatrace-bootstrapper/pkg/move" + "github.com/Dynatrace/dynatrace-bootstrapper/cmd" + "github.com/Dynatrace/dynatrace-bootstrapper/cmd/configure" + "github.com/Dynatrace/dynatrace-bootstrapper/cmd/move" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" @@ -11,11 +12,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -const ( - bootstrapperSourceArgument = "source" // TODO import consts from bootstrapper - bootstrapperTargetArgument = "target" -) - func mutateInitContainer(mutationRequest *dtwebhook.MutationRequest, installPath string) { addInitArgs(*mutationRequest.Pod, mutationRequest.InstallContainer, mutationRequest.DynaKube, installPath) addInitVolumeMounts(mutationRequest.InstallContainer) @@ -23,8 +19,8 @@ func mutateInitContainer(mutationRequest *dtwebhook.MutationRequest, installPath func addInitArgs(pod corev1.Pod, initContainer *corev1.Container, dk dynakube.DynaKube, installPath string) { args := []arg.Arg{ - {Name: bootstrapperSourceArgument, Value: consts.AgentCodeModuleSource}, // TODO import consts from bootstrapper - {Name: bootstrapperTargetArgument, Value: binInitMountPath}, + {Name: cmd.SourceFolderFlag, Value: consts.AgentCodeModuleSource}, + {Name: cmd.TargetFolderFlag, Value: binInitMountPath}, {Name: configure.InstallPathFlag, Value: installPath}, } diff --git a/pkg/webhook/mutation/pod/v2/oneagent/volumes.go b/pkg/webhook/mutation/pod/v2/oneagent/volumes.go index c7de5c2f82..d2b7c41337 100644 --- a/pkg/webhook/mutation/pod/v2/oneagent/volumes.go +++ b/pkg/webhook/mutation/pod/v2/oneagent/volumes.go @@ -3,6 +3,7 @@ package oneagent import ( "path/filepath" + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/preload" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2/common/volumes" corev1 "k8s.io/api/core/v1" ) @@ -12,7 +13,7 @@ const ( binInitMountPath = "/mnt/bin" ldPreloadPath = "/etc/ld.so.preload" - ldPreloadSubPath = "oneagent/ld.so.preload" // TODO: Get from the bootsrapper lib. + ldPreloadSubPath = preload.ConfigPath ) func addVolumeMounts(container *corev1.Container, installPath string) { From f7eb8e341249cc3c6a8b032b36b0fd50b36655b5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 14:54:02 +0000 Subject: [PATCH 356/426] chore(deps): update github/codeql-action action to v3.28.13 (main) (#4648) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index d501b4c0f2..44267af5ed 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12 + uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12 + uses: github/codeql-action/autobuild@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12 + uses: github/codeql-action/analyze@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index fc51bce893..52ba2247a9 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12 + uses: github/codeql-action/upload-sarif@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 with: sarif_file: results.sarif From 7777660d91f6bd2ed26c53a9c6ab84b81ec88c52 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 17:08:12 +0000 Subject: [PATCH 357/426] fix(deps): update module sigs.k8s.io/controller-runtime to v0.20.4 (main) (#4652) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 78756def48..038b12e45f 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( k8s.io/client-go v0.32.3 k8s.io/mount-utils v0.32.3 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - sigs.k8s.io/controller-runtime v0.20.3 + sigs.k8s.io/controller-runtime v0.20.4 sigs.k8s.io/e2e-framework v0.3.0 sigs.k8s.io/yaml v1.4.0 ) diff --git a/go.sum b/go.sum index c5889e7f68..56292fade8 100644 --- a/go.sum +++ b/go.sum @@ -399,8 +399,8 @@ k8s.io/mount-utils v0.32.3 h1:ZPXXHblfBhYP89OnaozpFg9Ojl6HhDfxBLcdWNkaxW8= k8s.io/mount-utils v0.32.3/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.20.3 h1:I6Ln8JfQjHH7JbtCD2HCYHoIzajoRxPNuvhvcDbZgkI= -sigs.k8s.io/controller-runtime v0.20.3/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= +sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= +sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/e2e-framework v0.3.0 h1:eqQALBtPCth8+ulTs6lcPK7ytV5rZSSHJzQHZph4O7U= sigs.k8s.io/e2e-framework v0.3.0/go.mod h1:C+ef37/D90Dc7Xq1jQnNbJYscrUGpxrWog9bx2KIa+c= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= From 8f8350edaef10d26beb43602575efbb19e2230ae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 08:59:55 +0000 Subject: [PATCH 358/426] chore(deps): update actions/setup-python action to v5.5.0 (main) (#4653) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/self-update-on-new-release-version.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/self-update-on-new-release-version.yaml b/.github/workflows/self-update-on-new-release-version.yaml index 359f01e3ca..741aace543 100644 --- a/.github/workflows/self-update-on-new-release-version.yaml +++ b/.github/workflows/self-update-on-new-release-version.yaml @@ -17,7 +17,7 @@ jobs: with: ref: main - name: Install Python - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 + uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0 with: python-version: '3.13' - name: Install python requirements From 2411d3456073aea36ad50e3bdf9a3b028f0363e8 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Tue, 25 Mar 2025 13:29:02 +0100 Subject: [PATCH 359/426] Add volume-type annotation (#4639) --- pkg/api/v1beta4/dynakube/dynakube_props.go | 4 - .../dynakube/injection/reconciler.go | 32 ++-- .../dynakube/injection/reconciler_test.go | 173 ++++++++++++++++++ .../processmoduleconfigsecret/reconciler.go | 6 +- .../namespace/bootstrapperconfig/replicate.go | 14 +- .../mutation/pod/common/oneagent/config.go | 4 +- .../mutation/pod/common/oneagent/mutator.go | 5 + pkg/webhook/mutation/pod/v2/webhook.go | 46 +++-- pkg/webhook/mutation/pod/v2/webhook_test.go | 83 +++++++++ pkg/webhook/mutation/pod/webhook.go | 4 +- 10 files changed, 330 insertions(+), 41 deletions(-) diff --git a/pkg/api/v1beta4/dynakube/dynakube_props.go b/pkg/api/v1beta4/dynakube/dynakube_props.go index c0db3da247..66b73ad319 100644 --- a/pkg/api/v1beta4/dynakube/dynakube_props.go +++ b/pkg/api/v1beta4/dynakube/dynakube_props.go @@ -104,7 +104,3 @@ func (dk *DynaKube) ApiRequestThreshold() time.Duration { func (dk *DynaKube) IsTokenScopeVerificationAllowed(timeProvider *timeprovider.Provider) bool { return timeProvider.IsOutdated(&dk.Status.DynatraceApi.LastTokenScopeRequest, dk.ApiRequestThreshold()) } - -func (dk *DynaKube) FeatureBootstrapperInjection() bool { - return dk.OneAgent().IsApplicationMonitoringMode() && dk.FeatureNodeImagePull() && !dk.OneAgent().IsCSIAvailable() -} diff --git a/pkg/controllers/dynakube/injection/reconciler.go b/pkg/controllers/dynakube/injection/reconciler.go index bc0180098e..02d8d27fb6 100644 --- a/pkg/controllers/dynakube/injection/reconciler.go +++ b/pkg/controllers/dynakube/injection/reconciler.go @@ -135,11 +135,9 @@ func (r *reconciler) setupOneAgentInjection(ctx context.Context) error { return err } - if !r.dk.FeatureBootstrapperInjection() { - err = r.pmcSecretreconciler.Reconcile(ctx) - if err != nil { - return err - } + err = r.pmcSecretreconciler.Reconcile(ctx) + if err != nil { + return err } if r.istioReconciler != nil { @@ -172,7 +170,7 @@ func (r *reconciler) setupOneAgentInjection(ctx context.Context) error { func (r *reconciler) generateCorrectInitSecret(ctx context.Context) error { var err error - if r.dk.FeatureBootstrapperInjection() { + if r.dk.FeatureNodeImagePull() { err = bootstrapperconfig.NewSecretGenerator(r.client, r.apiReader, r.dynatraceClient).GenerateForDynakube(ctx, r.dk) if err != nil { if conditions.IsKubeApiError(err) { @@ -181,7 +179,9 @@ func (r *reconciler) generateCorrectInitSecret(ctx context.Context) error { return err } - } else { + } + + if !r.dk.FeatureNodeImagePull() || r.dk.OneAgent().IsCSIAvailable() { err = initgeneration.NewInitGenerator(r.client, r.apiReader, r.dk.Namespace).GenerateForDynakube(ctx, r.dk) if err != nil { if conditions.IsKubeApiError(err) { @@ -206,16 +206,14 @@ func (r *reconciler) cleanupOneAgentInjection(ctx context.Context) { return } - if r.dk.FeatureBootstrapperInjection() { - err = bootstrapperconfig.Cleanup(ctx, r.client, r.apiReader, namespaces, *r.dk) - if err != nil { - log.Error(err, "failed to clean-up bootstrapper code module injection init-secrets") - } - } else { - err = initgeneration.NewInitGenerator(r.client, r.apiReader, r.dk.Namespace).Cleanup(ctx, namespaces) - if err != nil { - log.Error(err, "failed to clean-up code module injection init-secrets") - } + err = bootstrapperconfig.Cleanup(ctx, r.client, r.apiReader, namespaces, *r.dk) + if err != nil { + log.Error(err, "failed to clean-up bootstrapper code module injection init-secrets") + } + + err = initgeneration.NewInitGenerator(r.client, r.apiReader, r.dk.Namespace).Cleanup(ctx, namespaces) + if err != nil { + log.Error(err, "failed to clean-up code module injection init-secrets") } } } diff --git a/pkg/controllers/dynakube/injection/reconciler_test.go b/pkg/controllers/dynakube/injection/reconciler_test.go index 7a2c3ebfde..3bebb69cbe 100644 --- a/pkg/controllers/dynakube/injection/reconciler_test.go +++ b/pkg/controllers/dynakube/injection/reconciler_test.go @@ -14,6 +14,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/istio" versions "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/version" + "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/bootstrapperconfig" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" "github.com/Dynatrace/dynatrace-operator/pkg/injection/startup" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" @@ -444,6 +445,178 @@ func TestSetupEnrichmentInjection(t *testing.T) { }) } +func TestGenerateCorrectInitSecret(t *testing.T) { + ctx := context.Background() + dkBase := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-dynakube", + Namespace: "my-dynatrace", + }, + Spec: dynakube.DynaKubeSpec{}, + } + + namespaces := []*corev1.Namespace{ + clientInjectedNamespace("ns-1", dkBase.Name), + clientInjectedNamespace("ns-2", dkBase.Name), + } + + tokenSecret := clientSecret(dkBase.Name, dkBase.Namespace, map[string][]byte{ + dtclient.ApiToken: []byte("testAPIToken"), + dtclient.PaasToken: []byte("testPaasToken"), + }) + + tenantSecret := clientSecret(dkBase.OneAgent().GetTenantSecret(), dkBase.Namespace, map[string][]byte{ + "tenant-token": []byte("token"), + }) + + t.Run("default 1 == no node-image-pull + csi enabled => only init-secret", func(t *testing.T) { + dk := dkBase.DeepCopy() + + clt := fake.NewClientWithIndex( + tokenSecret, + dk, + namespaces[0], namespaces[1], + ) + r := reconciler{client: clt, apiReader: clt, dk: dk} + + err := r.generateCorrectInitSecret(ctx) + require.NoError(t, err) + + for _, ns := range namespaces { + assertSecretFound(t, clt, consts.AgentInitSecretName, ns.Name) + assertSecretNotFound(t, clt, consts.BootstrapperInitSecretName, ns.Name) + } + + assertSecretNotFound(t, clt, bootstrapperconfig.GetSourceSecretName(dk.Name), dk.Namespace) + }) + + t.Run("default 2 == no node-image-pull + no csi enabled => only init-secret", func(t *testing.T) { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + + dk := dkBase.DeepCopy() + + clt := fake.NewClientWithIndex( + tokenSecret, + dk, + namespaces[0], namespaces[1], + ) + r := reconciler{client: clt, apiReader: clt, dk: dk} + + err := r.generateCorrectInitSecret(ctx) + require.NoError(t, err) + + for _, ns := range namespaces { + assertSecretFound(t, clt, consts.AgentInitSecretName, ns.Name) + assertSecretNotFound(t, clt, consts.BootstrapperInitSecretName, ns.Name) + } + + assertSecretNotFound(t, clt, bootstrapperconfig.GetSourceSecretName(dk.Name), dk.Namespace) + }) + + t.Run("node-image-pull + csi enabled => both init-secret and bootstrapper-secret", func(t *testing.T) { + dk := dkBase.DeepCopy() + dk.Annotations = map[string]string{ + dynakube.AnnotationFeatureNodeImagePull: "true", + } + + clt := fake.NewClientWithIndex( + tokenSecret, + tenantSecret, + dk, + namespaces[0], namespaces[1], + ) + + dtClient := dtclientmock.NewClient(t) + dtClient.On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("uint")).Return(&dtclient.ProcessModuleConfig{}, nil) + + r := reconciler{client: clt, apiReader: clt, dk: dk, dynatraceClient: dtClient} + + err := r.generateCorrectInitSecret(ctx) + require.NoError(t, err) + + for _, ns := range namespaces { + assertSecretFound(t, clt, consts.AgentInitSecretName, ns.Name) + assertSecretFound(t, clt, consts.BootstrapperInitSecretName, ns.Name) + } + + assertSecretFound(t, clt, bootstrapperconfig.GetSourceSecretName(dk.Name), dk.Namespace) + }) + + t.Run("node-image-pull + csi not enabled => only bootstrapper-secret", func(t *testing.T) { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + + dk := dkBase.DeepCopy() + dk.Annotations = map[string]string{ + dynakube.AnnotationFeatureNodeImagePull: "true", + } + + clt := fake.NewClientWithIndex( + tokenSecret, + tenantSecret, + dk, + namespaces[0], namespaces[1], + ) + + dtClient := dtclientmock.NewClient(t) + dtClient.On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("uint")).Return(&dtclient.ProcessModuleConfig{}, nil) + + r := reconciler{client: clt, apiReader: clt, dk: dk, dynatraceClient: dtClient} + + err := r.generateCorrectInitSecret(ctx) + require.NoError(t, err) + + for _, ns := range namespaces { + assertSecretNotFound(t, clt, consts.AgentInitSecretName, ns.Name) + assertSecretFound(t, clt, consts.BootstrapperInitSecretName, ns.Name) + } + + assertSecretFound(t, clt, bootstrapperconfig.GetSourceSecretName(dk.Name), dk.Namespace) + }) +} + +func TestCleanupOneAgentInjection(t *testing.T) { + ctx := context.Background() + dkBase := &dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-dynakube", + Namespace: "my-dynatrace", + }, + Spec: dynakube.DynaKubeSpec{}, + } + + t.Run("remove everything", func(t *testing.T) { + dk := dkBase.DeepCopy() + namespaces := []*corev1.Namespace{ + clientInjectedNamespace("ns-1", dk.Name), + clientInjectedNamespace("ns-2", dk.Name), + } + + setCodeModulesInjectionCreatedCondition(dk.Conditions()) + + clt := fake.NewClientWithIndex( + clientSecret(consts.AgentInitSecretName, namespaces[0].Name, nil), + clientSecret(consts.AgentInitSecretName, namespaces[1].Name, nil), + clientSecret(consts.BootstrapperInitSecretName, namespaces[0].Name, nil), + clientSecret(consts.BootstrapperInitSecretName, namespaces[1].Name, nil), + clientSecret(bootstrapperconfig.GetSourceSecretName(dk.Name), dk.Namespace, nil), + dk, + namespaces[0], namespaces[1], + ) + r := reconciler{client: clt, apiReader: clt, dk: dk} + + r.cleanupOneAgentInjection(ctx) + + for _, ns := range namespaces { + assertSecretNotFound(t, clt, consts.AgentInitSecretName, ns.Name) + assertSecretNotFound(t, clt, consts.BootstrapperInitSecretName, ns.Name) + } + + assertSecretNotFound(t, clt, bootstrapperconfig.GetSourceSecretName(dk.Name), dk.Namespace) + + assert.Empty(t, dk.Conditions()) + }) +} + func newIstioTestingClient(fakeClient *fakeistio.Clientset, dk *dynakube.DynaKube) *istio.Client { return &istio.Client{ IstioClientset: fakeClient, diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go index 99be3d6924..34c33d226e 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go @@ -49,7 +49,11 @@ func NewReconciler(clt client.Client, } func (r *Reconciler) Reconcile(ctx context.Context) error { - if !(r.dk.OneAgent().IsCloudNativeFullstackMode() || r.dk.OneAgent().IsApplicationMonitoringMode()) { + isNeeded := r.dk.OneAgent().IsCSIAvailable() && + (r.dk.OneAgent().IsCloudNativeFullstackMode() || + r.dk.OneAgent().IsApplicationMonitoringMode()) + + if !(isNeeded) { if meta.FindStatusCondition(*r.dk.Conditions(), PMCConditionType) == nil { return nil } diff --git a/pkg/injection/namespace/bootstrapperconfig/replicate.go b/pkg/injection/namespace/bootstrapperconfig/replicate.go index f0692ba2ec..85f2ffa938 100644 --- a/pkg/injection/namespace/bootstrapperconfig/replicate.go +++ b/pkg/injection/namespace/bootstrapperconfig/replicate.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/consts" k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -20,18 +21,23 @@ func GetSourceSecretName(dkName string) string { return fmt.Sprintf(sourceSecretTemplate, dkName) } +// Replicate will only create the secret once, doesn't meant for keeping the secret up to date func Replicate(ctx context.Context, dk dynakube.DynaKube, query k8ssecret.QueryObject, targetNs string) error { - source, err := query.Get(ctx, types.NamespacedName{Name: GetSourceSecretName(dk.Name), Namespace: dk.Namespace}) + secret, err := getSecretFromSource(ctx, dk, query, targetNs) if err != nil { return err } - secret, err := k8ssecret.BuildForNamespace(consts.BootstrapperInitSecretName, targetNs, source.Data, k8ssecret.SetLabels(source.Labels)) + return client.IgnoreAlreadyExists(query.Create(ctx, secret)) +} + +func getSecretFromSource(ctx context.Context, dk dynakube.DynaKube, query k8ssecret.QueryObject, targetNs string) (*corev1.Secret, error) { + source, err := query.Get(ctx, types.NamespacedName{Name: GetSourceSecretName(dk.Name), Namespace: dk.Namespace}) if err != nil { - return err + return nil, err } - return client.IgnoreAlreadyExists(query.Create(ctx, secret)) + return k8ssecret.BuildForNamespace(consts.BootstrapperInitSecretName, targetNs, source.Data, k8ssecret.SetLabels(source.Labels)) } func (s *SecretGenerator) createSourceForWebhook(ctx context.Context, dk *dynakube.DynaKube, data map[string][]byte) error { diff --git a/pkg/webhook/mutation/pod/common/oneagent/config.go b/pkg/webhook/mutation/pod/common/oneagent/config.go index 350e30102a..037715fd69 100644 --- a/pkg/webhook/mutation/pod/common/oneagent/config.go +++ b/pkg/webhook/mutation/pod/common/oneagent/config.go @@ -15,7 +15,9 @@ const ( // AnnotationInstallPath can be set on a Pod to configure on which directory the OneAgent will be available from, // defaults to DefaultInstallPath if not set. - AnnotationInstallPath = "oneagent.dynatrace.com/install-path" + AnnotationInstallPath = AnnotationPrefix + ".dynatrace.com/install-path" + + AnnotationVolumeType = AnnotationPrefix + ".dynatrace.com/volume-type" // DefaultInstallPath is the default directory to install the app-only OneAgent package. DefaultInstallPath = "/opt/dynatrace/oneagent-paas" diff --git a/pkg/webhook/mutation/pod/common/oneagent/mutator.go b/pkg/webhook/mutation/pod/common/oneagent/mutator.go index 5eb8c9166c..0665cbdd17 100644 --- a/pkg/webhook/mutation/pod/common/oneagent/mutator.go +++ b/pkg/webhook/mutation/pod/common/oneagent/mutator.go @@ -8,6 +8,11 @@ import ( "k8s.io/apimachinery/pkg/labels" ) +const ( + CSIVolumeType = "csi" + EphemeralVolumeType = "ephemeral" +) + func IsEnabled(request *dtwebhook.BaseRequest) bool { enabledOnPod := maputils.GetFieldBool(request.Pod.Annotations, AnnotationInject, request.DynaKube.FeatureAutomaticInjection()) enabledOnDynakube := request.DynaKube.OneAgent().GetNamespaceSelector() != nil diff --git a/pkg/webhook/mutation/pod/v2/webhook.go b/pkg/webhook/mutation/pod/v2/webhook.go index 801c23406b..f9698687dd 100644 --- a/pkg/webhook/mutation/pod/v2/webhook.go +++ b/pkg/webhook/mutation/pod/v2/webhook.go @@ -7,6 +7,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/bootstrapperconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" @@ -23,6 +24,20 @@ type Injector struct { metaClient client.Client } +func IsEnabled(mutationRequest *dtwebhook.MutationRequest) bool { + ffEnabled := mutationRequest.DynaKube.FeatureNodeImagePull() + oaEnabled := oacommon.IsEnabled(mutationRequest.BaseRequest) + + defaultVolumeType := oacommon.EphemeralVolumeType + if mutationRequest.DynaKube.OneAgent().IsCSIAvailable() { + defaultVolumeType = oacommon.CSIVolumeType + } + + correctVolumeType := maputils.GetField(mutationRequest.Pod.Annotations, oacommon.AnnotationVolumeType, defaultVolumeType) == oacommon.EphemeralVolumeType + + return ffEnabled && oaEnabled && correctVolumeType +} + var _ dtwebhook.PodInjector = &Injector{} func NewInjector(kubeClient client.Client, apiReader client.Reader, metaClient client.Client, recorder events.EventRecorder) *Injector { @@ -135,22 +150,14 @@ func isCustomImageSet(mutationRequest *dtwebhook.MutationRequest) bool { } func (wh *Injector) isInputSecretPresent(mutationRequest *dtwebhook.MutationRequest) bool { - var initSecret corev1.Secret - - secretObjectKey := client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: mutationRequest.Namespace.Name} - err := wh.apiReader.Get(mutationRequest.Context, secretObjectKey, &initSecret) + err := wh.replicateInputSecret(mutationRequest) if k8serrors.IsNotFound(err) { - log.Info("dynatrace-bootstrapper-config is not available, trying to replicate", "pod", mutationRequest.PodName()) + log.Info("unable to copy source of dynatrace-bootstrapper-config as it is not available, injection not possible", "pod", mutationRequest.PodName()) - err = bootstrapperconfig.Replicate(mutationRequest.Context, mutationRequest.DynaKube, secret.Query(wh.kubeClient, wh.apiReader, log), mutationRequest.Namespace.Name) - if k8serrors.IsNotFound(err) { - log.Info("dynatrace-bootstrapper-config is not available, injection not possible", "pod", mutationRequest.PodName()) - - oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoBootstrapperConfigReason) + oacommon.SetNotInjectedAnnotations(mutationRequest.Pod, NoBootstrapperConfigReason) - return false - } + return false } if err != nil { @@ -164,6 +171,21 @@ func (wh *Injector) isInputSecretPresent(mutationRequest *dtwebhook.MutationRequ return true } +func (wh *Injector) replicateInputSecret(mutationRequest *dtwebhook.MutationRequest) error { + var initSecret corev1.Secret + + secretObjectKey := client.ObjectKey{Name: consts.BootstrapperInitSecretName, Namespace: mutationRequest.Namespace.Name} + err := wh.apiReader.Get(mutationRequest.Context, secretObjectKey, &initSecret) + + if k8serrors.IsNotFound(err) { + log.Info("dynatrace-bootstrapper-config is not available, trying to replicate", "pod", mutationRequest.PodName()) + + return bootstrapperconfig.Replicate(mutationRequest.Context, mutationRequest.DynaKube, secret.Query(wh.kubeClient, wh.apiReader, log), mutationRequest.Namespace.Name) + } + + return nil +} + func setDynatraceInjectedAnnotation(mutationRequest *dtwebhook.MutationRequest) { if mutationRequest.Pod.Annotations == nil { mutationRequest.Pod.Annotations = make(map[string]string) diff --git a/pkg/webhook/mutation/pod/v2/webhook_test.go b/pkg/webhook/mutation/pod/v2/webhook_test.go index 684f6906e7..963c89db80 100644 --- a/pkg/webhook/mutation/pod/v2/webhook_test.go +++ b/pkg/webhook/mutation/pod/v2/webhook_test.go @@ -9,6 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/bootstrapperconfig" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/container" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" @@ -30,6 +31,88 @@ const ( customImage = "custom-image" ) +func TestIsEnabled(t *testing.T) { + type testCase struct { + title string + podMods func(*corev1.Pod) + dkMods func(*dynakube.DynaKube) + withCSI bool + withoutCSI bool + } + + cases := []testCase{ + { + title: "nothing enabled => not enabled", + podMods: func(p *corev1.Pod) {}, + dkMods: func(dk *dynakube.DynaKube) {}, + withCSI: false, + withoutCSI: false, + }, + + { + title: "only OA enabled, without FF => not enabled", + podMods: func(p *corev1.Pod) {}, + dkMods: func(dk *dynakube.DynaKube) { + dk.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} + }, + withCSI: false, + withoutCSI: false, + }, + + { + title: "OA + FF enabled => enabled with no csi", + podMods: func(p *corev1.Pod) {}, + dkMods: func(dk *dynakube.DynaKube) { + dk.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} + dk.Annotations = map[string]string{dynakube.AnnotationFeatureNodeImagePull: "true"} + }, + withCSI: false, + withoutCSI: true, + }, + { + title: "OA + FF enabled + correct Volume-Type => enabled", + podMods: func(p *corev1.Pod) { + p.Annotations = map[string]string{oacommon.AnnotationVolumeType: oacommon.EphemeralVolumeType} + }, + dkMods: func(dk *dynakube.DynaKube) { + dk.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} + dk.Annotations = map[string]string{dynakube.AnnotationFeatureNodeImagePull: "true"} + }, + withCSI: true, + withoutCSI: true, + }, + { + title: "OA + FF enabled + incorrect Volume-Type => disabled", + podMods: func(p *corev1.Pod) { + p.Annotations = map[string]string{oacommon.AnnotationVolumeType: oacommon.CSIVolumeType} + }, + dkMods: func(dk *dynakube.DynaKube) { + dk.Spec.OneAgent.ApplicationMonitoring = &oneagent.ApplicationMonitoringSpec{} + dk.Annotations = map[string]string{dynakube.AnnotationFeatureNodeImagePull: "true"} + }, + withCSI: false, + withoutCSI: false, + }, + } + for _, test := range cases { + t.Run(test.title, func(t *testing.T) { + pod := &corev1.Pod{} + test.podMods(pod) + + dk := &dynakube.DynaKube{} + test.dkMods(dk) + + req := &dtwebhook.MutationRequest{BaseRequest: &dtwebhook.BaseRequest{Pod: pod, DynaKube: *dk}} + + assert.Equal(t, test.withCSI, IsEnabled(req)) + + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + + assert.Equal(t, test.withoutCSI, IsEnabled(req)) + }) + } +} + func TestHandle(t *testing.T) { ctx := context.Background() diff --git a/pkg/webhook/mutation/pod/webhook.go b/pkg/webhook/mutation/pod/webhook.go index e09fe6f7c4..05e8d40a65 100644 --- a/pkg/webhook/mutation/pod/webhook.go +++ b/pkg/webhook/mutation/pod/webhook.go @@ -11,7 +11,7 @@ import ( maputils "github.com/Dynatrace/dynatrace-operator/pkg/util/map" dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook" "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/events" - oacommon "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/common/oneagent" + podv2 "github.com/Dynatrace/dynatrace-operator/pkg/webhook/mutation/pod/v2" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -76,7 +76,7 @@ func (wh *webhook) Handle(ctx context.Context, request admission.Request) admiss wh.recorder.Setup(mutationRequest) - if mutationRequest.DynaKube.FeatureBootstrapperInjection() && oacommon.IsEnabled(mutationRequest.BaseRequest) { + if podv2.IsEnabled(mutationRequest) { err := wh.v2.Handle(ctx, mutationRequest) if err != nil { return silentErrorResponse(mutationRequest.Pod, err) From 00278d4468521b7836b4d3d991134589e87075a8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 14:32:01 +0000 Subject: [PATCH 360/426] fix(deps): update module github.com/docker/cli to v28.0.3+incompatible (main) (#4659) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 038b12e45f..613e4137dc 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.4 require ( github.com/Dynatrace/dynatrace-bootstrapper v1.0.2 github.com/container-storage-interface/spec v1.11.0 - github.com/docker/cli v28.0.2+incompatible + github.com/docker/cli v28.0.3+incompatible github.com/evanphx/json-patch v5.9.11+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.3 diff --git a/go.sum b/go.sum index 56292fade8..166247f196 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v28.0.2+incompatible h1:cRPZ77FK3/IXTAIQQj1vmhlxiLS5m+MIUDwS6f57lrE= -github.com/docker/cli v28.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v28.0.3+incompatible h1:z2HRZJHFWm71FhKiXnwqBT80xC45gD/ePmKUPbpvRjg= +github.com/docker/cli v28.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= From 3ad29c16c58e61721e96a30825596955a26ed766 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 23:15:19 +0000 Subject: [PATCH 361/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1742918310 (main) (#4660) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b4c77659fe..47e71f8812 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1741861735@sha256:8a6071b01366611fd9433bf9688f5c3150de819874fa2c06c4fcd4c25ea26f03 AS base -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1741850090@sha256:8d53b60617e53e4dbd6c0d485c569801f48dbeb40b48c8424a67e33a07320968 AS dependency +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1742918310@sha256:a1804302f6f53e04cc1c6b20bc2204d5c9ae6e5a664174b38fbeeb30f7983d4e AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 282576008ba9a4b26436c7b358f9a48f8cb7cbe8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 01:40:18 +0000 Subject: [PATCH 362/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1742939100 (main) (#4662) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 47e71f8812..ddae2c5b9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1741861735@sha256:8a6071b01366611fd9433bf9688f5c3150de819874fa2c06c4fcd4c25ea26f03 AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1742939100@sha256:414cfa255ea10eaef4528a26d5618eb67cf487b635ee20f8f14b9317bfd6a4be AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1742918310@sha256:a1804302f6f53e04cc1c6b20bc2204d5c9ae6e5a664174b38fbeeb30f7983d4e AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From dfe2546b0c5829b9d6a076e76282a3ea3c154702 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 06:20:20 +0000 Subject: [PATCH 363/426] fix(deps): update module github.com/docker/cli to v28.0.4+incompatible (main) (#4661) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 613e4137dc..cb65b7cad3 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.4 require ( github.com/Dynatrace/dynatrace-bootstrapper v1.0.2 github.com/container-storage-interface/spec v1.11.0 - github.com/docker/cli v28.0.3+incompatible + github.com/docker/cli v28.0.4+incompatible github.com/evanphx/json-patch v5.9.11+incompatible github.com/go-logr/logr v1.4.2 github.com/google/go-containerregistry v0.20.3 diff --git a/go.sum b/go.sum index 166247f196..4574d00c86 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v28.0.3+incompatible h1:z2HRZJHFWm71FhKiXnwqBT80xC45gD/ePmKUPbpvRjg= -github.com/docker/cli v28.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v28.0.4+incompatible h1:pBJSJeNd9QeIWPjRcV91RVJihd/TXB77q1ef64XEu4A= +github.com/docker/cli v28.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= From 68bf83e9dc396574ddf5e09e4e8a98c34e7fb098 Mon Sep 17 00:00:00 2001 From: Christoph Muellner <33160506+chrismuellner@users.noreply.github.com> Date: Wed, 26 Mar 2025 09:21:26 +0100 Subject: [PATCH 364/426] Update log monitoring sample requirements (#4640) --- assets/samples/dynakube/v1beta4/logMonitoring.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assets/samples/dynakube/v1beta4/logMonitoring.yaml b/assets/samples/dynakube/v1beta4/logMonitoring.yaml index e996673ab4..b849b23c78 100644 --- a/assets/samples/dynakube/v1beta4/logMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/logMonitoring.yaml @@ -3,6 +3,8 @@ kind: DynaKube metadata: name: dynakube namespace: dynatrace +# annotations: +# feature.dynatrace.com/oneagent-privileged: "true" # Required on Openshift spec: # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters From 9a147a85941a1235951a1ccdade366bb4444a8f6 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Wed, 26 Mar 2025 11:05:36 +0100 Subject: [PATCH 365/426] Cleanup /cmd (#4654) --- cmd/config/config.go | 24 -- cmd/config/config_test.go | 13 - cmd/csi/init/cmd.go | 4 +- cmd/csi/provisioner/cmd.go | 4 +- cmd/csi/server/cmd.go | 4 +- cmd/main.go | 44 +-- cmd/manager/manager.go | 10 - cmd/manager/test.go | 55 ---- cmd/operator/builder.go | 213 --------------- cmd/operator/builder_test.go | 257 ------------------ cmd/operator/certs.go | 59 ++++ cmd/operator/cmd.go | 100 +++++++ cmd/operator/config.go | 18 ++ cmd/operator/manager.go | 104 +------ cmd/operator/manager_test.go | 120 -------- cmd/standalone/{standalone.go => cmd.go} | 4 +- .../{standalone_test.go => cmd_test.go} | 0 cmd/startup_probe/{builder.go => cmd.go} | 13 +- cmd/support_archive/{builder.go => cmd.go} | 38 +-- .../{builder_test.go => cmd_test.go} | 0 cmd/support_archive/eec_fs_logs.go | 2 +- .../remote_command/command.go | 0 cmd/troubleshoot/builder_test.go | 52 ---- cmd/troubleshoot/{builder.go => cmd.go} | 24 +- cmd/webhook/builder_test.go | 41 --- cmd/{ => webhook}/certificates/config.go | 0 cmd/{ => webhook}/certificates/watcher.go | 0 cmd/webhook/{builder.go => cmd.go} | 149 ++++------ cmd/webhook/manager.go | 30 +- cmd/webhook/manager_test.go | 73 ----- codecov.yml | 16 +- hack/make/go.mk | 2 +- .../certificates/webhook_cert_controller.go | 2 +- test/helpers/platform/platform.go | 5 +- {cmd => test}/integration/integration_test.go | 0 35 files changed, 297 insertions(+), 1183 deletions(-) delete mode 100644 cmd/config/config.go delete mode 100644 cmd/config/config_test.go delete mode 100644 cmd/manager/manager.go delete mode 100644 cmd/manager/test.go delete mode 100644 cmd/operator/builder.go delete mode 100644 cmd/operator/builder_test.go create mode 100644 cmd/operator/certs.go create mode 100644 cmd/operator/cmd.go delete mode 100644 cmd/operator/manager_test.go rename cmd/standalone/{standalone.go => cmd.go} (84%) rename cmd/standalone/{standalone_test.go => cmd_test.go} (100%) rename cmd/startup_probe/{builder.go => cmd.go} (81%) rename cmd/support_archive/{builder.go => cmd.go} (89%) rename cmd/support_archive/{builder_test.go => cmd_test.go} (100%) rename cmd/{ => support_archive}/remote_command/command.go (100%) delete mode 100644 cmd/troubleshoot/builder_test.go rename cmd/troubleshoot/{builder.go => cmd.go} (90%) delete mode 100644 cmd/webhook/builder_test.go rename cmd/{ => webhook}/certificates/config.go (100%) rename cmd/{ => webhook}/certificates/watcher.go (100%) rename cmd/webhook/{builder.go => cmd.go} (72%) delete mode 100644 cmd/webhook/manager_test.go rename {cmd => test}/integration/integration_test.go (100%) diff --git a/cmd/config/config.go b/cmd/config/config.go deleted file mode 100644 index 14ca776ddb..0000000000 --- a/cmd/config/config.go +++ /dev/null @@ -1,24 +0,0 @@ -package config - -import ( - "github.com/pkg/errors" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client/config" -) - -type Provider interface { - GetConfig() (*rest.Config, error) -} - -type KubeConfigProvider struct { -} - -func NewKubeConfigProvider() Provider { - return KubeConfigProvider{} -} - -func (provider KubeConfigProvider) GetConfig() (*rest.Config, error) { - cfg, err := config.GetConfig() - - return cfg, errors.WithStack(err) -} diff --git a/cmd/config/config_test.go b/cmd/config/config_test.go deleted file mode 100644 index 643cf72f50..0000000000 --- a/cmd/config/config_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package config - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestConfigProvider(t *testing.T) { - provider := NewKubeConfigProvider() - - assert.NotNil(t, provider) -} diff --git a/cmd/csi/init/cmd.go b/cmd/csi/init/cmd.go index 9efde049ed..1e10fbb673 100644 --- a/cmd/csi/init/cmd.go +++ b/cmd/csi/init/cmd.go @@ -3,7 +3,6 @@ package init import ( "os" - "github.com/Dynatrace/dynatrace-operator/cmd/config" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/metadata" @@ -17,6 +16,7 @@ import ( "golang.org/x/sys/unix" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" ) @@ -63,7 +63,7 @@ func run() func(*cobra.Command, []string) error { Scheme: scheme.Scheme, } - kubeconfig, err := config.NewKubeConfigProvider().GetConfig() + kubeconfig, err := config.GetConfig() if err != nil { return errors.WithStack(err) } diff --git a/cmd/csi/provisioner/cmd.go b/cmd/csi/provisioner/cmd.go index adb27fe796..5fcf2c01b3 100644 --- a/cmd/csi/provisioner/cmd.go +++ b/cmd/csi/provisioner/cmd.go @@ -3,7 +3,6 @@ package provisioner import ( "os" - "github.com/Dynatrace/dynatrace-operator/cmd/config" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csiprovisioner "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/provisioner" @@ -18,6 +17,7 @@ import ( "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/metrics/server" @@ -57,7 +57,7 @@ func run() func(*cobra.Command, []string) error { version.LogVersion() logd.LogBaseLoggerSettings() - kubeConfig, err := config.NewKubeConfigProvider().GetConfig() + kubeConfig, err := config.GetConfig() if err != nil { return err } diff --git a/cmd/csi/server/cmd.go b/cmd/csi/server/cmd.go index ff780ea364..5222c6ce52 100644 --- a/cmd/csi/server/cmd.go +++ b/cmd/csi/server/cmd.go @@ -3,7 +3,6 @@ package server import ( "os" - "github.com/Dynatrace/dynatrace-operator/cmd/config" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" dtcsi "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi" csidriver "github.com/Dynatrace/dynatrace-operator/pkg/controllers/csi/driver" @@ -18,6 +17,7 @@ import ( "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/metrics/server" ) @@ -54,7 +54,7 @@ func run() func(*cobra.Command, []string) error { version.LogVersion() logd.LogBaseLoggerSettings() - kubeConfig, err := config.NewKubeConfigProvider().GetConfig() + kubeConfig, err := config.GetConfig() if err != nil { return err } diff --git a/cmd/main.go b/cmd/main.go index 08aaaa3010..7bd4e7f767 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -17,18 +17,16 @@ package main import ( "os" - cmdConfig "github.com/Dynatrace/dynatrace-operator/cmd/config" csiInit "github.com/Dynatrace/dynatrace-operator/cmd/csi/init" csiProvisioner "github.com/Dynatrace/dynatrace-operator/cmd/csi/provisioner" csiServer "github.com/Dynatrace/dynatrace-operator/cmd/csi/server" "github.com/Dynatrace/dynatrace-operator/cmd/operator" "github.com/Dynatrace/dynatrace-operator/cmd/standalone" - "github.com/Dynatrace/dynatrace-operator/cmd/startup_probe" - "github.com/Dynatrace/dynatrace-operator/cmd/support_archive" + startupProbe "github.com/Dynatrace/dynatrace-operator/cmd/startup_probe" + supportArchive "github.com/Dynatrace/dynatrace-operator/cmd/support_archive" "github.com/Dynatrace/dynatrace-operator/cmd/troubleshoot" "github.com/Dynatrace/dynatrace-operator/cmd/webhook" "github.com/Dynatrace/dynatrace-operator/pkg/logd" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/pkg/errors" "github.com/spf13/cobra" ctrl "sigs.k8s.io/controller-runtime" @@ -47,34 +45,6 @@ func newRootCommand() *cobra.Command { return cmd } -func createWebhookCommandBuilder() webhook.CommandBuilder { - return webhook.NewWebhookCommandBuilder(). - SetNamespace(os.Getenv(env.PodNamespace)). - SetPodName(os.Getenv(env.PodName)). - SetConfigProvider(cmdConfig.NewKubeConfigProvider()) -} - -func createOperatorCommandBuilder() operator.CommandBuilder { - return operator.NewOperatorCommandBuilder(). - SetNamespace(os.Getenv(env.PodNamespace)). - SetPodName(os.Getenv(env.PodName)). - SetConfigProvider(cmdConfig.NewKubeConfigProvider()) -} - -func createTroubleshootCommandBuilder() troubleshoot.CommandBuilder { - return troubleshoot.NewTroubleshootCommandBuilder(). - SetConfigProvider(cmdConfig.NewKubeConfigProvider()) -} - -func createSupportArchiveCommandBuilder() support_archive.CommandBuilder { - return support_archive.NewCommandBuilder(). - SetConfigProvider(cmdConfig.NewKubeConfigProvider()) -} - -func createStartupProbe() startup_probe.CommandBuilder { - return startup_probe.NewCommandBuilder() -} - func rootCommand(_ *cobra.Command, _ []string) error { return errors.New("operator binary must be called with one of the subcommands") } @@ -85,12 +55,12 @@ func main() { cmd := newRootCommand() cmd.AddCommand( - createWebhookCommandBuilder().Build(), - createOperatorCommandBuilder().Build(), + webhook.New(), + operator.New(), standalone.NewStandaloneCommand(), - createTroubleshootCommandBuilder().Build(), - createSupportArchiveCommandBuilder().Build(), - createStartupProbe().Build(), + troubleshoot.New(), + supportArchive.New(), + startupProbe.New(), csiInit.New(), csiProvisioner.New(), csiServer.New(), diff --git a/cmd/manager/manager.go b/cmd/manager/manager.go deleted file mode 100644 index 381ffefdaf..0000000000 --- a/cmd/manager/manager.go +++ /dev/null @@ -1,10 +0,0 @@ -package manager - -import ( - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/manager" -) - -type Provider interface { - CreateManager(namespace string, config *rest.Config) (manager.Manager, error) -} diff --git a/cmd/manager/test.go b/cmd/manager/test.go deleted file mode 100644 index b9874cef25..0000000000 --- a/cmd/manager/test.go +++ /dev/null @@ -1,55 +0,0 @@ -package manager - -import ( - "context" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/Dynatrace/dynatrace-operator/pkg/logd" - "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/controller-runtime/pkg/cache" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/config" - "sigs.k8s.io/controller-runtime/pkg/manager" -) - -type TestManager struct { - manager.Manager -} - -func (mgr *TestManager) GetClient() client.Client { - return struct{ client.Client }{} -} - -func (mgr *TestManager) GetAPIReader() client.Reader { - return nil -} - -func (mgr *TestManager) GetControllerOptions() config.Controller { - return config.Controller{} -} - -func (mgr *TestManager) GetScheme() *runtime.Scheme { - return scheme.Scheme -} - -func (mgr *TestManager) GetCache() cache.Cache { - return nil -} - -func (mgr *TestManager) GetLogger() logr.Logger { - return logd.Get().WithName("test-manager").Logger -} - -func (mgr *TestManager) GetRESTMapper() meta.RESTMapper { - return nil -} - -func (mgr *TestManager) Add(manager.Runnable) error { - return nil -} - -func (mgr *TestManager) Start(_ context.Context) error { - return nil -} diff --git a/cmd/operator/builder.go b/cmd/operator/builder.go deleted file mode 100644 index fc15a432c6..0000000000 --- a/cmd/operator/builder.go +++ /dev/null @@ -1,213 +0,0 @@ -package operator - -import ( - "context" - - "github.com/Dynatrace/dynatrace-operator/cmd/config" - cmdManager "github.com/Dynatrace/dynatrace-operator/cmd/manager" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/certificates" - "github.com/Dynatrace/dynatrace-operator/pkg/logd" - "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/pod" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubesystem" - "github.com/Dynatrace/dynatrace-operator/pkg/version" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -const ( - use = "operator" -) - -type CommandBuilder struct { - configProvider config.Provider - bootstrapManagerProvider cmdManager.Provider - operatorManagerProvider cmdManager.Provider - signalHandler context.Context - client client.Client - namespace string - podName string -} - -func NewOperatorCommandBuilder() CommandBuilder { - return CommandBuilder{} -} - -func (builder CommandBuilder) SetConfigProvider(provider config.Provider) CommandBuilder { - builder.configProvider = provider - - return builder -} - -func (builder CommandBuilder) setOperatorManagerProvider(provider cmdManager.Provider) CommandBuilder { - builder.operatorManagerProvider = provider - - return builder -} - -func (builder CommandBuilder) setBootstrapManagerProvider(provider cmdManager.Provider) CommandBuilder { - builder.bootstrapManagerProvider = provider - - return builder -} - -func (builder CommandBuilder) SetNamespace(namespace string) CommandBuilder { - builder.namespace = namespace - - return builder -} - -func (builder CommandBuilder) SetPodName(podName string) CommandBuilder { - builder.podName = podName - - return builder -} - -func (builder CommandBuilder) setSignalHandler(ctx context.Context) CommandBuilder { - builder.signalHandler = ctx - - return builder -} - -func (builder CommandBuilder) setClient(client client.Client) CommandBuilder { - builder.client = client - - return builder -} - -func (builder CommandBuilder) getOperatorManagerProvider(isDeployedByOlm bool) cmdManager.Provider { - if builder.operatorManagerProvider == nil { - builder.operatorManagerProvider = NewOperatorManagerProvider(isDeployedByOlm) - } - - return builder.operatorManagerProvider -} - -func (builder CommandBuilder) getBootstrapManagerProvider() cmdManager.Provider { - if builder.bootstrapManagerProvider == nil { - builder.bootstrapManagerProvider = NewBootstrapManagerProvider() - } - - return builder.bootstrapManagerProvider -} - -// TODO: This can't be stateless (so pointer receiver needs to be used), because the ctrl.SetupSignalHandler() can only be called once in a process, otherwise we get a panic. This "builder" pattern has to be refactored. -func (builder *CommandBuilder) getSignalHandler() context.Context { - if builder.signalHandler == nil { - builder.signalHandler = ctrl.SetupSignalHandler() - } - - return builder.signalHandler -} - -func (builder CommandBuilder) Build() *cobra.Command { - return &cobra.Command{ - Use: use, - RunE: builder.buildRun(), - SilenceUsage: true, - } -} - -func (builder CommandBuilder) setClientFromConfig(kubeCfg *rest.Config) (CommandBuilder, error) { - if builder.client == nil { - clt, err := client.New(kubeCfg, client.Options{}) - if err != nil { - return builder, err - } - - return builder.setClient(clt), nil - } - - return builder, nil -} - -func (builder CommandBuilder) buildRun() func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - installconfig.ReadModules() - version.LogVersion() - logd.LogBaseLoggerSettings() - - kubeCfg, err := builder.configProvider.GetConfig() - if err != nil { - return err - } - - builder, err = builder.setClientFromConfig(kubeCfg) - if err != nil { - return err - } - - if kubesystem.IsRunLocally() { - log.Info("running locally in debug mode") - - return builder.runLocally(kubeCfg) - } - - return builder.runInPod(kubeCfg) - } -} - -func (builder CommandBuilder) runInPod(kubeCfg *rest.Config) error { - operatorPod, err := pod.Get(context.TODO(), builder.client, builder.podName, builder.namespace) - if err != nil { - return err - } - - isDeployedViaOlm := kubesystem.IsDeployedViaOlm(*operatorPod) - if !isDeployedViaOlm { - err = builder.runBootstrapper(kubeCfg) - if err != nil { - return err - } - } - - return builder.runOperatorManager(kubeCfg, isDeployedViaOlm) -} - -func (builder CommandBuilder) runLocally(kubeCfg *rest.Config) error { - err := builder.runBootstrapper(kubeCfg) - if err != nil { - return err - } - - return builder.runOperatorManager(kubeCfg, false) -} - -func (builder CommandBuilder) runBootstrapper(kubeCfg *rest.Config) error { - bootstrapManager, err := builder.getBootstrapManagerProvider().CreateManager(builder.namespace, kubeCfg) - if err != nil { - return err - } - - return startBootstrapperManager(bootstrapManager, builder.namespace) -} - -func (builder CommandBuilder) runOperatorManager(kubeCfg *rest.Config, isDeployedViaOlm bool) error { - operatorManager, err := builder.getOperatorManagerProvider(isDeployedViaOlm).CreateManager(builder.namespace, kubeCfg) - if err != nil { - return err - } - - err = operatorManager.Start(builder.getSignalHandler()) - - return errors.WithStack(err) -} - -func startBootstrapperManager(bootstrapManager ctrl.Manager, namespace string) error { - ctx, cancelFn := context.WithCancel(context.Background()) - - err := certificates.AddBootstrap(bootstrapManager, namespace, cancelFn) - if err != nil { - return errors.WithStack(err) - } - - err = bootstrapManager.Start(ctx) - if err != nil { - return errors.WithStack(err) - } - - return nil -} diff --git a/cmd/operator/builder_test.go b/cmd/operator/builder_test.go deleted file mode 100644 index 92f53b2e9f..0000000000 --- a/cmd/operator/builder_test.go +++ /dev/null @@ -1,257 +0,0 @@ -package operator - -import ( - "context" - "testing" - - "github.com/Dynatrace/dynatrace-operator/cmd/manager" - dtfake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - configmock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/config" - providermock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/manager" - managermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/go-logr/logr" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "k8s.io/utils/ptr" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - "sigs.k8s.io/controller-runtime/pkg/config" -) - -const ( - testNamespace = "test-namespace" - testPod = "test-pod-name" -) - -func TestCommandBuilder(t *testing.T) { - t.Run("build command", func(t *testing.T) { - builder := NewOperatorCommandBuilder() - operatorCommand := builder.Build() - - assert.NotNil(t, operatorCommand) - assert.Equal(t, use, operatorCommand.Use) - assert.NotNil(t, operatorCommand.RunE) - }) - t.Run("set config provider", func(t *testing.T) { - builder := NewOperatorCommandBuilder() - - assert.NotNil(t, builder) - - expectedProvider := &configmock.Provider{} - builder = builder.SetConfigProvider(expectedProvider) - - assert.Equal(t, expectedProvider, builder.configProvider) - }) - t.Run("set operator manager provider", func(t *testing.T) { - expectedProvider := providermock.NewProvider(t) - builder := NewOperatorCommandBuilder().setOperatorManagerProvider(expectedProvider) - - assert.Equal(t, expectedProvider, builder.operatorManagerProvider) - }) - t.Run("set bootstrap manager provider", func(t *testing.T) { - expectedProvider := providermock.NewProvider(t) - builder := NewOperatorCommandBuilder().setBootstrapManagerProvider(expectedProvider) - - assert.Equal(t, expectedProvider, builder.bootstrapManagerProvider) - }) - t.Run("set namespace", func(t *testing.T) { - builder := NewOperatorCommandBuilder().SetNamespace("namespace") - - assert.Equal(t, "namespace", builder.namespace) - }) - t.Run("set context", func(t *testing.T) { - // If ctrl.SetupSignalHandler() is used multiple times during a test suit, it will panic - // Therefore it is necessary to set a custom context to unit test properly - ctx := context.TODO() - builder := NewOperatorCommandBuilder().setSignalHandler(ctx) - - assert.Equal(t, ctx, builder.signalHandler) - }) -} - -func TestOperatorCommand(t *testing.T) { - t.Run("operator command exists", func(t *testing.T) { - operatorCommand := NewOperatorCommandBuilder().Build() - - assert.Equal(t, "operator", operatorCommand.Use) - assert.NotNil(t, operatorCommand.RunE) - }) - t.Run("kubernetes config provider is called", func(t *testing.T) { - mockCfgProvider := &configmock.Provider{} - mockCfgProvider.On("GetConfig").Return(&rest.Config{}, nil) - - mockMgrProvider := providermock.NewProvider(t) - - builder := NewOperatorCommandBuilder(). - SetNamespace(testNamespace). - setOperatorManagerProvider(mockMgrProvider). - setBootstrapManagerProvider(mockMgrProvider). - SetConfigProvider(mockCfgProvider) - operatorCommand := builder.Build() - - _ = operatorCommand.RunE(operatorCommand, make([]string, 0)) - - mockCfgProvider.AssertCalled(t, "GetConfig") - }) - t.Run("exit on config provider error", func(t *testing.T) { - mockCfgProvider := &configmock.Provider{} - mockCfgProvider.On("GetConfig").Return(&rest.Config{}, errors.New("config provider error")) - builder := NewOperatorCommandBuilder(). - SetConfigProvider(mockCfgProvider) - operatorCommand := builder.Build() - - err := operatorCommand.RunE(operatorCommand, make([]string, 0)) - - require.EqualError(t, err, "config provider error") - }) - t.Run("create manager if not in OLM", func(t *testing.T) { - mockCfgProvider := &configmock.Provider{} - mockCfgProvider.On("GetConfig").Return(&rest.Config{}, nil) - - mockMgrProvider := providermock.NewProvider(t) - mockMgrProvider. - On("CreateManager", mock.AnythingOfType("string"), &rest.Config{}). - Return(&manager.TestManager{}, nil) - - builder := NewOperatorCommandBuilder(). - SetNamespace(testNamespace). - SetPodName(testPod). - setOperatorManagerProvider(mockMgrProvider). - setBootstrapManagerProvider(mockMgrProvider). - SetConfigProvider(mockCfgProvider). - setSignalHandler(context.TODO()). - setClient(createFakeClient(false)) - operatorCommand := builder.Build() - - err := operatorCommand.RunE(operatorCommand, make([]string, 0)) - - require.NoError(t, err) - }) - t.Run("exit on manager error", func(t *testing.T) { - mockCfgProvider := &configmock.Provider{} - mockCfgProvider.On("GetConfig").Return(&rest.Config{}, nil) - - mockMgrProvider := providermock.NewProvider(t) - mockMgrProvider. - On("CreateManager", mock.AnythingOfType("string"), &rest.Config{}). - Return(&manager.TestManager{}, errors.New("create manager error")) - - builder := NewOperatorCommandBuilder(). - SetNamespace(testNamespace). - SetPodName(testPod). - setBootstrapManagerProvider(mockMgrProvider). - SetConfigProvider(mockCfgProvider). - setClient(createFakeClient(false)) - operatorCommand := builder.Build() - - err := operatorCommand.RunE(operatorCommand, make([]string, 0)) - - require.EqualError(t, err, "create manager error") - }) - t.Run("bootstrap manager is started", func(t *testing.T) { - mockCfgProvider := &configmock.Provider{} - mockCfgProvider.On("GetConfig").Return(&rest.Config{}, nil) - - mockMgr := managermock.NewManager(t) - mockMgr.On("Start", mock.Anything).Return(nil) - - clt := dtfake.NewClient() - - mockMgr.On("GetScheme").Return(scheme.Scheme) - mockMgr.On("GetClient").Return(clt) - mockMgr.On("GetAPIReader").Return(clt) - mockMgr.On("GetControllerOptions").Return(config.Controller{SkipNameValidation: ptr.To(true)}) - mockMgr.On("GetLogger").Return(logr.Logger{}) - mockMgr.On("Add", mock.AnythingOfType("*controller.Controller[sigs.k8s.io/controller-runtime/pkg/reconcile.Request]")).Return(nil) - mockMgr.On("GetCache").Return(nil) - - mockMgrProvider := providermock.NewProvider(t) - mockMgrProvider. - On("CreateManager", mock.AnythingOfType("string"), &rest.Config{}). - Return(mockMgr, nil) - - builder := NewOperatorCommandBuilder(). - SetNamespace(testNamespace). - SetPodName(testPod). - setOperatorManagerProvider(mockMgrProvider). - setBootstrapManagerProvider(mockMgrProvider). - SetConfigProvider(mockCfgProvider). - setSignalHandler(context.TODO()). - setClient(createFakeClient(false)) - operatorCommand := builder.Build() - - err := operatorCommand.RunE(operatorCommand, make([]string, 0)) - - require.NoError(t, err) - mockMgr.AssertCalled(t, "Start", mock.Anything) - }) - t.Run("operator manager is started", func(t *testing.T) { - mockCfgProvider := &configmock.Provider{} - mockCfgProvider.On("GetConfig").Return(&rest.Config{}, nil) - - bootstrapMockMgr := managermock.NewManager(t) - bootstrapMockMgr.On("Start", mock.Anything).Return(nil).Maybe() - - mockBootstrapMgrProvider := providermock.NewProvider(t) - mockBootstrapMgrProvider. - On("CreateManager", mock.AnythingOfType("string"), &rest.Config{}). - Return(bootstrapMockMgr, nil).Maybe() - - operatorMockMgr := managermock.NewManager(t) - operatorMockMgr.On("Start", mock.Anything).Return(nil) - - mockOperatorMgrProvider := providermock.NewProvider(t) - mockOperatorMgrProvider. - On("CreateManager", mock.AnythingOfType("string"), &rest.Config{}). - Return(operatorMockMgr, nil) - - builder := NewOperatorCommandBuilder(). - SetNamespace(testNamespace). - SetPodName(testPod). - setOperatorManagerProvider(mockOperatorMgrProvider). - setBootstrapManagerProvider(mockBootstrapMgrProvider). - SetConfigProvider(mockCfgProvider). - setSignalHandler(context.TODO()). - setClient(createFakeClient(true)) - operatorCommand := builder.Build() - - err := operatorCommand.RunE(operatorCommand, make([]string, 0)) - - require.NoError(t, err) - mockBootstrapMgrProvider.AssertNotCalled(t, "CreateManager", mock.AnythingOfType("string"), &rest.Config{}) - bootstrapMockMgr.AssertNotCalled(t, "Start", mock.Anything) - operatorMockMgr.AssertCalled(t, "Start", mock.Anything) - }) -} - -func createFakeClient(isDeployedViaOlm bool) client.WithWatch { - annotations := map[string]string{} - if isDeployedViaOlm { - annotations = map[string]string{ - "olm.operatorNamespace": "operators", - } - } - - return fake.NewClientBuilder(). - WithScheme(scheme.Scheme). - WithObjects( - &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: testNamespace, - }, - }, - &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: testPod, - Namespace: testNamespace, - Annotations: annotations, - }, - }, - ).Build() -} diff --git a/cmd/operator/certs.go b/cmd/operator/certs.go new file mode 100644 index 0000000000..5488694662 --- /dev/null +++ b/cmd/operator/certs.go @@ -0,0 +1,59 @@ +package operator + +import ( + "context" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/certificates" + "github.com/pkg/errors" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +func runCertInit(cfg *rest.Config, namespace string) error { + certInitManager, err := createCertInitManager(cfg, namespace) + if err != nil { + return err + } + + ctx, cancelFn := context.WithCancel(context.Background()) + + err = certificates.AddInit(certInitManager, namespace, cancelFn) + if err != nil { + return errors.WithStack(err) + } + + err = certInitManager.Start(ctx) + if err != nil { + return errors.WithStack(err) + } + + return nil +} + +func createCertInitManager(cfg *rest.Config, namespace string) (manager.Manager, error) { + controlManager, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: scheme.Scheme, + Cache: cache.Options{ + DefaultNamespaces: map[string]cache.Config{ + namespace: {}, + }, + }, + HealthProbeBindAddress: healthProbeBindAddress, + LivenessEndpointName: livenessEndpointName, + }) + + if err != nil { + return nil, errors.WithStack(err) + } + + err = controlManager.AddHealthzCheck(livezEndpointName, healthz.Ping) + if err != nil { + return nil, errors.WithStack(err) + } + + return controlManager, errors.WithStack(err) +} diff --git a/cmd/operator/cmd.go b/cmd/operator/cmd.go new file mode 100644 index 0000000000..f371252dd6 --- /dev/null +++ b/cmd/operator/cmd.go @@ -0,0 +1,100 @@ +package operator + +import ( + "context" + "os" + + "github.com/Dynatrace/dynatrace-operator/pkg/logd" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/pod" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubesystem" + "github.com/Dynatrace/dynatrace-operator/pkg/version" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" +) + +const ( + use = "operator" +) + +func New() *cobra.Command { + return &cobra.Command{ + Use: use, + RunE: run(), + SilenceUsage: true, + } +} + +func run() func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + installconfig.ReadModules() + version.LogVersion() + logd.LogBaseLoggerSettings() + + kubeCfg, err := config.GetConfig() + if err != nil { + return err + } + + if kubesystem.IsRunLocally() { + log.Info("running locally in debug mode") + + return runLocally(kubeCfg) + } + + return runInPod(kubeCfg) + } +} + +func runInPod(kubeCfg *rest.Config) error { + clt, err := client.New(kubeCfg, client.Options{}) + if err != nil { + return err + } + + podName := os.Getenv(env.PodName) + namespace := os.Getenv(env.PodNamespace) + + operatorPod, err := pod.Get(context.Background(), clt, podName, namespace) + if err != nil { + return err + } + + isOLM := kubesystem.IsDeployedViaOlm(*operatorPod) + if !isOLM { + err = runCertInit(kubeCfg, namespace) + if err != nil { + return err + } + } + + return runOperator(kubeCfg, namespace, isOLM) +} + +func runLocally(kubeCfg *rest.Config) error { + namespace := os.Getenv(env.PodNamespace) + + err := runCertInit(kubeCfg, namespace) + if err != nil { + return err + } + + return runOperator(kubeCfg, namespace, false) +} + +func runOperator(kubeCfg *rest.Config, namespace string, isOLM bool) error { + operatorManager, err := createOperatorManager(kubeCfg, namespace, isOLM) + if err != nil { + return err + } + + ctx := ctrl.SetupSignalHandler() + err = operatorManager.Start(ctx) + + return errors.WithStack(err) +} diff --git a/cmd/operator/config.go b/cmd/operator/config.go index d5714fc1ca..d752aed4b7 100644 --- a/cmd/operator/config.go +++ b/cmd/operator/config.go @@ -4,4 +4,22 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/logd" ) +const ( + metricsBindAddress = ":8080" + healthProbeBindAddress = ":10080" + + leaderElectionId = "dynatrace-operator-lock" + leaderElectionResourceLock = "leases" + leaderElectionEnvVarRenewDeadline = "LEADER_ELECTION_RENEW_DEADLINE" + leaderElectionEnvVarRetryPeriod = "LEADER_ELECTION_RETRY_PERIOD" + leaderElectionEnvVarLeaseDuration = "LEADER_ELECTION_LEASE_DURATION" + + livezEndpointName = "livez" + livenessEndpointName = "/" + livezEndpointName + + defaultLeaseDuration = int64(30) + defaultRenewDeadline = int64(20) + defaultRetryPeriod = int64(6) +) + var log = logd.Get().WithName("operator-command") diff --git a/cmd/operator/manager.go b/cmd/operator/manager.go index fa71a84e63..9da99488ef 100644 --- a/cmd/operator/manager.go +++ b/cmd/operator/manager.go @@ -5,7 +5,6 @@ import ( "strconv" "time" - cmdManager "github.com/Dynatrace/dynatrace-operator/cmd/manager" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/certificates" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube" @@ -21,76 +20,22 @@ import ( "sigs.k8s.io/controller-runtime/pkg/metrics/server" ) -const ( - metricsBindAddress = ":8080" - healthProbeBindAddress = ":10080" - - leaderElectionId = "dynatrace-operator-lock" - leaderElectionResourceLock = "leases" - leaderElectionEnvVarRenewDeadline = "LEADER_ELECTION_RENEW_DEADLINE" - leaderElectionEnvVarRetryPeriod = "LEADER_ELECTION_RETRY_PERIOD" - leaderElectionEnvVarLeaseDuration = "LEADER_ELECTION_LEASE_DURATION" - - livezEndpointName = "livez" - livenessEndpointName = "/" + livezEndpointName - - defaultLeaseDuration = int64(30) - defaultRenewDeadline = int64(20) - defaultRetryPeriod = int64(6) -) - -type bootstrapManagerProvider struct { - managerBuilder -} - -func NewBootstrapManagerProvider() cmdManager.Provider { - return bootstrapManagerProvider{} -} - -func (provider bootstrapManagerProvider) CreateManager(namespace string, config *rest.Config) (manager.Manager, error) { - controlManager, err := provider.getManager(config, ctrl.Options{ - Scheme: scheme.Scheme, - Cache: cache.Options{ - DefaultNamespaces: map[string]cache.Config{ - namespace: {}, - }, - }, - HealthProbeBindAddress: healthProbeBindAddress, - LivenessEndpointName: livenessEndpointName, - }) - - if err != nil { - return nil, errors.WithStack(err) - } - - err = controlManager.AddHealthzCheck(livezEndpointName, healthz.Ping) +func createOperatorManager(cfg *rest.Config, namespace string, isOLM bool) (manager.Manager, error) { + mgr, err := ctrl.NewManager(cfg, createOptions(namespace)) if err != nil { return nil, errors.WithStack(err) } - return controlManager, errors.WithStack(err) -} - -type operatorManagerProvider struct { - managerBuilder - deployedViaOlm bool -} - -func NewOperatorManagerProvider(deployedViaOlm bool) cmdManager.Provider { - return operatorManagerProvider{ - deployedViaOlm: deployedViaOlm, - } -} - -func (provider operatorManagerProvider) CreateManager(namespace string, cfg *rest.Config) (manager.Manager, error) { - mgr, err := provider.getManager(cfg, provider.createOptions(namespace)) + err = mgr.AddHealthzCheck(livezEndpointName, healthz.Ping) if err != nil { return nil, errors.WithStack(err) } - err = mgr.AddHealthzCheck(livezEndpointName, healthz.Ping) - if err != nil { - return nil, errors.WithStack(err) + if isOLM { + err = certificates.Add(mgr, namespace) + if err != nil { + return nil, err + } } err = dynakube.Add(mgr, namespace) @@ -103,11 +48,6 @@ func (provider operatorManagerProvider) CreateManager(namespace string, cfg *res return nil, err } - err = provider.addCertificateController(mgr, namespace) - if err != nil { - return nil, err - } - err = edgeconnect.Add(mgr, namespace) if err != nil { return nil, err @@ -116,15 +56,7 @@ func (provider operatorManagerProvider) CreateManager(namespace string, cfg *res return mgr, nil } -func (provider operatorManagerProvider) addCertificateController(mgr manager.Manager, namespace string) error { - if !provider.deployedViaOlm { - return certificates.Add(mgr, namespace) - } - - return nil -} - -func (provider operatorManagerProvider) createOptions(namespace string) ctrl.Options { +func createOptions(namespace string) ctrl.Options { return ctrl.Options{ Cache: cache.Options{ DefaultNamespaces: map[string]cache.Config{ @@ -147,24 +79,6 @@ func (provider operatorManagerProvider) createOptions(namespace string) ctrl.Opt } } -// managerBuilder is used for testing the createManager functions in the providers. -type managerBuilder struct { - mgr manager.Manager -} - -func (builder *managerBuilder) getManager(config *rest.Config, options manager.Options) (manager.Manager, error) { - var err error - if builder.mgr == nil { - builder.mgr, err = ctrl.NewManager(config, options) - } - - return builder.mgr, err -} - -func (builder *managerBuilder) setManager(mgr manager.Manager) { - builder.mgr = mgr -} - func getTimeFromEnvWithDefault(envName string, defaultValue int64) *time.Duration { duration := time.Duration(defaultValue) * time.Second diff --git a/cmd/operator/manager_test.go b/cmd/operator/manager_test.go deleted file mode 100644 index 3dd726eaa4..0000000000 --- a/cmd/operator/manager_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package operator - -import ( - "errors" - "testing" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - managermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/go-logr/logr" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/rest" - "k8s.io/utils/ptr" - "sigs.k8s.io/controller-runtime/pkg/config" -) - -const ( - addHealthzCheckMethodName = "AddHealthzCheck" - checkerArgumentType = "healthz.Checker" -) - -func TestOperatorManagerProvider(t *testing.T) { - t.Run("creates correct options", func(t *testing.T) { - operatorMgrProvider := operatorManagerProvider{} - options := operatorMgrProvider.createOptions("namespace") - - assert.NotNil(t, options) - - assert.Contains(t, options.Cache.DefaultNamespaces, "namespace") - assert.Equal(t, scheme.Scheme, options.Scheme) - assert.Equal(t, metricsBindAddress, options.Metrics.BindAddress) - - assert.True(t, options.LeaderElection) - assert.Equal(t, leaderElectionId, options.LeaderElectionID) - assert.Equal(t, leaderElectionResourceLock, options.LeaderElectionResourceLock) - assert.Equal(t, "namespace", options.LeaderElectionNamespace) - assert.Equal(t, healthProbeBindAddress, options.HealthProbeBindAddress) - assert.Equal(t, livenessEndpointName, options.LivenessEndpointName) - }) - t.Run("check if healthz/readyz checks are added", func(t *testing.T) { - testHealthzAndReadyz(t, func(mockMgr *managermock.Manager) error { - var controlManagerProvider = NewOperatorManagerProvider(false).(operatorManagerProvider) - - controlManagerProvider.setManager(mockMgr) - _, err := controlManagerProvider.CreateManager("namespace", &rest.Config{}) - - return err - }) - }) -} - -func TestBootstrapManagerProvider(t *testing.T) { - t.Run("implements interface", func(t *testing.T) { - bootstrapProvider := NewBootstrapManagerProvider() - _, _ = bootstrapProvider.CreateManager("namespace", &rest.Config{}) - }) - t.Run("check if healthz/readyz checks are added", func(t *testing.T) { - testBootstrapHealthzAndReadyz(t, func(mockMgr *managermock.Manager) error { - bootstrapProvider, _ := NewBootstrapManagerProvider().(bootstrapManagerProvider) - bootstrapProvider.setManager(mockMgr) - _, err := bootstrapProvider.CreateManager("namespace", &rest.Config{}) - - return err - }) - }) -} - -func testHealthzAndReadyz(t *testing.T, createProviderAndRunManager func(mockMgr *managermock.Manager) error) { - mockMgr := managermock.NewManager(t) - mockMgr.On(addHealthzCheckMethodName, livezEndpointName, mock.AnythingOfType(checkerArgumentType)).Return(nil) - - client := fake.NewClient(&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "kube-system"}}) - - mockMgr.On("GetConfig").Return(&rest.Config{}) - mockMgr.On("GetScheme").Return(scheme.Scheme) - mockMgr.On("GetClient").Return(client) - mockMgr.On("GetAPIReader").Return(client) - mockMgr.On("GetControllerOptions").Return(config.Controller{SkipNameValidation: ptr.To(true)}) - mockMgr.On("GetLogger").Return(logr.Logger{}) - mockMgr.On("Add", mock.AnythingOfType("*controller.Controller[sigs.k8s.io/controller-runtime/pkg/reconcile.Request]")).Return(nil) - mockMgr.On("GetCache").Return(nil) - mockMgr.On("GetRESTMapper").Return(nil) - - err := createProviderAndRunManager(mockMgr) - - require.NoError(t, err) - mockMgr.AssertCalled(t, addHealthzCheckMethodName, livezEndpointName, mock.AnythingOfType(checkerArgumentType)) - - expectedHealthzError := errors.New("healthz error") - mockMgr = managermock.NewManager(t) - mockMgr.On(addHealthzCheckMethodName, mock.Anything, mock.Anything).Return(expectedHealthzError) - - err = createProviderAndRunManager(mockMgr) - - require.EqualError(t, err, expectedHealthzError.Error()) - mockMgr.AssertCalled(t, addHealthzCheckMethodName, mock.Anything, mock.Anything) -} - -func testBootstrapHealthzAndReadyz(t *testing.T, createProviderAndRunManager func(mockMgr *managermock.Manager) error) { - mockMgr := managermock.NewManager(t) - mockMgr.On(addHealthzCheckMethodName, livezEndpointName, mock.AnythingOfType(checkerArgumentType)).Return(nil) - - err := createProviderAndRunManager(mockMgr) - - require.NoError(t, err) - mockMgr.AssertCalled(t, addHealthzCheckMethodName, livezEndpointName, mock.AnythingOfType(checkerArgumentType)) - - expectedHealthzError := errors.New("healthz error") - mockMgr = managermock.NewManager(t) - mockMgr.On(addHealthzCheckMethodName, mock.Anything, mock.Anything).Return(expectedHealthzError) - - err = createProviderAndRunManager(mockMgr) - - require.EqualError(t, err, expectedHealthzError.Error()) - mockMgr.AssertCalled(t, addHealthzCheckMethodName, mock.Anything, mock.Anything) -} diff --git a/cmd/standalone/standalone.go b/cmd/standalone/cmd.go similarity index 84% rename from cmd/standalone/standalone.go rename to cmd/standalone/cmd.go index 4ba18ae6c6..15729fc0e7 100644 --- a/cmd/standalone/standalone.go +++ b/cmd/standalone/cmd.go @@ -15,12 +15,12 @@ const ( func NewStandaloneCommand() *cobra.Command { return &cobra.Command{ Use: use, - RunE: startStandAloneInit, + RunE: run, SilenceUsage: true, } } -func startStandAloneInit(_ *cobra.Command, _ []string) error { +func run(_ *cobra.Command, _ []string) error { unix.Umask(0000) signalHandler := ctrl.SetupSignalHandler() diff --git a/cmd/standalone/standalone_test.go b/cmd/standalone/cmd_test.go similarity index 100% rename from cmd/standalone/standalone_test.go rename to cmd/standalone/cmd_test.go diff --git a/cmd/startup_probe/builder.go b/cmd/startup_probe/cmd.go similarity index 81% rename from cmd/startup_probe/builder.go rename to cmd/startup_probe/cmd.go index 5ca0ffa006..a3ea9a399a 100644 --- a/cmd/startup_probe/builder.go +++ b/cmd/startup_probe/cmd.go @@ -21,18 +21,11 @@ var ( timeoutFlagValue = 5 ) -type CommandBuilder struct { -} - -func NewCommandBuilder() CommandBuilder { - return CommandBuilder{} -} - -func (builder CommandBuilder) Build() *cobra.Command { +func New() *cobra.Command { cmd := &cobra.Command{ Use: use, Long: "query DNS server about " + hostname, - RunE: builder.buildRun(), + RunE: run(), } cmd.PersistentFlags().IntVar(&timeoutFlagValue, "timeout", defaultTimeout, "specify a different timeout [s]") @@ -43,7 +36,7 @@ func (builder CommandBuilder) Build() *cobra.Command { return cmd } -func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { +func run() func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { f := func(_ *cobra.Command, _ []string) error { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutFlagValue)*time.Second) diff --git a/cmd/support_archive/builder.go b/cmd/support_archive/cmd.go similarity index 89% rename from cmd/support_archive/builder.go rename to cmd/support_archive/cmd.go index e7d7df4e55..0dc2c1d522 100644 --- a/cmd/support_archive/builder.go +++ b/cmd/support_archive/cmd.go @@ -8,8 +8,7 @@ import ( "os" "time" - "github.com/Dynatrace/dynatrace-operator/cmd/config" - "github.com/Dynatrace/dynatrace-operator/cmd/remote_command" + "github.com/Dynatrace/dynatrace-operator/cmd/support_archive/remote_command" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" @@ -24,6 +23,7 @@ import ( clientgocorev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/cluster" ) @@ -58,29 +58,11 @@ var ( NumEventsFlagValue int ) -type CommandBuilder struct { - configProvider config.Provider -} - -func NewCommandBuilder() CommandBuilder { - return CommandBuilder{} -} - -func (builder CommandBuilder) SetConfigProvider(provider config.Provider) CommandBuilder { - builder.configProvider = provider - - return builder -} - -func clusterOptions(opts *cluster.Options) { - opts.Scheme = scheme.Scheme -} - -func (builder CommandBuilder) Build() *cobra.Command { +func New() *cobra.Command { cmd := &cobra.Command{ Use: use, Long: "Pack logs and manifests useful for troubleshooting into single tarball", - RunE: builder.buildRun(), + RunE: run(), } addFlags(cmd) @@ -97,7 +79,7 @@ func addFlags(cmd *cobra.Command) { cmd.PersistentFlags().IntVar(&NumEventsFlagValue, numEventsFlagName, DefaultNumEvents, fmt.Sprintf("Number of events to be fetched (default %d)", DefaultNumEvents)) } -func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { +func run() func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { time.Sleep(time.Duration(delayFlagValue) * time.Second) @@ -116,7 +98,7 @@ func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { defer archiveTargetFile.Close() defer supportArchive.Close() - err = builder.runCollectors(log, supportArchive) + err = runCollectors(log, supportArchive) if err != nil { return err } @@ -155,10 +137,10 @@ func getAppNameLabel(ctx context.Context, pods clientgocorev1.PodInterface) stri return defaultOperatorAppName } -func (builder CommandBuilder) runCollectors(log logd.Logger, supportArchive archiver) error { +func runCollectors(log logd.Logger, supportArchive archiver) error { ctx := context.Background() - kubeConfig, err := builder.configProvider.GetConfig() + kubeConfig, err := config.GetConfig() if err != nil { return err } @@ -213,6 +195,10 @@ func getK8sClients(kubeConfig *rest.Config) (*kubernetes.Clientset, client.Reade return clientSet, apiReader, nil } +func clusterOptions(opts *cluster.Options) { + opts.Scheme = scheme.Scheme +} + func printCopyCommand(log logd.Logger, tarballToStdout bool, tarFileName string) { podNamespace := os.Getenv(env.PodNamespace) podName := os.Getenv(env.PodName) diff --git a/cmd/support_archive/builder_test.go b/cmd/support_archive/cmd_test.go similarity index 100% rename from cmd/support_archive/builder_test.go rename to cmd/support_archive/cmd_test.go diff --git a/cmd/support_archive/eec_fs_logs.go b/cmd/support_archive/eec_fs_logs.go index 02848c014d..3e7ac54564 100644 --- a/cmd/support_archive/eec_fs_logs.go +++ b/cmd/support_archive/eec_fs_logs.go @@ -6,7 +6,7 @@ import ( "io" "strings" - "github.com/Dynatrace/dynatrace-operator/cmd/remote_command" + "github.com/Dynatrace/dynatrace-operator/cmd/support_archive/remote_command" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" diff --git a/cmd/remote_command/command.go b/cmd/support_archive/remote_command/command.go similarity index 100% rename from cmd/remote_command/command.go rename to cmd/support_archive/remote_command/command.go diff --git a/cmd/troubleshoot/builder_test.go b/cmd/troubleshoot/builder_test.go deleted file mode 100644 index 9e0e358afc..0000000000 --- a/cmd/troubleshoot/builder_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package troubleshoot - -import ( - "context" - "testing" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestTroubleshootCommandBuilder(t *testing.T) { - t.Run("build command", func(t *testing.T) { - builder := NewTroubleshootCommandBuilder() - csiCommand := builder.Build() - - assert.NotNil(t, csiCommand) - assert.Equal(t, use, csiCommand.Use) - assert.NotNil(t, csiCommand.RunE) - }) - - t.Run("getAllDynakubesInNamespace", func(t *testing.T) { - dk := buildTestDynakube() - clt := fake.NewClient(&dk) - - dynakubes, err := getAllDynakubesInNamespace(context.Background(), getNullLogger(t), clt, testNamespace) - require.NoError(t, err) - assert.Len(t, dynakubes, 1) - assert.Equal(t, dk.Name, dynakubes[0].Name) - }) - - t.Run("getDynakube - only check one dynakube if set", func(t *testing.T) { - dk := buildTestDynakube() - clt := fake.NewClient(&dk) - dynakubes, err := getDynakubes(context.Background(), getNullLogger(t), clt, testNamespace, testDynakube) - require.NoError(t, err) - assert.Len(t, dynakubes, 1) - assert.Equal(t, testDynakube, dynakubes[0].Name) - }) -} - -func buildTestDynakube() dynakube.DynaKube { - return dynakube.DynaKube{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Name: testDynakube, - Namespace: testNamespace, - }, - } -} diff --git a/cmd/troubleshoot/builder.go b/cmd/troubleshoot/cmd.go similarity index 90% rename from cmd/troubleshoot/builder.go rename to cmd/troubleshoot/cmd.go index dc8459760d..7e638f69a9 100644 --- a/cmd/troubleshoot/builder.go +++ b/cmd/troubleshoot/cmd.go @@ -5,7 +5,6 @@ import ( "net/http" "os" - "github.com/Dynatrace/dynatrace-operator/cmd/config" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/logd" @@ -17,6 +16,7 @@ import ( "github.com/spf13/cobra" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/cluster" ) @@ -33,24 +33,10 @@ var ( namespaceFlagValue string ) -type CommandBuilder struct { - configProvider config.Provider -} - -func NewTroubleshootCommandBuilder() CommandBuilder { - return CommandBuilder{} -} - -func (builder CommandBuilder) SetConfigProvider(provider config.Provider) CommandBuilder { - builder.configProvider = provider - - return builder -} - -func (builder CommandBuilder) Build() *cobra.Command { +func New() *cobra.Command { cmd := &cobra.Command{ Use: use, - RunE: builder.buildRun(), + RunE: run(), } addFlags(cmd) @@ -67,12 +53,12 @@ func clusterOptions(opts *cluster.Options) { opts.Scheme = scheme.Scheme } -func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { +func run() func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { version.LogVersion() logd.LogBaseLoggerSettings() - kubeConfig, err := builder.configProvider.GetConfig() + kubeConfig, err := config.GetConfig() if err != nil { return err } diff --git a/cmd/webhook/builder_test.go b/cmd/webhook/builder_test.go deleted file mode 100644 index 36cfdaba55..0000000000 --- a/cmd/webhook/builder_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package webhook - -import ( - "testing" - - configmock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/config" - providermock "github.com/Dynatrace/dynatrace-operator/test/mocks/cmd/manager" - "github.com/stretchr/testify/assert" -) - -func TestWebhookCommandBuilder(t *testing.T) { - t.Run("build command", func(t *testing.T) { - builder := NewWebhookCommandBuilder() - csiCommand := builder.Build() - - assert.NotNil(t, csiCommand) - assert.Equal(t, use, csiCommand.Use) - assert.NotNil(t, csiCommand.RunE) - }) - t.Run("set config provider", func(t *testing.T) { - builder := NewWebhookCommandBuilder() - - assert.NotNil(t, builder) - - expectedProvider := &configmock.Provider{} - builder = builder.SetConfigProvider(expectedProvider) - - assert.Equal(t, expectedProvider, builder.configProvider) - }) - t.Run("set manager provider", func(t *testing.T) { - expectedProvider := providermock.NewProvider(t) - builder := NewWebhookCommandBuilder().SetManagerProvider(expectedProvider) - - assert.Equal(t, expectedProvider, builder.managerProvider) - }) - t.Run("set namespace", func(t *testing.T) { - builder := NewWebhookCommandBuilder().SetNamespace("namespace") - - assert.Equal(t, "namespace", builder.namespace) - }) -} diff --git a/cmd/certificates/config.go b/cmd/webhook/certificates/config.go similarity index 100% rename from cmd/certificates/config.go rename to cmd/webhook/certificates/config.go diff --git a/cmd/certificates/watcher.go b/cmd/webhook/certificates/watcher.go similarity index 100% rename from cmd/certificates/watcher.go rename to cmd/webhook/certificates/watcher.go diff --git a/cmd/webhook/builder.go b/cmd/webhook/cmd.go similarity index 72% rename from cmd/webhook/builder.go rename to cmd/webhook/cmd.go index 0491cad561..ef0d786a79 100644 --- a/cmd/webhook/builder.go +++ b/cmd/webhook/cmd.go @@ -2,10 +2,9 @@ package webhook import ( "context" + "os" - "github.com/Dynatrace/dynatrace-operator/cmd/certificates" - "github.com/Dynatrace/dynatrace-operator/cmd/config" - cmdManager "github.com/Dynatrace/dynatrace-operator/cmd/manager" + "github.com/Dynatrace/dynatrace-operator/cmd/webhook/certificates" edgeconnectv1alpha1 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha1/edgeconnect" edgeconnectv1alpha2 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1alpha2/edgeconnect" dynakubev1beta1 "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta1/dynakube" //nolint:staticcheck @@ -16,6 +15,7 @@ import ( edgeconnectvalidation "github.com/Dynatrace/dynatrace-operator/pkg/api/validation/edgeconnect" "github.com/Dynatrace/dynatrace-operator/pkg/logd" "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/pod" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubesystem" "github.com/Dynatrace/dynatrace-operator/pkg/version" @@ -25,6 +25,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" ) @@ -41,65 +42,74 @@ var ( certificateKeyFileName string ) -type CommandBuilder struct { - configProvider config.Provider - managerProvider cmdManager.Provider - namespace string - podName string +func addFlags(cmd *cobra.Command) { + cmd.PersistentFlags().StringVar(&certificateDirectory, FlagCertificateDirectory, "/tmp/webhook/certs", "Directory to look certificates for.") + cmd.PersistentFlags().StringVar(&certificateFileName, FlagCertificateFileName, "tls.crt", "File name for the public certificate.") + cmd.PersistentFlags().StringVar(&certificateKeyFileName, FlagCertificateKeyFileName, "tls.key", "File name for the private key.") } -func NewWebhookCommandBuilder() CommandBuilder { - return CommandBuilder{} -} +func New() *cobra.Command { + cmd := &cobra.Command{ + Use: use, + RunE: run(), + SilenceUsage: true, + } -func (builder CommandBuilder) SetConfigProvider(provider config.Provider) CommandBuilder { - builder.configProvider = provider + addFlags(cmd) - return builder + return cmd } -func (builder CommandBuilder) SetManagerProvider(provider cmdManager.Provider) CommandBuilder { - builder.managerProvider = provider +func run() func(*cobra.Command, []string) error { + return func(cmd *cobra.Command, args []string) error { + installconfig.ReadModules() + version.LogVersion() + logd.LogBaseLoggerSettings() - return builder -} + podName := os.Getenv(env.PodName) + namespace := os.Getenv(env.PodNamespace) -func (builder CommandBuilder) GetManagerProvider() cmdManager.Provider { - if builder.managerProvider == nil { - builder.managerProvider = NewProvider(certificateDirectory, certificateKeyFileName, certificateFileName) - } + kubeConfig, err := config.GetConfig() + if err != nil { + return err + } - return builder.managerProvider -} + webhookManager, err := createManager(kubeConfig, namespace, certificateDirectory, certificateFileName, certificateKeyFileName) + if err != nil { + return err + } -func (builder CommandBuilder) SetNamespace(namespace string) CommandBuilder { - builder.namespace = namespace + signalHandler := ctrl.SetupSignalHandler() - return builder -} + err = startCertificateWatcher(webhookManager, namespace, podName) + if err != nil { + return err + } -func (builder CommandBuilder) SetPodName(podName string) CommandBuilder { - builder.podName = podName + err = namespacemutator.AddWebhookToManager(webhookManager, namespace) + if err != nil { + return err + } - return builder -} + err = podmutator.AddWebhookToManager(signalHandler, webhookManager, namespace) + if err != nil { + return err + } -func (builder CommandBuilder) Build() *cobra.Command { - cmd := &cobra.Command{ - Use: use, - RunE: builder.buildRun(), - SilenceUsage: true, - } + err = setupDynakubeValidation(webhookManager) + if err != nil { + return err + } - addFlags(cmd) + err = setupEdgeconnectValidation(webhookManager) + if err != nil { + return err + } - return cmd -} + err = webhookManager.Start(signalHandler) -func addFlags(cmd *cobra.Command) { - cmd.PersistentFlags().StringVar(&certificateDirectory, FlagCertificateDirectory, "/tmp/webhook/certs", "Directory to look certificates for.") - cmd.PersistentFlags().StringVar(&certificateFileName, FlagCertificateFileName, "tls.crt", "File name for the public certificate.") - cmd.PersistentFlags().StringVar(&certificateKeyFileName, FlagCertificateKeyFileName, "tls.key", "File name for the private key.") + return errors.WithStack(err) + } } func startCertificateWatcher(webhookManager manager.Manager, namespace string, podName string) error { @@ -162,52 +172,3 @@ func setupEdgeconnectValidation(webhookManager manager.Manager) error { return nil } - -func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { - return func(cmd *cobra.Command, args []string) error { - installconfig.ReadModules() - version.LogVersion() - logd.LogBaseLoggerSettings() - - kubeConfig, err := builder.configProvider.GetConfig() - if err != nil { - return err - } - - webhookManager, err := builder.GetManagerProvider().CreateManager(builder.namespace, kubeConfig) - if err != nil { - return err - } - - signalHandler := ctrl.SetupSignalHandler() - - err = startCertificateWatcher(webhookManager, builder.namespace, builder.podName) - if err != nil { - return err - } - - err = namespacemutator.AddWebhookToManager(webhookManager, builder.namespace) - if err != nil { - return err - } - - err = podmutator.AddWebhookToManager(signalHandler, webhookManager, builder.namespace) - if err != nil { - return err - } - - err = setupDynakubeValidation(webhookManager) - if err != nil { - return err - } - - err = setupEdgeconnectValidation(webhookManager) - if err != nil { - return err - } - - err = webhookManager.Start(signalHandler) - - return errors.WithStack(err) - } -} diff --git a/cmd/webhook/manager.go b/cmd/webhook/manager.go index 65c719bf9d..b394ddc8b3 100644 --- a/cmd/webhook/manager.go +++ b/cmd/webhook/manager.go @@ -26,22 +26,8 @@ const ( readinessEndpointName = "/" + readyzEndpointName ) -type Provider struct { - certificateDirectory string - certificateFileName string - keyFileName string -} - -func NewProvider(certificateDirectory string, keyFileName string, certificateFileName string) Provider { - return Provider{ - certificateDirectory: certificateDirectory, - certificateFileName: certificateFileName, - keyFileName: keyFileName, - } -} - -func (provider Provider) CreateManager(namespace string, config *rest.Config) (manager.Manager, error) { - controlManager, err := ctrl.NewManager(config, provider.createOptions(namespace)) +func createManager(config *rest.Config, namespace, certificateDirectory, certificateFileName, keyFileName string) (manager.Manager, error) { + controlManager, err := ctrl.NewManager(config, createOptions(namespace)) if err != nil { return nil, errors.WithStack(err) } @@ -56,10 +42,10 @@ func (provider Provider) CreateManager(namespace string, config *rest.Config) (m return nil, errors.WithStack(err) } - return provider.setupWebhookServer(controlManager) + return setupWebhookServer(controlManager, certificateDirectory, certificateFileName, keyFileName) } -func (provider Provider) createOptions(namespace string) ctrl.Options { +func createOptions(namespace string) ctrl.Options { port := defaultPort webhookPortEnv := os.Getenv("WEBHOOK_PORT") @@ -100,7 +86,7 @@ func (provider Provider) createOptions(namespace string) ctrl.Options { } } -func (provider Provider) setupWebhookServer(mgr manager.Manager) (manager.Manager, error) { +func setupWebhookServer(mgr manager.Manager, certificateDirectory, certificateFileName, keyFileName string) (manager.Manager, error) { tlsConfig := func(config *tls.Config) { config.MinVersion = tls.VersionTLS13 } @@ -110,9 +96,9 @@ func (provider Provider) setupWebhookServer(mgr manager.Manager) (manager.Manage return nil, errors.WithStack(errors.New("Unable to cast webhook server")) } - webhookServer.Options.CertDir = provider.certificateDirectory - webhookServer.Options.KeyName = provider.keyFileName - webhookServer.Options.CertName = provider.certificateFileName + webhookServer.Options.CertDir = certificateDirectory + webhookServer.Options.KeyName = keyFileName + webhookServer.Options.CertName = certificateFileName webhookServer.Options.TLSOpts = []func(*tls.Config){tlsConfig} return mgr, nil diff --git a/cmd/webhook/manager_test.go b/cmd/webhook/manager_test.go deleted file mode 100644 index bd4f8ac511..0000000000 --- a/cmd/webhook/manager_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package webhook - -import ( - "testing" - - "github.com/Dynatrace/dynatrace-operator/cmd/manager" - "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme" - managermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/webhook" -) - -func TestCreateOptions(t *testing.T) { - t.Run("implements interface", func(t *testing.T) { - var provider manager.Provider = NewProvider("certs-dir", "key-file", "cert-file") - _, _ = provider.CreateManager("namespace", &rest.Config{}) - - providerImpl := provider.(Provider) - assert.Equal(t, "certs-dir", providerImpl.certificateDirectory) - assert.Equal(t, "key-file", providerImpl.keyFileName) - assert.Equal(t, "cert-file", providerImpl.certificateFileName) - }) - t.Run("creates options", func(t *testing.T) { - provider := Provider{} - options := provider.createOptions("test-namespace") - - assert.NotNil(t, options) - assert.Contains(t, options.Cache.DefaultNamespaces, "test-namespace") - assert.Equal(t, scheme.Scheme, options.Scheme) - assert.Equal(t, defaultMetricsBindAddress, options.Metrics.BindAddress) - - webhookServer, ok := options.WebhookServer.(*webhook.DefaultServer) - require.True(t, ok) - assert.Equal(t, defaultPort, webhookServer.Options.Port) - }) - - t.Run("creates options with custom ports", func(t *testing.T) { - t.Setenv("WEBHOOK_PORT", "6443") - t.Setenv("METRICS_BIND_ADDRESS", ":8081") - t.Setenv("HEALTH_PROBE_BIND_ADDRESS", ":10081") - - provider := Provider{} - options := provider.createOptions("test-namespace") - - assert.NotNil(t, options) - assert.Contains(t, options.Cache.DefaultNamespaces, "test-namespace") - assert.Equal(t, scheme.Scheme, options.Scheme) - - webhookServer, ok := options.WebhookServer.(*webhook.DefaultServer) - require.True(t, ok) - assert.Equal(t, 6443, webhookServer.Options.Port) - assert.Equal(t, ":10081", options.HealthProbeBindAddress) - assert.Equal(t, ":8081", options.Metrics.BindAddress) - }) - t.Run("configures webhooks server", func(t *testing.T) { - provider := NewProvider("certs-dir", "key-file", "cert-file") - expectedWebhookServer := &webhook.DefaultServer{} - - mockedMgr := managermock.NewManager(t) - mockedMgr.On("GetWebhookServer").Return(expectedWebhookServer) - - mgrWithWebhookServer, err := provider.setupWebhookServer(mockedMgr) - require.NoError(t, err) - - mgrWebhookServer, ok := mgrWithWebhookServer.GetWebhookServer().(*webhook.DefaultServer) - require.True(t, ok) - assert.Equal(t, "certs-dir", mgrWebhookServer.Options.CertDir) - assert.Equal(t, "key-file", mgrWebhookServer.Options.KeyName) - assert.Equal(t, "cert-file", mgrWebhookServer.Options.CertName) - }) -} diff --git a/codecov.yml b/codecov.yml index 89afc8d3f9..8ac6f6a035 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,7 +2,7 @@ codecov: require_ci_to_pass: false coverage: - range: 63..100 + range: 62..100 round: down precision: 2 @@ -11,16 +11,16 @@ coverage: default: # context, you can create multiple ones with custom titles enabled: yes # must be yes|true to enable this status target: - 63 # specify the target coverage for each commit status + 62 # specify the target coverage for each commit status # option: "auto" (must increase from parent commit or pull request base) # option: "X%" a static target percentage to hit if_not_found: success # if parent is not found report status as success, error, or failure if_ci_failed: error # if ci fails report status as success, error, or failure - patch: - default: - enabled: yes - target: auto - threshold: 1% # allowed to drop X% and still result in a "success" commit status - base: auto + patch: off ignore: + - "./cmd/csi/*.go" + - "./cmd/operator/*.go" + - "./cmd/standalone/*.go" + - "./cmd/webhook/*.go" + - "./cmd/startup_probe/*.go" - "./test/mocks/*.go" # ignore test mocks. diff --git a/hack/make/go.mk b/hack/make/go.mk index b2e676826d..48bddc1594 100644 --- a/hack/make/go.mk +++ b/hack/make/go.mk @@ -45,7 +45,7 @@ go/coverage: go/test ## Runs go integration test go/integration_test: - go test -ldflags="-X 'github.com/Dynatrace/dynatrace-operator/pkg/version.Commit=$(shell git rev-parse HEAD)' -X 'github.com/Dynatrace/dynatrace-operator/pkg/version.Version=$(shell git branch --show-current)'" ./cmd/integration/* + go test -ldflags="-X 'github.com/Dynatrace/dynatrace-operator/pkg/version.Commit=$(shell git rev-parse HEAD)' -X 'github.com/Dynatrace/dynatrace-operator/pkg/version.Version=$(shell git branch --show-current)'" ./test/integration/* ## creates mocks from .mockery.yaml go/gen_mocks: prerequisites/mockery diff --git a/pkg/controllers/certificates/webhook_cert_controller.go b/pkg/controllers/certificates/webhook_cert_controller.go index 39247c962f..5597ed81d1 100644 --- a/pkg/controllers/certificates/webhook_cert_controller.go +++ b/pkg/controllers/certificates/webhook_cert_controller.go @@ -36,7 +36,7 @@ func Add(mgr manager.Manager, ns string) error { Complete(newWebhookCertificateController(mgr, nil)) } -func AddBootstrap(mgr manager.Manager, ns string, cancelMgr context.CancelFunc) error { +func AddInit(mgr manager.Manager, ns string, cancelMgr context.CancelFunc) error { return ctrl.NewControllerManagedBy(mgr). For(&appsv1.Deployment{}). Named("webhook-boostrap-controller"). diff --git a/test/helpers/platform/platform.go b/test/helpers/platform/platform.go index e3adf95dbb..9f3a96c2f2 100644 --- a/test/helpers/platform/platform.go +++ b/test/helpers/platform/platform.go @@ -1,9 +1,9 @@ package platform import ( - "github.com/Dynatrace/dynatrace-operator/cmd/config" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/client-go/discovery" + "sigs.k8s.io/controller-runtime/pkg/client/config" ) const ( @@ -48,8 +48,7 @@ func (p *Resolver) GetPlatform() (string, error) { } func getDiscoveryClient() (discovery.DiscoveryInterface, error) { - kubeconfigProvider := config.KubeConfigProvider{} - kubeconfig, err := kubeconfigProvider.GetConfig() + kubeconfig, err := config.GetConfig() if err != nil { return nil, err } diff --git a/cmd/integration/integration_test.go b/test/integration/integration_test.go similarity index 100% rename from cmd/integration/integration_test.go rename to test/integration/integration_test.go From 86e608b5a4d3729bc46849bb8e89df78eead2cf7 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Wed, 26 Mar 2025 13:18:44 +0100 Subject: [PATCH 366/426] Updated golangci to v2 (#4658) --- .github/workflows/ci.yaml | 6 +- .golangci.yml | 658 +++++++++--------- hack/make/prerequisites.mk | 6 +- .../edgeconnect/edgeconnect_types_test.go | 2 +- .../v1beta3/dynakube/oneagent/props_test.go | 8 +- pkg/api/v1beta3/dynakube/test/proxy_test.go | 4 +- .../v1beta4/dynakube/oneagent/props_test.go | 8 +- pkg/api/v1beta4/dynakube/test/proxy_test.go | 4 +- .../dynatrace/communication_hosts_test.go | 2 +- .../dynatrace/dynatrace_client_test.go | 2 +- .../dynatrace/oneagent_connection_info.go | 2 +- .../dynatrace/settings_kubernetes_test.go | 10 +- .../dynatrace/settings_logmonitoring_test.go | 4 +- pkg/clients/dynatrace/settings_test.go | 4 +- .../certificates/certificate_secret_test.go | 6 +- pkg/controllers/certificates/certs_test.go | 4 +- pkg/controllers/csi/driver/server.go | 6 +- .../activegate/capability/capability_test.go | 2 +- .../internal/statefulset/statefulset_test.go | 2 +- .../dynakube/apimonitoring/reconciler_test.go | 10 +- .../dynakube/dtpullsecret/reconciler.go | 2 +- .../dynakube/istio/serviceentry_test.go | 20 +- .../dynakube/istio/virtualservice_test.go | 4 +- .../oneagent/daemonset/daemonset_test.go | 2 +- pkg/controllers/dynakube/token/tokens_test.go | 2 +- .../dynakube/version/activegate_test.go | 2 +- .../edgeconnect/deployment/deployment_test.go | 2 +- .../processmoduleconfig/merge_test.go | 6 +- 28 files changed, 383 insertions(+), 407 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2193660b9a..247da19400 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,11 +86,11 @@ jobs: with: go-version-file: "${{ github.workspace }}/go.mod" - name: Run golangci-lint - uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2 + uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd # v7.0.0 with: # renovate depName=github.com/golangci/golangci-lint - version: v1.64.8 - args: --build-tags e2e --timeout 300s --out-${NO_FUTURE}format colored-line-number + version: v2.0.1 + args: --build-tags e2e --timeout 300s - name: Run deadcode id: deadcode run: | diff --git a/.golangci.yml b/.golangci.yml index 2b25bac02c..147b0bb46e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,343 +1,319 @@ -linters-settings: - misspell: - locale: US - staticcheck: - checks: - - all - govet: - enable: - - fieldalignment - disable: - # Disable checking for copied locks since it causes a lot of annoying false-positives - - copylocks - goconst: - ignore-tests: true - gosec: - excludes: - - G101 # "pattern": "(?i)passwd|pass|password|pwd|secret|private_key|token" - - G305 # File traversal when extracting zip/tar archive - revive: - enable-all-rules: true - rules: - - name: cognitive-complexity - arguments: [20] # max allowed cognitive complexity factor - - name: function-result-limit - arguments: [3] - - name: function-length - # following values set to avoid further regressions: - arguments: [52, 468] # the maximum allowed statements and lines. 0 disables the check - - name: cyclomatic - arguments: [12] - - name: banned-characters - disabled: true - - name: file-header - disabled: true - - name: max-public-structs - disabled: true - - name: argument-limit - arguments: [5] - - name: line-length-limit - disabled: true - - name: add-constant - disabled: true - - name: var-naming - disabled: true - - name: unused-receiver - disabled: true - - name: import-shadowing - disabled: true - - name: modifies-value-receiver - disabled: true - - name: bare-return - disabled: true - - name: bare-return - disabled: true - - name: if-return - disabled: true - - name: redefines-builtin-id - disabled: true - - name: context-keys-type - disabled: true - - name: unused-parameter - disabled: true - - name: time-naming - disabled: true - - name: errorf - disabled: true - - name: unexported-return - disabled: true - - name: unhandled-error - disabled: true - - name: confusing-naming - disabled: true - - name: indent-error-flow - disabled: true - - name: early-return - disabled: true - - name: bool-literal-in-expr - disabled: true - - name: error-strings - disabled: true - - name: empty-lines - disabled: true - - name: flag-parameter - disabled: true - - name: blank-imports - disabled: true - - name: increment-decrement - disabled: true - - name: context-as-argument - disabled: true - - name: confusing-results - disabled: true - - name: receiver-naming - disabled: true - - name: nested-structs - disabled: true - - name: struct-tag - disabled: true - - name: error-naming - disabled: true - - name: range-val-address - disabled: true - - name: import-alias-naming - arguments: ["^[a-z][\\w]{0,}$"] - - name: unchecked-type-assertion - disabled: true - depguard: - rules: - all: - files: - - $all - allow: - - $gostd - # Approved orgs. - - "github.com/Dynatrace" - - "github.com/container-storage-interface" - - "github.com/containers" - - "github.com/klauspost" - - "github.com/opencontainers" - - "github.com/prometheus" - - "istio.io" - - "k8s.io" - - "sigs.k8s.io" - - "golang.org" - - "go.opentelemetry.io" - - "go.uber.org" - - "gopkg.in" - - "google.golang.org" - - # Approved packages. - - "github.com/mattn/go-sqlite3" - - "github.com/pkg/errors" - - "github.com/spf13/afero" - - "github.com/spf13/cobra" # For CLI - - "github.com/evanphx/json-patch" - - "github.com/go-logr/logr" - - "github.com/stretchr/testify" - - "github.com/google/go-containerregistry" - - "github.com/docker/cli" - - "github.com/go-gormigrate/gormigrate" - - "github.com/google/uuid" - - # Allowed packages in container-based builder. - deny: - # TODO: (andrii) Potentially uncomment it in future, but requires some refactoring - # - pkg: "reflect" - # desc: Please don't use reflect package - - pkg: "unsafe" - desc: Please don't use unsafe package - - main: - files: - - $all - # Don't allow go-cmp in non-test code. - # NOTE: test code is allowed to use github.com/google/go-cmp (there is no - # deny for it) but non-test code is not. - - "!$test" - - "!test/**/*.go" - - "!**/testing/**" - - "!**/*mock*/**/.go" - deny: - - pkg: "github.com/google/go-cmp" - desc: Please don't use go-cmp for non-test code. - mnd: - checks: - - argument - - case - - condition - - operation - - return - ignored-files: - - test*.go,testing.go - ignored-functions: - - '^time\.' - - strings.SplitN - - '^wait\.' - - rand.WithLength - - '^require\.' - - WaitForCondition - - '^int*' - ignored-numbers: - - '0666' - - '0644' - - '0755' - - '0770' - - '0755' - - '0000' - - '1001' - - '1000' - - '1234' - dupl: - threshold: 150 - godot: - exclude: - - '^\ \+' +version: "2" linters: - disable-all: true + default: none + enable: + - asasalint + - asciicheck + - bidichk + - copyloopvar + - decorder + - depguard + - dogsled + - dupl + - durationcheck + - errorlint + - forbidigo + - gocheckcompilerdirectives + - gochecksumtype + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - goheader + - gomoddirectives + - gomodguard + - goprintffuncname + - gosec + - gosmopolitan + - govet + - grouper + - importas + - ineffassign + - intrange + - loggercheck + - makezero + - mirror + - misspell + - mnd + - nakedret + - nilerr + - nilnil + - nlreturn + - noctx + - nolintlint + - nosprintfhostport + - perfsprint + - prealloc + - predeclared + - protogetter + - reassign + - revive + - sloglint + - staticcheck + - testableexamples + - testifylint + - thelper + - tparallel + - unconvert + - unparam + - unused + - usestdlibvars + - wastedassign + - whitespace + - wsl + - zerologlint + settings: + depguard: + rules: + all: + files: + - $all + allow: + - $gostd + - github.com/Dynatrace + - github.com/container-storage-interface + - github.com/containers + - github.com/klauspost + - github.com/opencontainers + - github.com/prometheus + - istio.io + - k8s.io + - sigs.k8s.io + - golang.org + - go.opentelemetry.io + - go.uber.org + - gopkg.in + - google.golang.org + - github.com/mattn/go-sqlite3 + - github.com/pkg/errors + - github.com/spf13/afero + - github.com/spf13/cobra + - github.com/evanphx/json-patch + - github.com/go-logr/logr + - github.com/stretchr/testify + - github.com/google/go-containerregistry + - github.com/docker/cli + - github.com/go-gormigrate/gormigrate + - github.com/google/uuid + deny: + - pkg: unsafe + desc: Please don't use unsafe package + main: + files: + - $all + - '!$test' + - '!test/**/*.go' + - '!**/testing/**' + - '!**/*mock*/**/.go' + deny: + - pkg: github.com/google/go-cmp + desc: Please don't use go-cmp for non-test code. + dupl: + threshold: 150 + godot: + exclude: + - ^\ \+ + gosec: + excludes: + - G101 + - G305 + govet: + enable: + - fieldalignment + disable: + - copylocks + misspell: + locale: US + mnd: + checks: + - argument + - case + - condition + - operation + - return + ignored-numbers: + - "0666" + - "0644" + - "0755" + - "0770" + - "0755" + - "0000" + - "1001" + - "1000" + - "1234" + ignored-files: + - test*.go,testing.go + ignored-functions: + - ^time\. + - strings.SplitN + - ^wait\. + - rand.WithLength + - ^require\. + - WaitForCondition + - ^int* + revive: + enable-all-rules: true + rules: + - name: cognitive-complexity + arguments: + - 20 + - name: function-result-limit + arguments: + - 3 + - name: function-length + arguments: + - 52 + - 468 + - name: cyclomatic + arguments: + - 12 + - name: banned-characters + disabled: true + - name: file-header + disabled: true + - name: max-public-structs + disabled: true + - name: argument-limit + arguments: + - 5 + - name: line-length-limit + disabled: true + - name: add-constant + disabled: true + - name: var-naming + disabled: true + - name: unused-receiver + disabled: true + - name: import-shadowing + disabled: true + - name: modifies-value-receiver + disabled: true + - name: bare-return + disabled: true + - name: bare-return + disabled: true + - name: if-return + disabled: true + - name: redefines-builtin-id + disabled: true + - name: context-keys-type + disabled: true + - name: unused-parameter + disabled: true + - name: time-naming + disabled: true + - name: errorf + disabled: true + - name: unexported-return + disabled: true + - name: unhandled-error + disabled: true + - name: confusing-naming + disabled: true + - name: indent-error-flow + disabled: true + - name: early-return + disabled: true + - name: bool-literal-in-expr + disabled: true + - name: error-strings + disabled: true + - name: empty-lines + disabled: true + - name: flag-parameter + disabled: true + - name: blank-imports + disabled: true + - name: increment-decrement + disabled: true + - name: context-as-argument + disabled: true + - name: confusing-results + disabled: true + - name: receiver-naming + disabled: true + - name: nested-structs + disabled: true + - name: struct-tag + disabled: true + - name: error-naming + disabled: true + - name: range-val-address + disabled: true + - name: import-alias-naming + arguments: + - ^[a-z][\w]{0,}$ + - name: unchecked-type-assertion + disabled: true + staticcheck: + checks: + - all + - "-ST*" # this is stylecheck, but has been rolled into staticcheck + - "-QF1008" # could remove embedded field from selector, example: dk.ObjectMeta.Labels == dk.Labels + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - dupl + - perfsprint + - wsl + path: _(test|gen)\.go + - linters: + - govet + - noctx + - perfsprint + - thelper + - wsl + path: (test/*) + - linters: + - dupl + - govet + path: _(test|gen)\.go + - linters: + - gosec + path: pkg/webhook/validation/proxy_url_test.go + - linters: + - gosec + path: pkg/ingestendpoint/secret_test.go + - linters: + - unparam + text: always receives + - linters: + - revive + path: pkg/clients/dynatrace + - linters: + - godot + path-except: pkg/api/(.+)\.go + - linters: + - goconst + path: (.+)_test\.go + paths: + - pkg/api/v1alpha1/dynakube + - pkg/api/v1alpha1/edgeconnect + - pkg/api/v1beta1/dynakube + - pkg/api/v1beta2/dynakube + - pkg/api/v1beta3/dynakube + - third_party$ + - builtin$ + - examples$ +formatters: enable: - - asasalint # Check for pass []any as any in variadic func(...any). - - asciicheck # Checks that all code identifiers does not have non-ASCII symbols in the name. - - bidichk # Checks for dangerous unicode character sequences. - - copyloopvar # Copyloopvar is a linter detects places where loop variables are copied. - - decorder # Check declaration order and count of types, constants, variables and functions. - - depguard # Go linter that checks if package imports are in a list of acceptable packages - - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - - dupl # Tool for code clone detection. - - durationcheck # Check for two durations multiplied together. - - errorlint # Errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - - forbidigo # Forbids identifiers. - - gci # Gci controls Go package import order and makes it always deterministic. - - gocheckcompilerdirectives # Checks that go compiler directive comments (//go:) are valid. - - gochecksumtype # Run exhaustiveness checks on Go "sum types" - - gocognit # Computes and checks the cognitive complexity of functions. - - goconst # Finds repeated strings that could be replaced by a constant - - gocritic # Provides diagnostics that check for bugs, performance and style issues. - - gocyclo # Computes and checks the cyclomatic complexity of functions. complexity. - - godot # Check if comments end in a period. - - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - - goheader # Checks is file header matches to pattern. - - mnd # An analyzer to detect magic numbers. - - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - - goprintffuncname # Checks that printf-like functions are named with f at the end. - - gosec # Inspects source code for security problems - - gosimple # Linter for Go source code that specializes in simplifying code. - - gosmopolitan # Report certain i18n/l10n anti-patterns in your Go codebase. - - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string - - grouper # Analyze expression groups. - - importas # Enforces consistent import aliases. - - ineffassign # Detects when assignments to existing variables are not used - - intrange # Intrange is a linter to find places where for loops could make use of an integer range. - - loggercheck # Checks key value pairs for common logger libraries (kitlog,klog,logr,zap). - - makezero # Finds slice declarations with non-zero initial length. - - mirror # Reports wrong mirror patterns of bytes/strings usage. - - misspell # Finds commonly misspelled English words in comments. - - nakedret # Checks that functions with naked returns are not longer than a maximum size (can be zero). - - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - - nilnil # Checks that there is no simultaneous return of nil error and an invalid value. - - nlreturn # Nlreturn checks for a new line before return and branch statements to increase code clarity. - - noctx # Finds sending http request without context.Context. - - nolintlint # Reports ill-formed or insufficient nolint directives. - - nosprintfhostport # Checks for misuse of Sprintf to construct a host with port in a URL. - - perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative. - - prealloc # Finds slice declarations that could potentially be pre-allocated - - predeclared # Find code that shadows one of Go's predeclared identifiers. - - protogetter # Reports direct reads from proto message fields when getters should be used. - - reassign # Checks that package variables are not reassigned. - - revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. - - sloglint # Ensure consistent code style when using log/slog. - - staticcheck # It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint. - - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - testableexamples # Linter checks if examples are testable (have an expected output). - - testifylint # Checks usage of github.com/stretchr/testify. - - thelper # Thelper detects tests helpers which is not start with t.Helper() method. - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - - unconvert # Remove unnecessary type conversions - - unparam # Reports unused function parameters - - unused # Checks Go code for unused constants, variables, functions and types - - usestdlibvars # A linter that detect the possibility to use variables/constants from the Go standard library. - - wastedassign # wastedassign finds wasted assignment statements. - - whitespace # Tool for detection of leading and trailing whitespace. - - wsl # Add or remove empty lines. - - zerologlint # Detects the wrong usage of zerolog that a user forgets to dispatch with Send or Msg. - -# Blocked: -# false positive -> https://github.com/timakin/bodyclose/issues/51 -# - bodyclose # Checks whether HTTP response body is closed successfully. - -# TODO: Requires some code changes before enabling: -# - contextcheck # Check whether the function uses a non-inherited context. -# - cyclop # Checks function and package cyclomatic complexity. -# - dupword # Checks for duplicate words in the source code. comment -# - errcheck # enabled by default and recommended -# - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and reports occations, where the check for the returned error can be omitted. -# - errname # Checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error. -# - execinquery # Execinquery is a linter about query string checker in Query function which reads your Go src files and warning it finds. -# - exhaustruct # Checks if all structure fields are initialized. -# - exportloopref # Checks for pointers to enclosing loop variables. -# - forcetypeassert # Finds forced type assertions. -# - funlen # Tool for detection of long functions. -# - gochecknoglobals # Check that no global variables exist. -# - gochecknoinits # Checks that no init functions are present in Go code. -# - goerr113 # Go linter to check the errors handling expressions. -# - gofumpt # Gofumpt checks whether code was gofumpt-ed. -# - inamedparam # reports interfaces with unnamed method parameters. -# - ireturn # Accept Interfaces, Return Concrete Types. -# - maintidx # Maintidx measures the maintainability index of each function. -# - musttag # Enforce field tags in (un)marshaled structs. -# - nestif # Reports deeply nested if statements. -# - nonamedreturns # Reports all named returns. -# - paralleltest # Detects missing usage of t.Parallel() method in your Go test. -# - promlinter # Check Prometheus metrics naming via promlint. -# - rowserrcheck # Checks whether Rows.Err of rows is checked successfully. -# - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. -# - wrapcheck # Checks that errors returned from external packages are wrapped. -# TODO: Need to discuss/decide/remove -# - exhaustive # Check exhaustiveness of enum switch statements. -# - godox # Tool for detection of FIXME, TODO and other comment keywords. -# - inamedparam # reports interfaces with unnamed method parameters. -# - interfacebloat # A linter that checks the number of methods inside an interface. -# - lll # Reports long lines. -# - stylecheck # Stylecheck is a replacement for golint. -# - tagliatelle # Checks the struct tags. -# - testpackage # Linter that makes you use a separate _test package. - -issues: - exclude-dirs: - - pkg/api/v1alpha1/dynakube # legacy version, should not be changed - exclude-rules: - # Exclude duplicate code and function length and complexity checking in test - # files (due to common repeats and long functions in test code) - - path: _(test|gen)\.go - linters: - - dupl - - wsl - - perfsprint - - path: (test/*) - linters: - - noctx - - wsl - - thelper - - perfsprint - - govet - - path: _(test|gen)\.go - linters: - - govet - - dupl - - linters: - - gosec - path: pkg/webhook/validation/proxy_url_test.go - - linters: - - gosec - path: pkg/ingestendpoint/secret_test.go - - linters: - - unparam - text: always receives - - linters: - - revive - path: pkg/clients/dynatrace # it's awaiting refactoring - # Run some linter only for test files by excluding its issues for everything else. - - path-except: 'pkg/api/(.+)\.go' - linters: - - godot + - gci + - gofmt + exclusions: + generated: lax + paths: + - pkg/api/v1alpha1/dynakube + - pkg/api/v1alpha1/edgeconnect + - pkg/api/v1beta1/dynakube + - pkg/api/v1beta2/dynakube + - pkg/api/v1beta3/dynakube + - third_party$ + - builtin$ + - examples$ diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 1c3a39072a..0e25f093ab 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -2,8 +2,8 @@ kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.2 -# renovate depName=github.com/golangci/golangci-lint -golang_ci_cmd_version=v1.64.8 +# renovate depName=github.com/golangci/golangci-lint/v2 +golang_ci_cmd_version=v2.0.1 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.6 # renovate depName=golang.org/x/tools @@ -39,7 +39,7 @@ CONTROLLER_GEN=$(shell hack/build/command.sh controller-gen) ## Install go linters prerequisites/go-linting: prerequisites/go-deadcode - go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(golang_ci_cmd_version) + go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(golang_ci_cmd_version) go install github.com/daixiang0/gci@$(gci_version) go install golang.org/x/tools/cmd/goimports@$(golang_tools_version) go install github.com/bombsimon/wsl/v4/cmd...@master diff --git a/pkg/api/v1alpha2/edgeconnect/edgeconnect_types_test.go b/pkg/api/v1alpha2/edgeconnect/edgeconnect_types_test.go index 2083267d4a..2a71b3088f 100644 --- a/pkg/api/v1alpha2/edgeconnect/edgeconnect_types_test.go +++ b/pkg/api/v1alpha2/edgeconnect/edgeconnect_types_test.go @@ -25,6 +25,6 @@ func TestHostMappings(t *testing.T) { To: KubernetesDefaultDNS, }, } - require.EqualValues(t, expected, got) + require.Equal(t, expected, got) }) } diff --git a/pkg/api/v1beta3/dynakube/oneagent/props_test.go b/pkg/api/v1beta3/dynakube/oneagent/props_test.go index 00987176f8..6dff931c89 100644 --- a/pkg/api/v1beta3/dynakube/oneagent/props_test.go +++ b/pkg/api/v1beta3/dynakube/oneagent/props_test.go @@ -63,7 +63,7 @@ func TestNeedsReadonlyOneagent(t *testing.T) { func TestDefaultOneAgentImage(t *testing.T) { t.Run("OneAgentImage with no API URL", func(t *testing.T) { oneAgent := OneAgent{} - assert.Equal(t, "", oneAgent.GetDefaultImage("")) + assert.Empty(t, oneAgent.GetDefaultImage("")) }) t.Run("OneAgentImage adds raw postfix", func(t *testing.T) { @@ -96,7 +96,7 @@ func TestCustomOneAgentImage(t *testing.T) { t.Run("OneAgentImage with no custom image", func(t *testing.T) { oneAgent := OneAgent{Spec: &Spec{ClassicFullStack: &HostInjectSpec{}}} - assert.Equal(t, "", oneAgent.GetCustomImage()) + assert.Empty(t, oneAgent.GetCustomImage()) }) } @@ -287,10 +287,10 @@ func TestOneAgentArgumentsMap(t *testing.T) { assert.Equal(t, "prop3=val3", argMap["--set-host-property"][5]) require.Len(t, argMap["--set-no-proxy"], 1) - assert.Equal(t, "", argMap["--set-no-proxy"][0]) + assert.Empty(t, argMap["--set-no-proxy"][0]) require.Len(t, argMap["--set-proxy"], 1) - assert.Equal(t, "", argMap["--set-proxy"][0]) + assert.Empty(t, argMap["--set-proxy"][0]) require.Len(t, argMap["--set-tenant"], 1) assert.Equal(t, "$(DT_TENANT)", argMap["--set-tenant"][0]) diff --git a/pkg/api/v1beta3/dynakube/test/proxy_test.go b/pkg/api/v1beta3/dynakube/test/proxy_test.go index 80c592c19c..58c2d3a8f5 100644 --- a/pkg/api/v1beta3/dynakube/test/proxy_test.go +++ b/pkg/api/v1beta3/dynakube/test/proxy_test.go @@ -36,7 +36,7 @@ func proxyValueTester(t *testing.T) { emptyDk := dynakube.DynaKube{} proxy, err = emptyDk.Proxy(context.TODO(), nil) require.NoError(t, err) - assert.Equal(t, "", proxy) + assert.Empty(t, proxy) } func proxyValueFromTester(t *testing.T) { @@ -57,5 +57,5 @@ func proxyValueFromTester(t *testing.T) { kubeReader = fake.NewClient() proxy, err = dk.Proxy(context.TODO(), kubeReader) require.Error(t, err) - assert.Equal(t, "", proxy) + assert.Empty(t, proxy) } diff --git a/pkg/api/v1beta4/dynakube/oneagent/props_test.go b/pkg/api/v1beta4/dynakube/oneagent/props_test.go index 71bc2c88c1..85d55630fa 100644 --- a/pkg/api/v1beta4/dynakube/oneagent/props_test.go +++ b/pkg/api/v1beta4/dynakube/oneagent/props_test.go @@ -63,7 +63,7 @@ func TestNeedsReadonlyOneagent(t *testing.T) { func TestDefaultOneAgentImage(t *testing.T) { t.Run("OneAgentImage with no API URL", func(t *testing.T) { oneAgent := OneAgent{} - assert.Equal(t, "", oneAgent.GetDefaultImage("")) + assert.Empty(t, oneAgent.GetDefaultImage("")) }) t.Run("OneAgentImage adds raw postfix", func(t *testing.T) { @@ -96,7 +96,7 @@ func TestCustomOneAgentImage(t *testing.T) { t.Run("OneAgentImage with no custom image", func(t *testing.T) { oneAgent := OneAgent{Spec: &Spec{ClassicFullStack: &HostInjectSpec{}}} - assert.Equal(t, "", oneAgent.GetCustomImage()) + assert.Empty(t, oneAgent.GetCustomImage()) }) } @@ -287,10 +287,10 @@ func TestOneAgentArgumentsMap(t *testing.T) { assert.Equal(t, "prop3=val3", argMap["--set-host-property"][5]) require.Len(t, argMap["--set-no-proxy"], 1) - assert.Equal(t, "", argMap["--set-no-proxy"][0]) + assert.Empty(t, argMap["--set-no-proxy"][0]) require.Len(t, argMap["--set-proxy"], 1) - assert.Equal(t, "", argMap["--set-proxy"][0]) + assert.Empty(t, argMap["--set-proxy"][0]) require.Len(t, argMap["--set-tenant"], 1) assert.Equal(t, "$(DT_TENANT)", argMap["--set-tenant"][0]) diff --git a/pkg/api/v1beta4/dynakube/test/proxy_test.go b/pkg/api/v1beta4/dynakube/test/proxy_test.go index b2bf42ceda..cfb626a7bf 100644 --- a/pkg/api/v1beta4/dynakube/test/proxy_test.go +++ b/pkg/api/v1beta4/dynakube/test/proxy_test.go @@ -36,7 +36,7 @@ func proxyValueTester(t *testing.T) { emptyDk := dynakube.DynaKube{} proxy, err = emptyDk.Proxy(context.TODO(), nil) require.NoError(t, err) - assert.Equal(t, "", proxy) + assert.Empty(t, proxy) } func proxyValueFromTester(t *testing.T) { @@ -57,5 +57,5 @@ func proxyValueFromTester(t *testing.T) { kubeReader = fake.NewClient() proxy, err = dk.Proxy(context.TODO(), kubeReader) require.Error(t, err) - assert.Equal(t, "", proxy) + assert.Empty(t, proxy) } diff --git a/pkg/clients/dynatrace/communication_hosts_test.go b/pkg/clients/dynatrace/communication_hosts_test.go index 7bcafa5ade..451f2193e5 100644 --- a/pkg/clients/dynatrace/communication_hosts_test.go +++ b/pkg/clients/dynatrace/communication_hosts_test.go @@ -146,7 +146,7 @@ func testCommunicationHostsGetCommunicationHosts(t *testing.T, dynatraceClient C res, err := dynatraceClient.GetOneAgentConnectionInfo(ctx) require.NoError(t, err) - assert.ObjectsAreEqualValues(res.CommunicationHosts, []CommunicationHost{ + assert.ObjectsAreEqual(res.CommunicationHosts, []CommunicationHost{ {Host: "host1.dynatracelabs.com", Port: 80, Protocol: "http"}, {Host: "host2.dynatracelabs.com", Port: 443, Protocol: "https"}, {Host: "12.0.9.1", Port: 80, Protocol: "http"}, diff --git a/pkg/clients/dynatrace/dynatrace_client_test.go b/pkg/clients/dynatrace/dynatrace_client_test.go index 8316fa068d..5b69771049 100644 --- a/pkg/clients/dynatrace/dynatrace_client_test.go +++ b/pkg/clients/dynatrace/dynatrace_client_test.go @@ -120,7 +120,7 @@ func TestBuildHostCache(t *testing.T) { err := dc.buildHostCache(ctx) require.NoError(t, err) assert.NotEmpty(t, dc.hostCache) - assert.ObjectsAreEqualValues(dc.hostCache, map[string]hostInfo{ + assert.ObjectsAreEqual(dc.hostCache, map[string]hostInfo{ "10.11.12.13": {version: "1.142.0.20180313-173634", entityID: "dynatraceSampleEntityId"}, "192.168.0.1": {version: "1.142.0.20180313-173634", entityID: "dynatraceSampleEntityId"}, }) diff --git a/pkg/clients/dynatrace/oneagent_connection_info.go b/pkg/clients/dynatrace/oneagent_connection_info.go index 6281b0f141..d8d48826eb 100644 --- a/pkg/clients/dynatrace/oneagent_connection_info.go +++ b/pkg/clients/dynatrace/oneagent_connection_info.go @@ -82,7 +82,7 @@ func (dtc *dynatraceClient) readResponseForOneAgentConnectionInfo(response []byt hash := fnv.New32a() // Hash write implements Write interface, but never return err, so let's ignore it - _, _ = hash.Write([]byte(fmt.Sprintf("%s-%s-%d", e.Protocol, e.Host, e.Port))) + _, _ = fmt.Fprintf(hash, "%s-%s-%d", e.Protocol, e.Host, e.Port) communicationHosts[hash.Sum32()] = e } diff --git a/pkg/clients/dynatrace/settings_kubernetes_test.go b/pkg/clients/dynatrace/settings_kubernetes_test.go index a40493906d..b4881da087 100644 --- a/pkg/clients/dynatrace/settings_kubernetes_test.go +++ b/pkg/clients/dynatrace/settings_kubernetes_test.go @@ -34,7 +34,7 @@ func TestDynatraceClient_CreateOrUpdateKubernetesSetting(t *testing.T) { require.NotNil(t, actual) require.NoError(t, err) assert.Len(t, actual, len(testObjectID)) - assert.EqualValues(t, testObjectID, actual) + assert.Equal(t, testObjectID, actual) }) t.Run(`create settings for the given monitored entity id`, func(t *testing.T) { @@ -54,7 +54,7 @@ func TestDynatraceClient_CreateOrUpdateKubernetesSetting(t *testing.T) { require.NotNil(t, actual) require.NoError(t, err) assert.Len(t, actual, len(testObjectID)) - assert.EqualValues(t, testObjectID, actual) + assert.Equal(t, testObjectID, actual) }) t.Run(`don't create settings for the given monitored entity id because no kube-system uuid is provided`, func(t *testing.T) { @@ -134,7 +134,7 @@ func TestDynatraceClient_CreateOrUpdateAppKubernetesSetting(t *testing.T) { require.NotNil(t, actual) require.NoError(t, err) assert.Len(t, actual, len(testObjectID)) - assert.EqualValues(t, testObjectID, actual) + assert.Equal(t, testObjectID, actual) }) t.Run(`don't create app settings for the given monitored entity id because of api error`, func(t *testing.T) { @@ -174,7 +174,7 @@ func TestDynatraceClient_getKubernetesSettingBody(t *testing.T) { // assert require.NotNil(t, actual) assert.Len(t, actual, 1) - assert.EqualValues(t, hierarchicalMonitoringSettingsSchemaVersion, actual[0].SchemaVersion) + assert.Equal(t, hierarchicalMonitoringSettingsSchemaVersion, actual[0].SchemaVersion) assert.IsType(t, postKubernetesSettings{}, actual[0].Value) assert.True(t, actual[0].Value.(postKubernetesSettings).Enabled) bodyJson, err := json.Marshal(actual[0]) @@ -203,7 +203,7 @@ func TestDynatraceClient_getKubernetesSettingBody(t *testing.T) { // assert require.NotNil(t, actual) assert.Len(t, actual, 1) - assert.EqualValues(t, schemaVersionV1, actual[0].SchemaVersion) + assert.Equal(t, schemaVersionV1, actual[0].SchemaVersion) assert.IsType(t, postKubernetesSettings{}, actual[0].Value) assert.True(t, actual[0].Value.(postKubernetesSettings).Enabled) bodyJson, err := json.Marshal(actual[0]) diff --git a/pkg/clients/dynatrace/settings_logmonitoring_test.go b/pkg/clients/dynatrace/settings_logmonitoring_test.go index 31965462f5..f28e57da06 100644 --- a/pkg/clients/dynatrace/settings_logmonitoring_test.go +++ b/pkg/clients/dynatrace/settings_logmonitoring_test.go @@ -38,7 +38,7 @@ func TestDynatraceClient_CreateLogMonitoringSetting(t *testing.T) { require.NotNil(t, actual) require.NoError(t, err) assert.Len(t, actual, len(testObjectID)) - assert.EqualValues(t, testObjectID, actual) + assert.Equal(t, testObjectID, actual) }) t.Run("create settings logmonitoring settings with custom rule matchers", func(t *testing.T) { // arrange @@ -72,6 +72,6 @@ func TestDynatraceClient_CreateLogMonitoringSetting(t *testing.T) { require.NotNil(t, actual) require.NoError(t, err) assert.Len(t, actual, len(testObjectID)) - assert.EqualValues(t, testObjectID, actual) + assert.Equal(t, testObjectID, actual) }) } diff --git a/pkg/clients/dynatrace/settings_test.go b/pkg/clients/dynatrace/settings_test.go index 31731170d9..14a2d1f223 100644 --- a/pkg/clients/dynatrace/settings_test.go +++ b/pkg/clients/dynatrace/settings_test.go @@ -39,7 +39,7 @@ func TestDynatraceClient_GetMonitoredEntitiesForKubeSystemUUID(t *testing.T) { require.NotNil(t, actual) require.NoError(t, err) assert.Len(t, actual, 2) - assert.EqualValues(t, expected, actual) + assert.Equal(t, expected, actual) }) t.Run("no monitored entities for this uuid exist", func(t *testing.T) { @@ -61,7 +61,7 @@ func TestDynatraceClient_GetMonitoredEntitiesForKubeSystemUUID(t *testing.T) { require.NotNil(t, actual) require.NoError(t, err) assert.Empty(t, actual) - assert.EqualValues(t, expected, actual) + assert.Equal(t, expected, actual) }) t.Run("no monitored entities found because no kube-system uuid is provided", func(t *testing.T) { diff --git a/pkg/controllers/certificates/certificate_secret_test.go b/pkg/controllers/certificates/certificate_secret_test.go index 14255822ba..976da7f1c5 100644 --- a/pkg/controllers/certificates/certificate_secret_test.go +++ b/pkg/controllers/certificates/certificate_secret_test.go @@ -150,7 +150,7 @@ func TestCreateOrUpdateIfNecessary(t *testing.T) { require.NoError(t, err) assert.NotNil(t, newSecret) - assert.EqualValues(t, certSecret.certificates.Data, newSecret.Data) + assert.Equal(t, certSecret.certificates.Data, newSecret.Data) }) t.Run(`update if secret exists`, func(t *testing.T) { fakeClient := fake.NewClient() @@ -174,7 +174,7 @@ func TestCreateOrUpdateIfNecessary(t *testing.T) { require.NoError(t, err) require.NotNil(t, newSecret) - require.EqualValues(t, certSecret.certificates.Data, newSecret.Data) + require.Equal(t, certSecret.certificates.Data, newSecret.Data) certSecret.secret = &newSecret certSecret.certificates.Data = map[string][]byte{testKey: testValue2} @@ -187,7 +187,7 @@ func TestCreateOrUpdateIfNecessary(t *testing.T) { require.NoError(t, err) assert.NotNil(t, newSecret) - assert.EqualValues(t, certSecret.certificates.Data, newSecret.Data) + assert.Equal(t, certSecret.certificates.Data, newSecret.Data) }) } diff --git a/pkg/controllers/certificates/certs_test.go b/pkg/controllers/certificates/certs_test.go index 5f50b9a512..916704c43f 100644 --- a/pkg/controllers/certificates/certs_test.go +++ b/pkg/controllers/certificates/certs_test.go @@ -31,7 +31,7 @@ func TestCertsValidation(t *testing.T) { // No changes should have been applied. assert.Equal(t, string(firstCerts.Data[RootCert]), string(newCerts.Data[RootCert])) - assert.Equal(t, "", string(firstCerts.Data[RootCertOld])) + assert.Empty(t, string(firstCerts.Data[RootCertOld])) assert.Equal(t, string(firstCerts.Data[RootKey]), string(newCerts.Data[RootKey])) assert.Equal(t, string(firstCerts.Data[ServerCert]), string(newCerts.Data[ServerCert])) assert.Equal(t, string(firstCerts.Data[ServerKey]), string(newCerts.Data[ServerKey])) @@ -46,7 +46,7 @@ func TestCertsValidation(t *testing.T) { // Server certificates should have been updated. assert.Equal(t, string(firstCerts.Data[RootCert]), string(newCerts.Data[RootCert])) - assert.Equal(t, "", string(firstCerts.Data[RootCertOld])) + assert.Empty(t, string(firstCerts.Data[RootCertOld])) assert.Equal(t, string(firstCerts.Data[RootKey]), string(newCerts.Data[RootKey])) assert.NotEqual(t, string(firstCerts.Data[ServerCert]), string(newCerts.Data[ServerCert])) assert.NotEqual(t, string(firstCerts.Data[ServerKey]), string(newCerts.Data[ServerKey])) diff --git a/pkg/controllers/csi/driver/server.go b/pkg/controllers/csi/driver/server.go index 9b71e7dc8d..67be7015ab 100644 --- a/pkg/controllers/csi/driver/server.go +++ b/pkg/controllers/csi/driver/server.go @@ -289,12 +289,12 @@ func grpcLimiter(maxGrpcRequests int32) grpc.UnaryServerInterceptor { return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { var methodName string - switch { - case info.FullMethod == "/csi.v1.Node/NodePublishVolume": + switch info.FullMethod { + case "/csi.v1.Node/NodePublishVolume": req := req.(*csi.NodePublishVolumeRequest) methodName = "NodePublishVolume" log.Info("GRPC call", "method", methodName, "volume-id", req.GetVolumeId()) - case info.FullMethod == "/csi.v1.Node/NodeUnpublishVolume": + case "/csi.v1.Node/NodeUnpublishVolume": req := req.(*csi.NodeUnpublishVolumeRequest) methodName = "NodeUnpublishVolume" log.Info("GRPC call", "method", methodName, "volume-id", req.GetVolumeId()) diff --git a/pkg/controllers/dynakube/activegate/capability/capability_test.go b/pkg/controllers/dynakube/activegate/capability/capability_test.go index bbfa135af8..7ad0dbda58 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability_test.go +++ b/pkg/controllers/dynakube/activegate/capability/capability_test.go @@ -95,7 +95,7 @@ func TestNewMultiCapability(t *testing.T) { require.NotNil(t, mc) assert.False(t, mc.Enabled()) assert.Equal(t, expectedShortName, mc.ShortName()) - assert.Equal(t, "", mc.ArgName()) + assert.Empty(t, mc.ArgName()) }) } diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go index 15999b25a6..45df16a836 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset_test.go @@ -228,7 +228,7 @@ func TestAddTemplateSpec(t *testing.T) { assert.NotEmpty(t, spec.Containers) assert.NotEmpty(t, spec.Affinity) - assert.Equal(t, len(dk.PullSecretNames()), len(spec.ImagePullSecrets)) + assert.Len(t, dk.PullSecretNames(), len(spec.ImagePullSecrets)) assert.Equal(t, dk.PullSecretNames()[0], spec.ImagePullSecrets[0].Name) }) diff --git a/pkg/controllers/dynakube/apimonitoring/reconciler_test.go b/pkg/controllers/dynakube/apimonitoring/reconciler_test.go index 5ae32efee6..7968db2bde 100644 --- a/pkg/controllers/dynakube/apimonitoring/reconciler_test.go +++ b/pkg/controllers/dynakube/apimonitoring/reconciler_test.go @@ -173,7 +173,7 @@ func TestReconcile(t *testing.T) { // assert require.NoError(t, err) - assert.Equal(t, "", actual) + assert.Empty(t, actual) }) } @@ -191,7 +191,7 @@ func TestReconcileErrors(t *testing.T) { // assert require.Error(t, err) - assert.Equal(t, "", actual) + assert.Empty(t, actual) }) t.Run("don't create setting when get entities api response is error", func(t *testing.T) { @@ -203,7 +203,7 @@ func TestReconcileErrors(t *testing.T) { // assert require.Error(t, err) - assert.Equal(t, "", actual) + assert.Empty(t, actual) }) t.Run("don't create setting when get settings api response is error", func(t *testing.T) { @@ -215,7 +215,7 @@ func TestReconcileErrors(t *testing.T) { // assert require.Error(t, err) - assert.Equal(t, "", actual) + assert.Empty(t, actual) }) t.Run("don't create setting when create settings api response is error", func(t *testing.T) { @@ -227,7 +227,7 @@ func TestReconcileErrors(t *testing.T) { // assert require.Error(t, err) - assert.Equal(t, "", actual) + assert.Empty(t, actual) }) t.Run("create settings successful in case of CreateOrUpdateKubernetesAppSetting error", func(t *testing.T) { diff --git a/pkg/controllers/dynakube/dtpullsecret/reconciler.go b/pkg/controllers/dynakube/dtpullsecret/reconciler.go index 4b579c3131..287a7ec2e6 100644 --- a/pkg/controllers/dynakube/dtpullsecret/reconciler.go +++ b/pkg/controllers/dynakube/dtpullsecret/reconciler.go @@ -39,7 +39,7 @@ func NewReconciler(clt client.Client, apiReader client.Reader, dk *dynakube.Dyna } func (r *Reconciler) Reconcile(ctx context.Context) error { - if !(r.dk.OneAgent().IsDaemonsetRequired() || r.dk.ActiveGate().IsEnabled()) { + if !r.dk.OneAgent().IsDaemonsetRequired() && !r.dk.ActiveGate().IsEnabled() { if meta.FindStatusCondition(*r.dk.Conditions(), PullSecretConditionType) == nil { return nil // no condition == nothing is there to clean up } diff --git a/pkg/controllers/dynakube/istio/serviceentry_test.go b/pkg/controllers/dynakube/istio/serviceentry_test.go index 36fdb18d76..e9ceef4bc6 100644 --- a/pkg/controllers/dynakube/istio/serviceentry_test.go +++ b/pkg/controllers/dynakube/istio/serviceentry_test.go @@ -50,7 +50,7 @@ func TestServiceEntryGeneration(t *testing.T) { Protocol: protocolHttps, }} result := buildServiceEntryFQDNs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts1) - assert.EqualValues(t, expected, result) + assert.Equal(t, expected, result) commHosts2 := []dtclient.CommunicationHost{{ Host: testHost1, @@ -58,7 +58,7 @@ func TestServiceEntryGeneration(t *testing.T) { Protocol: protocolHttps, }} result = buildServiceEntryFQDNs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts2) - assert.NotEqualValues(t, expected, result) + assert.NotEqual(t, expected, result) }) t.Run(`generate with two different hostnames and same port`, func(t *testing.T) { expected := &istiov1beta1.ServiceEntry{ @@ -89,7 +89,7 @@ func TestServiceEntryGeneration(t *testing.T) { Protocol: protocolHttps, }} result := buildServiceEntryFQDNs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts1) - assert.EqualValues(t, expected, result) + assert.Equal(t, expected, result) }) t.Run(`generate with Ip`, func(t *testing.T) { const testIp = "42.42.42.42" @@ -117,7 +117,7 @@ func TestServiceEntryGeneration(t *testing.T) { Protocol: protocolHttps, }} result := buildServiceEntryIPs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts1) - assert.EqualValues(t, expected, result) + assert.Equal(t, expected, result) commHosts2 := []dtclient.CommunicationHost{{ Host: testIp, @@ -125,7 +125,7 @@ func TestServiceEntryGeneration(t *testing.T) { Protocol: protocolHttps, }} result = buildServiceEntryIPs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts2) - assert.NotEqualValues(t, expected, result) + assert.NotEqual(t, expected, result) }) t.Run(`generate with two different Ips and same ports`, func(t *testing.T) { const ( @@ -162,7 +162,7 @@ func TestServiceEntryGeneration(t *testing.T) { Protocol: protocolHttps, }} result := buildServiceEntryIPs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts1) - assert.EqualValues(t, expected, result) + assert.Equal(t, expected, result) }) } @@ -174,7 +174,7 @@ func TestBuildServiceEntryForHostname(t *testing.T) { Protocol: protocolHttp, }} result := buildServiceEntryFQDNs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts1) - assert.EqualValues(t, expected, result) + assert.Equal(t, expected, result) commHosts2 := []dtclient.CommunicationHost{{ Host: testHost2, @@ -182,7 +182,7 @@ func TestBuildServiceEntryForHostname(t *testing.T) { Protocol: protocolHttp, }} result = buildServiceEntryFQDNs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts2) - assert.NotEqualValues(t, expected, result) + assert.NotEqual(t, expected, result) } func TestBuildServiceEntryIp(t *testing.T) { @@ -192,14 +192,14 @@ func TestBuildServiceEntryIp(t *testing.T) { Port: testPort1, }} result := buildServiceEntryIPs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts1) - assert.EqualValues(t, expected, result) + assert.Equal(t, expected, result) commHosts2 := []dtclient.CommunicationHost{{ Host: testIP2, Port: testPort2, }} result = buildServiceEntryIPs(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts2) - assert.NotEqualValues(t, expected, result) + assert.NotEqual(t, expected, result) } func buildExpectedServiceEntryForHostname(_ *testing.T) *istiov1beta1.ServiceEntry { diff --git a/pkg/controllers/dynakube/istio/virtualservice_test.go b/pkg/controllers/dynakube/istio/virtualservice_test.go index bed3e9a49a..38f44463fd 100644 --- a/pkg/controllers/dynakube/istio/virtualservice_test.go +++ b/pkg/controllers/dynakube/istio/virtualservice_test.go @@ -57,7 +57,7 @@ func TestVirtualServiceGeneration(t *testing.T) { }} result := buildVirtualService(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts) - assert.EqualValues(t, expected, result) + assert.Equal(t, expected, result) }) t.Run("generate for http connection", func(t *testing.T) { expected := &istiov1beta1.VirtualService{ @@ -87,7 +87,7 @@ func TestVirtualServiceGeneration(t *testing.T) { }} result := buildVirtualService(buildObjectMeta(testName, testNamespace, buildTestLabels()), commHosts) - assert.EqualValues(t, expected, result) + assert.Equal(t, expected, result) }) t.Run("generate for invalid protocol", func(t *testing.T) { commHosts := []dtclient.CommunicationHost{{ diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go index 86d50e066b..fbdc1e1a90 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go @@ -660,7 +660,7 @@ func TestPriorityClass(t *testing.T) { dsBuilder := builder{} priorityClassName := dsBuilder.priorityClassName() - assert.Equal(t, "", priorityClassName) + assert.Empty(t, priorityClassName) }) t.Run("returns nodeselector", func(t *testing.T) { dsBuilder := builder{ diff --git a/pkg/controllers/dynakube/token/tokens_test.go b/pkg/controllers/dynakube/token/tokens_test.go index 9d4926f92b..758baaf397 100644 --- a/pkg/controllers/dynakube/token/tokens_test.go +++ b/pkg/controllers/dynakube/token/tokens_test.go @@ -107,7 +107,7 @@ func TestTokens(t *testing.T) { assert.Len(t, tokens.ApiToken().Features, 4) assert.Empty(t, tokens.PaasToken().Features) assert.Empty(t, tokens.DataIngestToken().Features) - assert.NoError(t, err, "") + assert.NoError(t, err) }) t.Run("activegate enabled dynakube, no permissions in api token => fail", func(t *testing.T) { dk := dynakube.DynaKube{} diff --git a/pkg/controllers/dynakube/version/activegate_test.go b/pkg/controllers/dynakube/version/activegate_test.go index a90a4d9d35..45c7cb52f3 100644 --- a/pkg/controllers/dynakube/version/activegate_test.go +++ b/pkg/controllers/dynakube/version/activegate_test.go @@ -47,7 +47,7 @@ func TestActiveGateUpdater(t *testing.T) { assert.Equal(t, "activegate", updater.Name()) assert.True(t, updater.IsEnabled()) assert.Equal(t, dk.Spec.ActiveGate.Image, updater.CustomImage()) - assert.Equal(t, "", updater.CustomVersion()) + assert.Empty(t, updater.CustomVersion()) assert.False(t, updater.IsAutoUpdateEnabled()) imageInfo, err := updater.LatestImageInfo(ctx) require.NoError(t, err) diff --git a/pkg/controllers/edgeconnect/deployment/deployment_test.go b/pkg/controllers/edgeconnect/deployment/deployment_test.go index 7b1499ca21..97c431b729 100644 --- a/pkg/controllers/edgeconnect/deployment/deployment_test.go +++ b/pkg/controllers/edgeconnect/deployment/deployment_test.go @@ -64,7 +64,7 @@ func Test_buildAppLabels(t *testing.T) { t.Run("Check version label set correctly", func(t *testing.T) { labels := buildAppLabels(ec) - assert.Equal(t, "", labels.Version) + assert.Empty(t, labels.Version) }) } diff --git a/pkg/injection/codemodule/processmoduleconfig/merge_test.go b/pkg/injection/codemodule/processmoduleconfig/merge_test.go index 472ea54bc8..302a52fb5e 100644 --- a/pkg/injection/codemodule/processmoduleconfig/merge_test.go +++ b/pkg/injection/codemodule/processmoduleconfig/merge_test.go @@ -84,11 +84,11 @@ func TestConfSectionHeader(t *testing.T) { header := confSectionHeader("[general]") assert.Equal(t, "general", header) header = confSectionHeader("general") - assert.Equal(t, "", header) + assert.Empty(t, header) header = confSectionHeader("key val") - assert.Equal(t, "", header) + assert.Empty(t, header) header = confSectionHeader("") - assert.Equal(t, "", header) + assert.Empty(t, header) } func TestStoreConfFile(t *testing.T) { From 208a2e8b34f429c2f9a960b9aed8e2317925432a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 12:30:01 +0000 Subject: [PATCH 367/426] chore(deps): update module github.com/golangci/golangci-lint to v2.0.2 (main) (#4646) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 247da19400..ca61cecd3d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -89,7 +89,7 @@ jobs: uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd # v7.0.0 with: # renovate depName=github.com/golangci/golangci-lint - version: v2.0.1 + version: v2.0.2 args: --build-tags e2e --timeout 300s - name: Run deadcode id: deadcode From e772e8f8258195d3082f9e711a0fd6f2678143be Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 13:22:43 +0000 Subject: [PATCH 368/426] chore(deps): update module github.com/golangci/golangci-lint/v2 to v2.0.2 (main) (#4665) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 0e25f093ab..9c3b26a27e 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -3,7 +3,7 @@ kustomize_version=v5.6.0 #renovate depName=sigs.k8s.io/controller-tools/cmd controller_gen_version=v0.17.2 # renovate depName=github.com/golangci/golangci-lint/v2 -golang_ci_cmd_version=v2.0.1 +golang_ci_cmd_version=v2.0.2 # renovate depName=github.com/daixiang0/gci gci_version=v0.13.6 # renovate depName=golang.org/x/tools From 88666f28076a37432cbe41b0a48b8d61f80cd338 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 22:28:52 +0000 Subject: [PATCH 369/426] fix(deps): update module istio.io/api to v1.25.1 (main) (#4670) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cb65b7cad3..8298c8b5f6 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( golang.org/x/sys v0.31.0 google.golang.org/grpc v1.71.0 gopkg.in/yaml.v3 v3.0.1 - istio.io/api v1.25.0 + istio.io/api v1.25.1 istio.io/client-go v1.25.0 k8s.io/api v0.32.3 k8s.io/apiextensions-apiserver v0.32.3 diff --git a/go.sum b/go.sum index 4574d00c86..e424e9d524 100644 --- a/go.sum +++ b/go.sum @@ -379,8 +379,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -istio.io/api v1.25.0 h1:UVQNFUAz4R06NagA+QpEzLmi4sw+m+UuMgD6sIyXawA= -istio.io/api v1.25.0/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= +istio.io/api v1.25.1 h1:l3JS6Rh4bH+6ox84hRvtsJsr7gMJLsoJG2BQZGbXRyc= +istio.io/api v1.25.1/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= istio.io/client-go v1.25.0 h1:MMG8r1g+o2yEzVwi0AGSdB6EQyLEhYz8YMYQQIw8IZw= istio.io/client-go v1.25.0/go.mod h1:Y4qIjNIVCkpZMiq/e3C7tMjOm7aYUbxT6ebtmai1TRY= k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= From 5b56fbc93fbe93a0f9875d4480287d4b6cfad41d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 02:07:54 +0000 Subject: [PATCH 370/426] fix(deps): update module istio.io/client-go to v1.25.1 (main) (#4671) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8298c8b5f6..4c342165aa 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( google.golang.org/grpc v1.71.0 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.25.1 - istio.io/client-go v1.25.0 + istio.io/client-go v1.25.1 k8s.io/api v0.32.3 k8s.io/apiextensions-apiserver v0.32.3 k8s.io/apimachinery v0.32.3 diff --git a/go.sum b/go.sum index e424e9d524..25b3b2394f 100644 --- a/go.sum +++ b/go.sum @@ -381,8 +381,8 @@ gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= istio.io/api v1.25.1 h1:l3JS6Rh4bH+6ox84hRvtsJsr7gMJLsoJG2BQZGbXRyc= istio.io/api v1.25.1/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= -istio.io/client-go v1.25.0 h1:MMG8r1g+o2yEzVwi0AGSdB6EQyLEhYz8YMYQQIw8IZw= -istio.io/client-go v1.25.0/go.mod h1:Y4qIjNIVCkpZMiq/e3C7tMjOm7aYUbxT6ebtmai1TRY= +istio.io/client-go v1.25.1 h1:1Asibz5v2NBA6w4Sqa85NS7TkpEolZcPKAT5oUAXWi8= +istio.io/client-go v1.25.1/go.mod h1:Vap9OyHJMvvDegYoZczcNybS4wbPaTk+4bZcWMb8+vE= k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= From c84d5523965a16b348cd6ddad5521eee24d0c412 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Thu, 27 Mar 2025 08:27:45 +0100 Subject: [PATCH 371/426] Migrate CI to build and distribute images using buildah and podman (#4617) --- .github/actions/build-image/action.yaml | 22 +++++---- .github/actions/create-manifests/action.yaml | 8 ++-- .github/actions/upload-image/action.yaml | 2 +- .github/workflows/ci.yaml | 13 +++--- .github/workflows/release.yaml | 15 +++--- hack/build/build_image.sh | 10 ++-- hack/build/ci/create-manifest.sh | 49 +++++++++++++------- hack/build/ci/upload-docker-image.sh | 30 ------------ hack/build/ci/upload-podman-image.sh | 22 +++++++++ 9 files changed, 91 insertions(+), 80 deletions(-) delete mode 100755 hack/build/ci/upload-docker-image.sh create mode 100755 hack/build/ci/upload-podman-image.sh diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 7e3c22dd37..d279c901f1 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -1,4 +1,4 @@ -name: Build Docker Image +name: Build Image description: Builds the operator docker image inputs: platform: @@ -15,8 +15,6 @@ runs: steps: - name: Set up QEMU uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - name: Set up Golang uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: @@ -35,23 +33,27 @@ runs: run: | touch dynatrace-operator-bin-sbom.cdx.json - name: Build target - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2.13 with: - builder: ${{ steps.buildx.outputs.name }} build-args: | GO_LINKER_ARGS=${{ steps.prep.outputs.go_linker_args }} GO_BUILD_TAGS=${{ steps.prep.outputs.go_build_tags }} context: . - file: ./Dockerfile + containerfiles: | + ./Dockerfile platforms: linux/${{ inputs.platform }} - push: false - tags: operator-${{ inputs.platform }}:${{ inputs.image-tag }} + tags: ${{ inputs.image-tag }} + image: operator-${{ inputs.platform }} labels: ${{ inputs.labels }} - outputs: type=docker,dest=/tmp/operator-${{ inputs.platform }}.tar + oci: true + - name: Export image to file + shell: bash + run: | + set -x + podman save --format oci-archive -o /tmp/operator-${{ inputs.platform }}.tar operator-${{ inputs.platform }}:${{ inputs.image-tag }} - name: Upload artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: operator-${{ inputs.platform }} path: /tmp/operator-${{ inputs.platform }}.tar retention-days: 1 - diff --git a/.github/actions/create-manifests/action.yaml b/.github/actions/create-manifests/action.yaml index 96f4b90c0b..0f9ea7cebd 100644 --- a/.github/actions/create-manifests/action.yaml +++ b/.github/actions/create-manifests/action.yaml @@ -10,9 +10,11 @@ inputs: repository: description: The repository in the registry where the manifests are pushed required: true - combined: - description: Should it create a combined manifests for amd64, arm64 and ppc64le builds + platforms: + description: List of platforms required: true + annotation: + description: Annotation information about an entry in a manifest list outputs: digest: description: The digest of the created manifest @@ -26,4 +28,4 @@ runs: IMAGE: ${{ inputs.registry }}/${{ inputs.repository }} shell: bash run: | - hack/build/ci/create-manifest.sh "${IMAGE}" "${{ inputs.version }}" ${{ inputs.combined }} + hack/build/ci/create-manifest.sh "${IMAGE}" "${{ inputs.version }}" "${{ inputs.platforms }}" "${{ inputs.annotation }}" diff --git a/.github/actions/upload-image/action.yaml b/.github/actions/upload-image/action.yaml index fe75fc2283..79476ba6e8 100644 --- a/.github/actions/upload-image/action.yaml +++ b/.github/actions/upload-image/action.yaml @@ -39,4 +39,4 @@ runs: env: IMAGE: "${{ inputs.registry }}/${{ inputs.repository }}:${{ inputs.version }}" run: | - hack/build/ci/upload-docker-image.sh "${{ inputs.platform }}" "${{ env.IMAGE }}" "${{ inputs.skip-platform-suffix }}" + hack/build/ci/upload-podman-image.sh "${{ inputs.platform }}" "${{ env.IMAGE }}" "${{ inputs.skip-platform-suffix }}" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ca61cecd3d..ca7399c525 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -198,7 +198,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build image - if: matrix.platform == 'amd64' || github.ref_protected + if: matrix.platform == 'amd64' || matrix.platform == 'arm64' || github.ref_protected uses: ./.github/actions/build-image with: platform: ${{ matrix.platform }} @@ -217,13 +217,13 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_PASSWORD }} - name: Upload Image - if: matrix.platform == 'amd64' || github.ref_protected + if: matrix.platform == 'amd64' || matrix.platform == 'arm64' || github.ref_protected uses: ./.github/actions/upload-image with: platform: ${{ matrix.platform }} @@ -234,7 +234,7 @@ jobs: manifest: name: Create manifest - needs: [prepare, push] + needs: [ prepare, push ] runs-on: ubuntu-latest env: COMBINED: ${{ github.ref_protected }} @@ -243,7 +243,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} @@ -254,4 +254,5 @@ jobs: version: ${{ needs.prepare.outputs.version }} registry: ${{ needs.prepare.outputs.registry }} repository: ${{ needs.prepare.outputs.repository }} - combined: ${{ env.COMBINED }} + platforms: "amd64, arm64" + annotation: "version=${{ needs.prepare.outputs.version }}" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 481b913d7a..da59d303fb 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -94,7 +94,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry if: ${{ matrix.registry != 'amazon-ecr' }} - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 with: registry: ${{ matrix.url }} username: ${{ secrets[matrix.username] }} @@ -127,7 +127,7 @@ jobs: signing-password: ${{ secrets.COSIGN_PASSWORD }} manifest: - name: Create Docker manifests + name: Create manifests environment: Release needs: [prepare, push] runs-on: ubuntu-latest @@ -162,7 +162,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry if: ${{ matrix.registry != 'amazon-ecr' }} - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 with: registry: ${{ matrix.url }} username: ${{ secrets[matrix.username] }} @@ -185,7 +185,8 @@ jobs: version: ${{ needs.prepare.outputs.version }} registry: ${{ matrix.url }} repository: ${{ secrets[matrix.repository] }} - combined: true + platforms: "amd64, arm64, ppc64le, s390x" + annotation: "com.googleapis.cloudmarketplace.product.service.name=services/dynatrace-operator-dynatrace-marketplace-prod.cloudpartnerservices.goog" - name: Sign images for ${{matrix.registry}} uses: ./.github/actions/sign-image with: @@ -222,7 +223,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry if: ${{ matrix.registry != 'amazon-ecr' }} - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 with: registry: ${{ matrix.url }} username: ${{ secrets[matrix.username] }} @@ -266,7 +267,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 with: registry: ${{ env.SCAN_REGISTRY }} username: ${{ secrets.RHCC_USERNAME }} @@ -329,7 +330,7 @@ jobs: run: | helm registry login -u "${{ secrets.DOCKERHUB_USERNAME }}" -p "${{ secrets.DOCKERHUB_PASSWORD }}" "registry.hub.docker.com" - name: Login Docker to dockerhub - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 with: registry: docker.io username: ${{ secrets.DOCKERHUB_USERNAME }} diff --git a/hack/build/build_image.sh b/hack/build/build_image.sh index fdfe2091d4..76d9203f8b 100755 --- a/hack/build/build_image.sh +++ b/hack/build/build_image.sh @@ -23,10 +23,9 @@ out_image="${image}:${tag}" mkdir -p third_party_licenses touch dynatrace-operator-bin-sbom.cdx.json -if ! command -v docker 2>/dev/null; then - CONTAINER_CMD=podman -else - CONTAINER_CMD=docker +if ! command -v podman 2>/dev/null; then + echo "Only podman is supported to build images" + exit 1 fi OPERATOR_BUILD_PLATFORM="--platform=linux/amd64" @@ -35,7 +34,8 @@ if [ -n "${OPERATOR_DEV_BUILD_PLATFORM}" ]; then OPERATOR_BUILD_PLATFORM="--platform=${OPERATOR_DEV_BUILD_PLATFORM}" fi -${CONTAINER_CMD} build "${OPERATOR_BUILD_PLATFORM}" . -f ./Dockerfile -t "${out_image}" \ +podman build "${OPERATOR_BUILD_PLATFORM}" . -f ./Dockerfile -t "${out_image}" \ + --format oci \ --build-arg "GO_LINKER_ARGS=${go_linker_args}" \ --build-arg "GO_BUILD_TAGS=${go_build_tags}" \ --build-arg "DEBUG_TOOLS=${debug}" \ diff --git a/hack/build/ci/create-manifest.sh b/hack/build/ci/create-manifest.sh index e54518cd79..a680f9f6c2 100755 --- a/hack/build/ci/create-manifest.sh +++ b/hack/build/ci/create-manifest.sh @@ -1,33 +1,46 @@ #!/bin/bash -if [ -z "$2" ] +if [ -z "$3" ] then - echo "Usage: $0 " + echo "Usage: $0 " exit 1 fi image_name=$1 image_tag=$2 -multiplatform=$3 +raw_platforms=$3 +annotation=$4 + image="${image_name}:${image_tag}" -if [ "$multiplatform" == "true" ] +echo "This script is based on podman version 4.9.3" +echo "current version of podman is $(podman --version)" + +platforms=($(echo "${raw_platforms}" | tr "," "\n")) + +echo "Creating manifest for ${platforms[*]}" + +images=() + +for platfrom in "${platforms[@]}" +do + podman pull "${image}-${platfrom}" + images+=("${image}-${platfrom}") +done + +podman manifest create "${image}" + +if [ -z "${annotation}" ] then - supported_architectures=("amd64" "arm64" "ppc64le" "s390x") - images=() - echo "Creating manifest for ${supported_architectures[*]}" - - for architecture in "${supported_architectures[@]}" - do - docker pull "${image}-${architecture}" - images+=("${image}-${architecture}") - done - docker manifest create "${image}" "${images[@]}" + podman manifest add "${image}" "${images[@]}" else - echo "Creating manifest for the AMD image " - docker pull "${image}-amd64" - docker manifest create "${image}" "${image}-amd64" + podman manifest add --annotation "${annotation}" "${image}" "${images[@]}" fi -sha256=$(docker manifest push "${image}") +podman manifest inspect "${image}" + +podman manifest push --format oci --digestfile=digestfile.sha256 "${image}" + +sha256=$(cat digestfile.sha256) + echo "digest=${sha256}">> $GITHUB_OUTPUT diff --git a/hack/build/ci/upload-docker-image.sh b/hack/build/ci/upload-docker-image.sh deleted file mode 100755 index 5e20764c50..0000000000 --- a/hack/build/ci/upload-docker-image.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -set -x - -readonly platform="${1}" -targetImage="${2}" -readonly skip_platform_suffix="${3}" - -readonly imageTarPath="/tmp/operator-${platform}.tar" - -if [ -z "${skip_platform_suffix}" ] -then - targetImage=${targetImage}-${platform} -fi - -docker load -i "${imageTarPath}" - -# $docker load -i /tmp/alpine.tar -# Loaded image: alpine:latest -# -# we're interested in "alpine:latest", that's field=3 -srcImage=$(docker load -i "${imageTarPath}" | cut -d' ' -f3) - -docker load --input "${imageTarPath}" -docker tag "${srcImage}" "${targetImage}" -pushinfo=$(docker push "${targetImage}") - -# filtering by image-tag directly does not work currently see: https://github.com/moby/moby/issues/29901 -digest=$(echo "$pushinfo" | tail -n 1 | cut -d " " -f 3) -echo "digest=${digest}">> "$GITHUB_OUTPUT" diff --git a/hack/build/ci/upload-podman-image.sh b/hack/build/ci/upload-podman-image.sh new file mode 100755 index 0000000000..e8b302a1e4 --- /dev/null +++ b/hack/build/ci/upload-podman-image.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -x + +readonly platform="${1}" +target_image="${2}" +readonly skip_platform_suffix="${3}" + +readonly image_tar_path="/tmp/operator-${platform}.tar" + +if [ -z "${skip_platform_suffix}" ] +then + target_image=${target_image}-${platform} +fi + +src_image=$(podman load -i "${image_tar_path}" | cut -d' ' -f3) + +# we need retag it because we load it as localhost +podman tag "${src_image}" "${target_image}" + +# --format is manifest type (oci, v2s2, or v2s1) to use when pushing an image. +podman push --format oci "${target_image}" From 503f20bcd26713018fece6bbb9f4ffd142521bcd Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Thu, 27 Mar 2025 08:51:13 +0100 Subject: [PATCH 372/426] Fix Settings API server error handler of EdgeConnect client. (#4667) --- pkg/clients/edgeconnect/client.go | 4 ++-- pkg/clients/edgeconnect/environment_settings_test.go | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkg/clients/edgeconnect/client.go b/pkg/clients/edgeconnect/client.go index 700f7c3f59..811a305427 100644 --- a/pkg/clients/edgeconnect/client.go +++ b/pkg/clients/edgeconnect/client.go @@ -145,12 +145,12 @@ func (c *client) handleErrorResponseFromAPI(response []byte, statusCode int) err } func (c *client) handleErrorResponseFromSettingsApi(response []byte, statusCode int) error { - se := []SettingsApiResponse{} + se := SettingsApiResponse{} if err := json.Unmarshal(response, &se); err != nil { return errors.WithStack(errors.WithMessagef(err, "response error, can't unmarshal json response %d", statusCode)) } - return se[0].Error + return se.Error } func (c *client) getServerResponseData(response *http.Response) ([]byte, error) { diff --git a/pkg/clients/edgeconnect/environment_settings_test.go b/pkg/clients/edgeconnect/environment_settings_test.go index da9a12ce4c..a069483db9 100644 --- a/pkg/clients/edgeconnect/environment_settings_test.go +++ b/pkg/clients/edgeconnect/environment_settings_test.go @@ -164,8 +164,7 @@ func writeEnvironmentSettingsResponse(w http.ResponseWriter, status int) { } func writeSettingsApiResponse(w http.ResponseWriter, status int) { - errorResponse := []SettingsApiResponse{} - errorResponse = append(errorResponse, SettingsApiResponse{ + errorResponse := SettingsApiResponse{ Error: SettingsApiError{ Message: "test-message", ConstraintViolations: []ConstraintViolations{ @@ -178,8 +177,8 @@ func writeSettingsApiResponse(w http.ResponseWriter, status int) { Code: status, }, Code: status, - }, - ) + } + result, _ := json.Marshal(&errorResponse) w.WriteHeader(status) From d98244c7b2f60bf1a18541662d66ef6707d21ed2 Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Thu, 27 Mar 2025 14:30:25 +0100 Subject: [PATCH 373/426] Creates AG TLS certificate by default (#4651) --- doc/e2e/features.md | 25 +- hack/make/tests/e2e.mk | 14 +- pkg/api/v1beta3/dynakube/feature_flags.go | 4 +- pkg/api/v1beta4/dynakube/activegate/props.go | 1 + pkg/api/v1beta4/dynakube/feature_flags.go | 4 +- .../builder/modifiers/certs_test.go | 26 ++ .../builder/modifiers/ssl_volume_test.go | 32 ++ .../internal/tls/reconciler_test.go | 12 +- .../dynakube/extension/eec/reconciler_test.go | 352 ++++++++++++++++-- .../oneagent/daemonset/volumes_test.go | 8 +- .../bootstrapperconfig_test.go | 3 +- .../cloudnative/codemodules/codemodules.go | 170 ++++++--- test/scenarios/istio/istio_test.go | 3 +- 13 files changed, 542 insertions(+), 112 deletions(-) diff --git a/doc/e2e/features.md b/doc/e2e/features.md index 1ea5092c4b..316af9cf7c 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -213,12 +213,13 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/codemo - [func VolumesAreMountedCorrectly(sampleApp sample.App) features.Func](<#VolumesAreMountedCorrectly>) - [func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxy>) - [func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxyAndAGCert>) -- [func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxyCA>) +- [func WithProxyAndAutomaticAGCert(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxyAndAutomaticAGCert>) - [func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxyCAAndAGCert>) +- [func WithProxyCAAndAutomaticAGCert(t *testing.T, proxySpec *value.Source) features.Feature](<#WithProxyCAAndAutomaticAGCert>) -## func [ImageHasBeenDownloaded]() +## func [ImageHasBeenDownloaded]() ```go func ImageHasBeenDownloaded(dk dynakube.DynaKube) features.Func @@ -236,7 +237,7 @@ Verification that the storage in the CSI driver directory does not increase when -## func [VolumesAreMountedCorrectly]() +## func [VolumesAreMountedCorrectly]() ```go func VolumesAreMountedCorrectly(sampleApp sample.App) features.Func @@ -260,28 +261,36 @@ Connectivity in the dynatrace namespace and sample application namespace is rest -## func [WithProxyAndAGCert]() +## func [WithProxyAndAGCert]() ```go func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature ``` - + -## func [WithProxyCA]() +## func [WithProxyAndAutomaticAGCert]() ```go -func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature +func WithProxyAndAutomaticAGCert(t *testing.T, proxySpec *value.Source) features.Feature ``` -## func [WithProxyCAAndAGCert]() +## func [WithProxyCAAndAGCert]() ```go func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature ``` + + +## func [WithProxyCAAndAutomaticAGCert]() + +```go +func WithProxyCAAndAutomaticAGCert(t *testing.T, proxySpec *value.Source) features.Feature +``` + # _default ```go diff --git a/hack/make/tests/e2e.mk b/hack/make/tests/e2e.mk index 3e821cc203..01ae73f40c 100644 --- a/hack/make/tests/e2e.mk +++ b/hack/make/tests/e2e.mk @@ -64,20 +64,24 @@ test/e2e/cloudnative/codemodules: manifests/crd/helm ## Runs CloudNative codemodules-with-proxy e2e test only test/e2e/cloudnative/codemodules-with-proxy: manifests/crd/helm - go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/istio -args --feature "codemodules-with-proxy" $(SKIPCLEANUP) - -## Runs CloudNative codemodules-with-proxy-custom-ca e2e test only -test/e2e/cloudnative/codemodules-with-custom-ca: manifests/crd/helm - go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/istio -args --feature "codemodules-with-proxy-custom-ca" $(SKIPCLEANUP) + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/istio -args --feature "codemodules-with-proxy-no-certs" $(SKIPCLEANUP) ## Runs CloudNative codemodules e2e test with proxy and AG custom certificate test/e2e/cloudnative/codemodules-with-proxy-and-ag-cert: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/istio -args --feature "codemodules-with-proxy-and-ag-cert" $(SKIPCLEANUP) +## Runs CloudNative codemodules e2e test with proxy and automatically created AG certificate +test/e2e/cloudnative/codemodules-with-proxy-and-auto-ag-cert: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/istio -args --feature "codemodules-with-proxy-and-auto-ag-cert" $(SKIPCLEANUP) + ## Runs CloudNative codemodules e2e test with proxy and AG custom certificates test/e2e/cloudnative/codemodules-with-proxy-custom-ca-ag-cert: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/istio -args --feature "codemodules-with-proxy-custom-ca-ag-cert" $(SKIPCLEANUP) +## Runs CloudNative codemodules e2e test with proxy and automatically created AG certificates +test/e2e/cloudnative/codemodules-with-proxy-custom-ca-auto-ag-cert: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/istio -args --feature "codemodules-with-proxy-custom-ca-auto-ag-cert" $(SKIPCLEANUP) + ## Runs CloudNative automatic injection disabled e2e test only test/e2e/cloudnative/disabledautoinjection: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/standard -args --feature "cloudnative-disabled-auto-inject" $(SKIPCLEANUP) diff --git a/pkg/api/v1beta3/dynakube/feature_flags.go b/pkg/api/v1beta3/dynakube/feature_flags.go index eb4b17d0f0..8464fe7099 100644 --- a/pkg/api/v1beta3/dynakube/feature_flags.go +++ b/pkg/api/v1beta3/dynakube/feature_flags.go @@ -129,9 +129,9 @@ func (dk *DynaKube) FeatureNoProxy() string { return dk.getFeatureFlagRaw(AnnotationFeatureNoProxy) } -// FeatureActiveGateAutomaticTLSCertificate is a feature flag to enable automatic creation of AG TLS certificate if TrustedCAs are used. +// FeatureActiveGateAutomaticTLSCertificate is a feature flag to disable automatic creation of ActiveGate TLS certificate. func (dk *DynaKube) FeatureActiveGateAutomaticTLSCertificate() bool { - return dk.getFeatureFlagRaw(AnnotationFeatureActiveGateAutomaticTLSCertificate) == truePhrase + return dk.getFeatureFlagRaw(AnnotationFeatureActiveGateAutomaticTLSCertificate) != falsePhrase } // FeatureOneAgentMaxUnavailable is a feature flag to configure maxUnavailable on the OneAgent DaemonSets rolling upgrades. diff --git a/pkg/api/v1beta4/dynakube/activegate/props.go b/pkg/api/v1beta4/dynakube/activegate/props.go index 49fde94e5a..f8c91f62ed 100644 --- a/pkg/api/v1beta4/dynakube/activegate/props.go +++ b/pkg/api/v1beta4/dynakube/activegate/props.go @@ -99,6 +99,7 @@ func (ag *Spec) IsMetricsIngestEnabled() bool { func (ag *Spec) IsAutomaticTlsSecretEnabled() bool { return ag.automaticTLSCertificateEnabled } + func (ag *Spec) HasCaCert() bool { return ag.IsEnabled() && (ag.TlsSecretName != "" || ag.IsAutomaticTlsSecretEnabled()) } diff --git a/pkg/api/v1beta4/dynakube/feature_flags.go b/pkg/api/v1beta4/dynakube/feature_flags.go index a4556aaf80..44c5ad0609 100644 --- a/pkg/api/v1beta4/dynakube/feature_flags.go +++ b/pkg/api/v1beta4/dynakube/feature_flags.go @@ -134,9 +134,9 @@ func (dk *DynaKube) FeatureNoProxy() string { return dk.getFeatureFlagRaw(AnnotationFeatureNoProxy) } -// FeatureActiveGateAutomaticTLSCertificate is a feature flag to enable automatic creation of AG TLS certificate if TrustedCAs are used. +// FeatureActiveGateAutomaticTLSCertificate is a feature flag to disable automatic creation of ActiveGate TLS certificate. func (dk *DynaKube) FeatureActiveGateAutomaticTLSCertificate() bool { - return dk.getFeatureFlagRaw(AnnotationFeatureActiveGateAutomaticTLSCertificate) == truePhrase + return dk.getFeatureFlagRaw(AnnotationFeatureActiveGateAutomaticTLSCertificate) != falsePhrase } // FeatureOneAgentMaxUnavailable is a feature flag to configure maxUnavailable on the OneAgent DaemonSets rolling upgrades. diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs_test.go index a21e0db748..1d1e7e68d9 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/certs_test.go @@ -18,9 +18,14 @@ func setCertUsage(dk *dynakube.DynaKube, isUsed bool) { } } +func disableAutomaticAGCertificate(dk *dynakube.DynaKube) { + dk.Annotations[dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate] = "false" +} + func TestCertEnabled(t *testing.T) { t.Run("true", func(t *testing.T) { dk := getBaseDynakube() + disableAutomaticAGCertificate(&dk) enableKubeMonCapability(&dk) setCertUsage(&dk, true) @@ -31,6 +36,7 @@ func TestCertEnabled(t *testing.T) { t.Run("false", func(t *testing.T) { dk := getBaseDynakube() + disableAutomaticAGCertificate(&dk) enableKubeMonCapability(&dk) setCertUsage(&dk, false) @@ -38,6 +44,26 @@ func TestCertEnabled(t *testing.T) { assert.False(t, mod.Enabled()) }) + + t.Run("true, AG cert enabled", func(t *testing.T) { + dk := getBaseDynakube() + enableKubeMonCapability(&dk) + setCertUsage(&dk, true) + + mod := NewCertificatesModifier(dk) + + assert.True(t, mod.Enabled()) + }) + + t.Run("false, AG cert enabled", func(t *testing.T) { + dk := getBaseDynakube() + enableKubeMonCapability(&dk) + setCertUsage(&dk, false) + + mod := NewCertificatesModifier(dk) + + assert.True(t, mod.Enabled()) + }) } func TestCertModify(t *testing.T) { diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/ssl_volume_test.go b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/ssl_volume_test.go index af2537e2fc..0b53d7bdef 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/ssl_volume_test.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/builder/modifiers/ssl_volume_test.go @@ -10,6 +10,7 @@ import ( func TestSSLVolumeEnabled(t *testing.T) { t.Run("true - TlsSecretName", func(t *testing.T) { dk := getBaseDynakube() + disableAutomaticAGCertificate(&dk) enableKubeMonCapability(&dk) dk.Spec.ActiveGate.TlsSecretName = testTlsSecretName @@ -20,6 +21,7 @@ func TestSSLVolumeEnabled(t *testing.T) { t.Run("true - TrustedCAs", func(t *testing.T) { dk := getBaseDynakube() + disableAutomaticAGCertificate(&dk) enableKubeMonCapability(&dk) dk.Spec.TrustedCAs = testTlsSecretName @@ -30,12 +32,42 @@ func TestSSLVolumeEnabled(t *testing.T) { t.Run("false", func(t *testing.T) { dk := getBaseDynakube() + disableAutomaticAGCertificate(&dk) enableKubeMonCapability(&dk) mod := NewSSLVolumeModifier(dk) assert.False(t, mod.Enabled()) }) + + t.Run("true - TlsSecretName, AG cert enabled", func(t *testing.T) { + dk := getBaseDynakube() + enableKubeMonCapability(&dk) + dk.Spec.ActiveGate.TlsSecretName = testTlsSecretName + + mod := NewSSLVolumeModifier(dk) + + assert.True(t, mod.Enabled()) + }) + + t.Run("true - TrustedCAs, AG cert enabled", func(t *testing.T) { + dk := getBaseDynakube() + enableKubeMonCapability(&dk) + dk.Spec.TrustedCAs = testTlsSecretName + + mod := NewSSLVolumeModifier(dk) + + assert.True(t, mod.Enabled()) + }) + + t.Run("false, AG cert enabled", func(t *testing.T) { + dk := getBaseDynakube() + enableKubeMonCapability(&dk) + + mod := NewSSLVolumeModifier(dk) + + assert.True(t, mod.Enabled()) + }) } func TestSSLVolumeModify(t *testing.T) { diff --git a/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go b/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go index 68412c66ad..c81a7d6afd 100644 --- a/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go +++ b/pkg/controllers/dynakube/activegate/internal/tls/reconciler_test.go @@ -27,9 +27,6 @@ func TestReconciler_Reconcile(t *testing.T) { t.Run(`ActiveGate disabled`, func(t *testing.T) { dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", - }, Namespace: testNamespace, Name: testDynakubeName, }, @@ -49,9 +46,6 @@ func TestReconciler_Reconcile(t *testing.T) { t.Run(`custom ActiveGate TLS secret exists`, func(t *testing.T) { dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", - }, Namespace: testNamespace, Name: testDynakubeName, }, @@ -81,6 +75,9 @@ func TestReconciler_Reconcile(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Namespace: testNamespace, Name: testDynakubeName, + Annotations: map[string]string{ + dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "false", + }, }, Spec: dynakube.DynaKubeSpec{ ActiveGate: activegate.Spec{ @@ -105,9 +102,6 @@ func TestReconciler_Reconcile(t *testing.T) { t.Run(`secret created`, func(t *testing.T) { dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", - }, Namespace: testNamespace, Name: testDynakubeName, }, diff --git a/pkg/controllers/dynakube/extension/eec/reconciler_test.go b/pkg/controllers/dynakube/extension/eec/reconciler_test.go index 7052e708d8..286c022362 100644 --- a/pkg/controllers/dynakube/extension/eec/reconciler_test.go +++ b/pkg/controllers/dynakube/extension/eec/reconciler_test.go @@ -106,6 +106,10 @@ func getTLSSecret(name string, namespace string, crt string, key string) corev1. } } +func disableAutomaticAGCertificate(dk *dynakube.DynaKube) { + dk.Annotations[dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate] = "false" +} + func TestConditions(t *testing.T) { t.Run("no kubeSystemUUID", func(t *testing.T) { dk := getTestDynakube() @@ -307,6 +311,41 @@ func TestEnvironmentVariables(t *testing.T) { } func TestVolumeMounts(t *testing.T) { + t.Run("volume mounts, AG cert disabled", func(t *testing.T) { + dk := getTestDynakube() + disableAutomaticAGCertificate(dk) + statefulSet := getStatefulset(t, dk) + + expectedVolumeMounts := []corev1.VolumeMount{ + { + Name: consts.ExtensionsTokensVolumeName, + MountPath: eecTokenMountPath, + ReadOnly: true, + }, + { + Name: logVolumeName, + MountPath: logMountPath, + ReadOnly: false, + }, + { + Name: runtimeVolumeName, + MountPath: runtimeMountPath, + ReadOnly: false, + }, + { + Name: configurationVolumeName, + MountPath: configurationMountPath, + ReadOnly: false, + }, + { + Name: httpsCertVolumeName, + MountPath: httpsCertMountPath, + ReadOnly: true, + }, + } + assert.Equal(t, expectedVolumeMounts, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts) + }) + t.Run("volume mounts", func(t *testing.T) { statefulSet := getStatefulset(t, getTestDynakube()) @@ -336,12 +375,18 @@ func TestVolumeMounts(t *testing.T) { MountPath: httpsCertMountPath, ReadOnly: true, }, + { + Name: activeGateTrustedCertVolumeName, + MountPath: activeGateTrustedCertMountPath, + ReadOnly: true, + }, } assert.Equal(t, expectedVolumeMounts, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts) }) - t.Run("volume mounts with PVC", func(t *testing.T) { + t.Run("volume mounts with PVC, AG cert disabled", func(t *testing.T) { dk := getTestDynakube() + disableAutomaticAGCertificate(dk) dk.Spec.Templates.ExtensionExecutionController.PersistentVolumeClaim = &corev1.PersistentVolumeClaimSpec{ Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ @@ -408,6 +453,48 @@ func TestVolumeMounts(t *testing.T) { assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) }) + t.Run("volume mounts with custom configuration, AG cert disabled", func(t *testing.T) { + dk := getTestDynakube() + disableAutomaticAGCertificate(dk) + dk.Spec.Templates.ExtensionExecutionController.CustomConfig = testCustomConfigConfigMapName + + statefulSet := getStatefulset(t, dk) + + expectedVolumeMounts := []corev1.VolumeMount{ + { + Name: consts.ExtensionsTokensVolumeName, + MountPath: eecTokenMountPath, + ReadOnly: true, + }, + { + Name: logVolumeName, + MountPath: logMountPath, + ReadOnly: false, + }, + { + Name: runtimeVolumeName, + MountPath: runtimeMountPath, + ReadOnly: false, + }, + { + Name: configurationVolumeName, + MountPath: configurationMountPath, + ReadOnly: false, + }, + { + Name: httpsCertVolumeName, + MountPath: httpsCertMountPath, + ReadOnly: true, + }, + { + Name: customConfigVolumeName, + MountPath: customConfigMountPath, + ReadOnly: true, + }, + } + assert.Equal(t, expectedVolumeMounts, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts) + }) + t.Run("volume mounts with custom configuration", func(t *testing.T) { dk := getTestDynakube() dk.Spec.Templates.ExtensionExecutionController.CustomConfig = testCustomConfigConfigMapName @@ -445,6 +532,11 @@ func TestVolumeMounts(t *testing.T) { MountPath: customConfigMountPath, ReadOnly: true, }, + { + Name: activeGateTrustedCertVolumeName, + MountPath: activeGateTrustedCertMountPath, + ReadOnly: true, + }, } assert.Equal(t, expectedVolumeMounts, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts) }) @@ -756,6 +848,55 @@ func TestUpdateStrategy(t *testing.T) { } func TestVolumes(t *testing.T) { + t.Run("volumes without PVC, AG cert disabled", func(t *testing.T) { + dk := getTestDynakube() + disableAutomaticAGCertificate(dk) + dk.Spec.Templates.ExtensionExecutionController.UseEphemeralVolume = true + + statefulSet := getStatefulset(t, dk) + + mode := int32(420) + expectedVolumes := []corev1.Volume{ + { + Name: consts.ExtensionsTokensVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTokenSecretName(), + DefaultMode: &mode, + }, + }, + }, + { + Name: logVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + { + Name: configurationVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + { + Name: httpsCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTLSSecretName(), + }, + }, + }, + { + Name: runtimeVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + } + + assert.Equal(t, expectedVolumes, statefulSet.Spec.Template.Spec.Volumes) + }) + t.Run("volumes without PVC", func(t *testing.T) { dk := getTestDynakube() dk.Spec.Templates.ExtensionExecutionController.UseEphemeralVolume = true @@ -799,6 +940,70 @@ func TestVolumes(t *testing.T) { EmptyDir: &corev1.EmptyDirVolumeSource{}, }, }, + { + Name: activeGateTrustedCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + DefaultMode: &mode, + SecretName: dk.ActiveGate().GetTLSSecretName(), + Items: []corev1.KeyToPath{ + { + Key: activeGateTrustedCertSecretKeyPath, + Path: activeGateTrustedCertSecretKeyPath, + }, + }, + }, + }, + }, + } + + assert.Equal(t, expectedVolumes, statefulSet.Spec.Template.Spec.Volumes) + }) + + t.Run("volumes with PVC, AG cert disabled", func(t *testing.T) { + dk := getTestDynakube() + disableAutomaticAGCertificate(dk) + dk.Spec.Templates.ExtensionExecutionController.PersistentVolumeClaim = &corev1.PersistentVolumeClaimSpec{ + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + } + + statefulSet := getStatefulset(t, dk) + + mode := int32(420) + expectedVolumes := []corev1.Volume{ + { + Name: consts.ExtensionsTokensVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTokenSecretName(), + DefaultMode: &mode, + }, + }, + }, + { + Name: logVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + { + Name: configurationVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + { + Name: httpsCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTLSSecretName(), + }, + }, + }, } assert.Equal(t, expectedVolumes, statefulSet.Spec.Template.Spec.Volumes) @@ -847,13 +1052,29 @@ func TestVolumes(t *testing.T) { }, }, }, + { + Name: activeGateTrustedCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + DefaultMode: &mode, + SecretName: dk.ActiveGate().GetTLSSecretName(), + Items: []corev1.KeyToPath{ + { + Key: activeGateTrustedCertSecretKeyPath, + Path: activeGateTrustedCertSecretKeyPath, + }, + }, + }, + }, + }, } assert.Equal(t, expectedVolumes, statefulSet.Spec.Template.Spec.Volumes) }) - t.Run("volumes without PVC and with custom configuration", func(t *testing.T) { + t.Run("volumes without PVC and with custom configuration, AG cert disabled", func(t *testing.T) { dk := getTestDynakube() + disableAutomaticAGCertificate(dk) dk.Spec.Templates.ExtensionExecutionController.UseEphemeralVolume = true dk.Spec.Templates.ExtensionExecutionController.CustomConfig = testCustomConfigConfigMapName @@ -896,7 +1117,65 @@ func TestVolumes(t *testing.T) { EmptyDir: &corev1.EmptyDirVolumeSource{}, }, }, + { + Name: customConfigVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: testCustomConfigConfigMapName, + }, + }, + }, + }, + } + assert.Equal(t, expectedVolumes, statefulSet.Spec.Template.Spec.Volumes) + }) + + t.Run("volumes without PVC and with custom configuration", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.Templates.ExtensionExecutionController.UseEphemeralVolume = true + dk.Spec.Templates.ExtensionExecutionController.CustomConfig = testCustomConfigConfigMapName + + statefulSet := getStatefulset(t, dk) + + mode := int32(420) + expectedVolumes := []corev1.Volume{ + { + Name: consts.ExtensionsTokensVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTokenSecretName(), + DefaultMode: &mode, + }, + }, + }, + { + Name: logVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + { + Name: configurationVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + { + Name: httpsCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.ExtensionsTLSSecretName(), + }, + }, + }, + { + Name: runtimeVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, { Name: customConfigVolumeName, VolumeSource: corev1.VolumeSource{ @@ -907,10 +1186,26 @@ func TestVolumes(t *testing.T) { }, }, }, + { + Name: activeGateTrustedCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + DefaultMode: &mode, + SecretName: dk.ActiveGate().GetTLSSecretName(), + Items: []corev1.KeyToPath{ + { + Key: activeGateTrustedCertSecretKeyPath, + Path: activeGateTrustedCertSecretKeyPath, + }, + }, + }, + }, + }, } assert.Equal(t, expectedVolumes, statefulSet.Spec.Template.Spec.Volumes) }) + t.Run("Custom EEC tls certificate is mounted to EEC", func(t *testing.T) { dk := getTestDynakube() dk.Spec.Templates.ExtensionExecutionController.TlsRefName = "custom-tls" @@ -970,6 +1265,21 @@ func TestActiveGateVolumes(t *testing.T) { }, }, } + expectedAutoAgCertVolume := corev1.Volume{ + Name: activeGateTrustedCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + DefaultMode: &defaultMode, + SecretName: testDynakubeName + activegate.TlsSecretSuffix, + Items: []corev1.KeyToPath{ + { + Key: activeGateTrustedCertSecretKeyPath, + Path: activeGateTrustedCertSecretKeyPath, + }, + }, + }, + }, + } t.Run("volumes with custom ActiveGate tls certificate", func(t *testing.T) { dk := getTestDynakube() @@ -984,8 +1294,21 @@ func TestActiveGateVolumes(t *testing.T) { require.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) }) + t.Run("volumes with automatically created ActiveGate tls certificate", func(t *testing.T) { + dk := getTestDynakube() + statefulSet := getStatefulset(t, dk) + + require.NotEmpty(t, statefulSet.Spec.Template.Spec.Containers) + require.NotEmpty(t, statefulSet.Spec.Template.Spec.Volumes) + + require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, expectedEnvVar) + require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + require.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedAutoAgCertVolume) + }) + t.Run("volumes without custom ActiveGate tls certificate", func(t *testing.T) { dk := getTestDynakube() + disableAutomaticAGCertificate(dk) statefulSet := getStatefulset(t, dk) require.NotEmpty(t, statefulSet.Spec.Template.Spec.Containers) @@ -996,8 +1319,9 @@ func TestActiveGateVolumes(t *testing.T) { require.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) }) - t.Run("volumes with TrustedCAs certificates", func(t *testing.T) { + t.Run("volumes with TrustedCAs certificates, AG cert disabled", func(t *testing.T) { dk := getTestDynakube() + disableAutomaticAGCertificate(dk) dk.Spec.TrustedCAs = "custom-tls" statefulSet := getStatefulset(t, dk) @@ -1009,27 +1333,9 @@ func TestActiveGateVolumes(t *testing.T) { require.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) }) - t.Run("volumes with automatically created ActiveGate tls certificate", func(t *testing.T) { + t.Run("volumes with TrustedCAs certificates and automatically created ActiveGate tls certificate", func(t *testing.T) { dk := getTestDynakube() - dk.Annotations[dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate] = "true" dk.Spec.TrustedCAs = "custom-tls" - - expectedVolume := corev1.Volume{ - Name: activeGateTrustedCertVolumeName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - DefaultMode: &defaultMode, - SecretName: dk.ActiveGate().GetTLSSecretName(), - Items: []corev1.KeyToPath{ - { - Key: activeGateTrustedCertSecretKeyPath, - Path: activeGateTrustedCertSecretKeyPath, - }, - }, - }, - }, - } - statefulSet := getStatefulset(t, dk) require.NotEmpty(t, statefulSet.Spec.Template.Spec.Containers) @@ -1037,6 +1343,6 @@ func TestActiveGateVolumes(t *testing.T) { require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, expectedEnvVar) require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) - require.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) + require.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedAutoAgCertVolume) }) } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go index e268b4ba65..efe4b3aa34 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go @@ -86,13 +86,10 @@ func TestPrepareVolumes(t *testing.T) { volumes := prepareVolumes(dk) assert.Contains(t, volumes, getActiveGateCaCertVolume(dk)) }) - t.Run(`has automatically created tls volume`, func(t *testing.T) { + t.Run(`has automatically created AG tls volume`, func(t *testing.T) { dk := &dynakube.DynaKube{ ObjectMeta: corev1.ObjectMeta{ Name: "dynakube", - Annotations: map[string]string{ - dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", - }, }, Spec: dynakube.DynaKubeSpec{ ActiveGate: activegate.Spec{ @@ -214,9 +211,6 @@ func TestPrepareVolumeMounts(t *testing.T) { dk := &dynakube.DynaKube{ ObjectMeta: corev1.ObjectMeta{ Name: "dynakube", - Annotations: map[string]string{ - dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", - }, }, Spec: dynakube.DynaKubeSpec{ OneAgent: oneagent.Spec{ diff --git a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go index 3e3574fa47..438d9b6ce0 100644 --- a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go +++ b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go @@ -196,7 +196,8 @@ func TestGenerateForDynakube(t *testing.T) { Name: testDynakube, Namespace: testNamespaceDynatrace, Annotations: map[string]string{ - dynakube.AnnotationFeatureOneAgentInitialConnectRetry: "6500", + dynakube.AnnotationFeatureOneAgentInitialConnectRetry: "6500", + dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "false", }, }, Spec: dynakube.DynaKubeSpec{ diff --git a/test/features/cloudnative/codemodules/codemodules.go b/test/features/cloudnative/codemodules/codemodules.go index cf241443a1..1d652c1926 100644 --- a/test/features/cloudnative/codemodules/codemodules.go +++ b/test/features/cloudnative/codemodules/codemodules.go @@ -135,7 +135,7 @@ const ( // the local cluster. Sample application is installed. The test checks if DT_PROXY environment // variable is defined in the *dynakubeComponents-oneagent* container and the *application container*. func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature { - builder := features.New("codemodules-with-proxy") + builder := features.New("codemodules-with-proxy-no-certs") secretConfigs := tenant.GetMultiTenantSecret(t) require.Len(t, secretConfigs, 2) @@ -146,6 +146,9 @@ func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature { dynakubeComponents.WithActiveGate(), dynakubeComponents.WithIstioIntegration(), dynakubeComponents.WithProxy(proxySpec), + dynakubeComponents.WithAnnotations(map[string]string{ + dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "false", + }), ) sampleNamespace := *namespace.New("codemodules-sample-with-proxy", namespace.WithIstio()) @@ -188,23 +191,31 @@ func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature { return builder.Feature() } -func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature { - const configMapName = "proxy-ca" - builder := features.New("codemodules-with-proxy-custom-ca") +func getAgTlsSecret(secret *corev1.Secret) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + err := envConfig.Client().Resources().Get(ctx, secret.Name, secret.Namespace, secret) + require.NoError(t, err) + + _, ok := secret.Data[dynakube.TLSCertKey] + require.True(t, ok) + + return ctx + } +} + +func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature { + builder := features.New("codemodules-with-proxy-and-ag-cert") secretConfigs := tenant.GetMultiTenantSecret(t) require.Len(t, secretConfigs, 2) cloudNativeDynakube := *dynakubeComponents.New( - dynakubeComponents.WithName("codemodules-with-proxy-custom-ca"), + dynakubeComponents.WithName("codemodules-with-proxy-and-ag-cert"), dynakubeComponents.WithApiUrl(secretConfigs[0].ApiUrl), dynakubeComponents.WithCloudNativeSpec(codeModulesCloudNativeSpec(t)), - dynakubeComponents.WithCustomCAs(configMapName), dynakubeComponents.WithActiveGate(), + dynakubeComponents.WithActiveGateTLSSecret(agSecretName), dynakubeComponents.WithIstioIntegration(), dynakubeComponents.WithProxy(proxySpec), - dynakubeComponents.WithAnnotations(map[string]string{ - dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate: "true", - }), ) sampleNamespace := *namespace.New("codemodules-sample-with-proxy-custom-ca", namespace.WithIstio()) @@ -215,14 +226,20 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature { builder.Assess("create sample namespace", sampleApp.InstallNamespace()) - // Add customCA config map - trustedCa, _ := os.ReadFile(path.Join(project.TestDataDir(), proxyCertificate)) - caConfigMap := configmap.New(configMapName, cloudNativeDynakube.Namespace, - map[string]string{dynakube.TrustedCAKey: string(trustedCa)}) - builder.Assess("create trusted CAs config map", configmap.Create(caConfigMap)) + // Add ActiveGate TLS secret + // public certificate for OneAgents + agCrt, _ := os.ReadFile(path.Join(project.TestDataDir(), agCertificate)) + // public certificate and private key for ActiveGate server + agP12, _ := os.ReadFile(path.Join(project.TestDataDir(), agCertificateAndPrivateKey)) + agSecret := secret.New(agSecretName, cloudNativeDynakube.Namespace, + map[string][]byte{ + dynakube.TLSCertKey: agCrt, + agCertificateAndPrivateKeyField: agP12, + }) + builder.Assess("create AG TLS secret", secret.Create(agSecret)) // Register proxy create and delete - proxy.SetupProxyWithCustomCAandTeardown(t, builder, cloudNativeDynakube) + proxy.SetupProxyWithTeardown(t, builder, cloudNativeDynakube) proxy.CutOffDynatraceNamespace(builder, proxySpec) proxy.IsDynatraceNamespaceCutOff(builder, cloudNativeDynakube) @@ -238,6 +255,60 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature { builder.Assess("codemodules have been downloaded", ImageHasBeenDownloaded(cloudNativeDynakube)) + cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agCrt }, nil) + cloudnative.AssessOneAgentContainer(builder, func() []byte { return agCrt }, nil) + cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, nil) + + // Register sample, dynakubeComponents and operator uninstall + builder.Teardown(sampleApp.Uninstall()) + dynakubeComponents.Delete(builder, helpers.LevelTeardown, cloudNativeDynakube) + + builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(cloudNativeDynakube.Name, cloudNativeDynakube.Namespace)) + + return builder.Feature() +} + +func WithProxyAndAutomaticAGCert(t *testing.T, proxySpec *value.Source) features.Feature { + builder := features.New("codemodules-with-proxy-and-auto-ag-cert") + secretConfigs := tenant.GetMultiTenantSecret(t) + require.Len(t, secretConfigs, 2) + + cloudNativeDynakube := *dynakubeComponents.New( + dynakubeComponents.WithName("codemodules-with-proxy"), + dynakubeComponents.WithApiUrl(secretConfigs[0].ApiUrl), + dynakubeComponents.WithCloudNativeSpec(codeModulesCloudNativeSpec(t)), + dynakubeComponents.WithActiveGate(), + dynakubeComponents.WithIstioIntegration(), + dynakubeComponents.WithProxy(proxySpec), + ) + + sampleNamespace := *namespace.New("codemodules-sample-with-proxy", namespace.WithIstio()) + sampleApp := sample.NewApp(t, &cloudNativeDynakube, + sample.AsDeployment(), + sample.WithNamespace(sampleNamespace), + ) + + builder.Assess("create sample namespace", sampleApp.InstallNamespace()) + + // Register proxy create and delete + proxy.SetupProxyWithTeardown(t, builder, cloudNativeDynakube) + proxy.CutOffDynatraceNamespace(builder, proxySpec) + proxy.IsDynatraceNamespaceCutOff(builder, cloudNativeDynakube) + + // Register dynakubeComponents install + dynakubeComponents.Install(builder, helpers.LevelAssess, &secretConfigs[0], cloudNativeDynakube) + + // Register sample app install + builder.Assess("install sample app", sampleApp.Install()) + + // Register actual test + cloudnative.AssessSampleInitContainers(builder, sampleApp) + istio.AssessIstio(builder, cloudNativeDynakube, *sampleApp) + builder.Assess("codemodules have been downloaded", ImageHasBeenDownloaded(cloudNativeDynakube)) + + builder.Assess("check env variables of oneagent pods", checkOneAgentEnvVars(cloudNativeDynakube)) + builder.Assess("check proxy settings in ruxitagentproc.conf", proxy.CheckRuxitAgentProcFileHasProxySetting(*sampleApp, proxySpec)) + agTlsSecret := corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: cloudNativeDynakube.ActiveGate().GetTLSSecretName(), @@ -246,41 +317,29 @@ func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature { } builder.Assess("read AG TLS secret", getAgTlsSecret(&agTlsSecret)) - cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agTlsSecret.Data[dynakube.TLSCertKey] }, trustedCa) - cloudnative.AssessOneAgentContainer(builder, func() []byte { return agTlsSecret.Data[dynakube.TLSCertKey] }, trustedCa) - cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, trustedCa) + cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agTlsSecret.Data[dynakube.TLSCertKey] }, nil) + cloudnative.AssessOneAgentContainer(builder, func() []byte { return agTlsSecret.Data[dynakube.TLSCertKey] }, nil) + cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, nil) // Register sample, dynakubeComponents and operator uninstall builder.Teardown(sampleApp.Uninstall()) dynakubeComponents.Delete(builder, helpers.LevelTeardown, cloudNativeDynakube) builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(cloudNativeDynakube.Name, cloudNativeDynakube.Namespace)) - builder.WithTeardown("deleted trusted CAs config map", configmap.Delete(caConfigMap)) return builder.Feature() } -func getAgTlsSecret(secret *corev1.Secret) features.Func { - return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { - err := envConfig.Client().Resources().Get(ctx, secret.Name, secret.Namespace, secret) - require.NoError(t, err) - - _, ok := secret.Data[dynakube.TLSCertKey] - require.True(t, ok) - - return ctx - } -} - -func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature { - builder := features.New("codemodules-with-proxy-and-ag-cert") +func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature { + builder := features.New("codemodules-with-proxy-custom-ca-ag-cert") secretConfigs := tenant.GetMultiTenantSecret(t) require.Len(t, secretConfigs, 2) cloudNativeDynakube := *dynakubeComponents.New( - dynakubeComponents.WithName("codemodules-with-proxy-and-ag-cert"), + dynakubeComponents.WithName("codemodules-with-proxy-custom-ca-ag-cert"), dynakubeComponents.WithApiUrl(secretConfigs[0].ApiUrl), dynakubeComponents.WithCloudNativeSpec(codeModulesCloudNativeSpec(t)), + dynakubeComponents.WithCustomCAs(configMapName), dynakubeComponents.WithActiveGate(), dynakubeComponents.WithActiveGateTLSSecret(agSecretName), dynakubeComponents.WithIstioIntegration(), @@ -307,8 +366,14 @@ func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature }) builder.Assess("create AG TLS secret", secret.Create(agSecret)) + // Add customCA config map + trustedCa, _ := os.ReadFile(path.Join(project.TestDataDir(), proxyCertificate)) + caConfigMap := configmap.New(configMapName, cloudNativeDynakube.Namespace, + map[string]string{dynakube.TrustedCAKey: string(trustedCa)}) + builder.Assess("create trusted CAs config map", configmap.Create(caConfigMap)) + // Register proxy create and delete - proxy.SetupProxyWithTeardown(t, builder, cloudNativeDynakube) + proxy.SetupProxyWithCustomCAandTeardown(t, builder, cloudNativeDynakube) proxy.CutOffDynatraceNamespace(builder, proxySpec) proxy.IsDynatraceNamespaceCutOff(builder, cloudNativeDynakube) @@ -324,21 +389,22 @@ func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature builder.Assess("codemodules have been downloaded", ImageHasBeenDownloaded(cloudNativeDynakube)) - cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agCrt }, nil) - cloudnative.AssessOneAgentContainer(builder, func() []byte { return agCrt }, nil) - cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, nil) + cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agCrt }, trustedCa) + cloudnative.AssessOneAgentContainer(builder, func() []byte { return agCrt }, trustedCa) + cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, trustedCa) // Register sample, dynakubeComponents and operator uninstall builder.Teardown(sampleApp.Uninstall()) dynakubeComponents.Delete(builder, helpers.LevelTeardown, cloudNativeDynakube) builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(cloudNativeDynakube.Name, cloudNativeDynakube.Namespace)) + builder.WithTeardown("deleted trusted CAs config map", configmap.Delete(caConfigMap)) return builder.Feature() } -func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature { - builder := features.New("codemodules-with-proxy-custom-ca-ag-cert") +func WithProxyCAAndAutomaticAGCert(t *testing.T, proxySpec *value.Source) features.Feature { + builder := features.New("codemodules-with-proxy-custom-ca-auto-ag-cert") secretConfigs := tenant.GetMultiTenantSecret(t) require.Len(t, secretConfigs, 2) @@ -361,18 +427,6 @@ func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Featur builder.Assess("create sample namespace", sampleApp.InstallNamespace()) - // Add ActiveGate TLS secret - // public certificate for OneAgents - agCrt, _ := os.ReadFile(path.Join(project.TestDataDir(), agCertificate)) - // public certificate and private key for ActiveGate server - agP12, _ := os.ReadFile(path.Join(project.TestDataDir(), agCertificateAndPrivateKey)) - agSecret := secret.New(agSecretName, cloudNativeDynakube.Namespace, - map[string][]byte{ - dynakube.TLSCertKey: agCrt, - agCertificateAndPrivateKeyField: agP12, - }) - builder.Assess("create AG TLS secret", secret.Create(agSecret)) - // Add customCA config map trustedCa, _ := os.ReadFile(path.Join(project.TestDataDir(), proxyCertificate)) caConfigMap := configmap.New(configMapName, cloudNativeDynakube.Namespace, @@ -396,8 +450,16 @@ func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Featur builder.Assess("codemodules have been downloaded", ImageHasBeenDownloaded(cloudNativeDynakube)) - cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agCrt }, trustedCa) - cloudnative.AssessOneAgentContainer(builder, func() []byte { return agCrt }, trustedCa) + agTlsSecret := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: cloudNativeDynakube.ActiveGate().GetTLSSecretName(), + Namespace: cloudNativeDynakube.Namespace, + }, + } + builder.Assess("read AG TLS secret", getAgTlsSecret(&agTlsSecret)) + + cloudnative.AssessSampleContainer(builder, sampleApp, func() []byte { return agTlsSecret.Data[dynakube.TLSCertKey] }, trustedCa) + cloudnative.AssessOneAgentContainer(builder, func() []byte { return agTlsSecret.Data[dynakube.TLSCertKey] }, trustedCa) cloudnative.AssessActiveGateContainer(builder, &cloudNativeDynakube, trustedCa) // Register sample, dynakubeComponents and operator uninstall diff --git a/test/scenarios/istio/istio_test.go b/test/scenarios/istio/istio_test.go index 26b697266e..a6ac20b451 100644 --- a/test/scenarios/istio/istio_test.go +++ b/test/scenarios/istio/istio_test.go @@ -53,9 +53,10 @@ func TestIstio(t *testing.T) { activegate.Feature(t, proxy.ProxySpec), cloudnativeDefault.Feature(t, true), codemodules.WithProxy(t, proxy.ProxySpec), - codemodules.WithProxyCA(t, proxy.HttpsProxySpec), codemodules.WithProxyAndAGCert(t, proxy.ProxySpec), + codemodules.WithProxyAndAutomaticAGCert(t, proxy.ProxySpec), codemodules.WithProxyCAAndAGCert(t, proxy.HttpsProxySpec), + codemodules.WithProxyCAAndAutomaticAGCert(t, proxy.HttpsProxySpec), } testEnv.Test(t, scenarios.FilterFeatures(*cfg, feats)...) From 46a61e4be1659fe043ed7ed835ff91ecdeb06acd Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Thu, 27 Mar 2025 15:22:56 +0100 Subject: [PATCH 374/426] Configure host volumes for host agent without CSI driver (#4632) --- doc/e2e/features.md | 24 ++- hack/make/tests/e2e.mk | 8 + pkg/api/v1beta4/dynakube/oneagent/props.go | 26 +++- .../v1beta4/dynakube/oneagent/props_test.go | 6 +- pkg/api/validation/dynakube/oneagent.go | 4 +- pkg/api/validation/dynakube/oneagent_test.go | 2 +- pkg/controllers/csi/metadata/correctness.go | 4 +- .../csi/provisioner/cleanup/hostmounts.go | 2 +- pkg/controllers/csi/provisioner/controller.go | 2 +- .../dynakube/oneagent/daemonset/daemonset.go | 6 +- .../dynakube/oneagent/daemonset/env_vars.go | 2 +- .../dynakube/oneagent/daemonset/volumes.go | 52 ++++++- .../oneagent/daemonset/volumes_test.go | 139 ++++++++++++++++++ test/features/cloudnative/default/default.go | 6 +- test/features/hostmonitoring/without_csi.go | 38 +++++ test/helpers/components/dynakube/options.go | 6 + test/scenarios/istio/istio_test.go | 2 +- test/scenarios/no_csi/no_csi_test.go | 4 + test/scenarios/standard/standard_test.go | 2 +- 19 files changed, 307 insertions(+), 28 deletions(-) create mode 100644 test/features/hostmonitoring/without_csi.go diff --git a/doc/e2e/features.md b/doc/e2e/features.md index 316af9cf7c..a5746cad0d 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -299,14 +299,14 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/defaul ## Index -- [func Feature(t *testing.T, istioEnabled bool) features.Feature](<#Feature>) +- [func Feature(t *testing.T, istioEnabled bool, withCSI bool) features.Feature](<#Feature>) ## func [Feature]() ```go -func Feature(t *testing.T, istioEnabled bool) features.Feature +func Feature(t *testing.T, istioEnabled bool, withCSI bool) features.Feature ``` ### With istio enabled @@ -495,6 +495,26 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/extensions" func Feature(t *testing.T) features.Feature ``` +# hostmonitoring + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/hostmonitoring" +``` + +## Index + +- [func WithoutCSI(t *testing.T) features.Feature](<#WithoutCSI>) + + + +## func [WithoutCSI]() + +```go +func WithoutCSI(t *testing.T) features.Feature +``` + +ApplicationMonitoring deployment without CSI driver + # logmonitoring ```go diff --git a/hack/make/tests/e2e.mk b/hack/make/tests/e2e.mk index 01ae73f40c..2d1f01febb 100644 --- a/hack/make/tests/e2e.mk +++ b/hack/make/tests/e2e.mk @@ -153,3 +153,11 @@ test/e2e/extensions: manifests/crd/helm ## Runs LogMonitoring related e2e tests test/e2e/logmonitoring: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "logmonitoring-components-rollout" $(SKIPCLEANUP) + +## Runs Host Monitoring without CSI e2e test only +test/e2e/hostmonitoring/withoutcsi: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "host-monitoring-without-csi" $(SKIPCLEANUP) + +## Runs CloudNative default e2e test only +test/e2e/cloudnative/withoutcsi: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "cloudnative" $(SKIPCLEANUP) diff --git a/pkg/api/v1beta4/dynakube/oneagent/props.go b/pkg/api/v1beta4/dynakube/oneagent/props.go index 7d0ca9adc6..0cb4645324 100644 --- a/pkg/api/v1beta4/dynakube/oneagent/props.go +++ b/pkg/api/v1beta4/dynakube/oneagent/props.go @@ -16,6 +16,7 @@ const ( OneAgentConnectionInfoConfigMapSuffix = "-oneagent-connection-info" PodNameOsAgent = "oneagent" DefaultOneAgentImageRegistrySubPath = "/linux/oneagent" + storageVolumeDefaultHostPath = "/var/opt/dynatrace" ) func NewOneAgent(spec *Spec, status *Status, codeModulesStatus *CodeModulesStatus, //nolint:revive @@ -103,8 +104,8 @@ func (oa *OneAgent) GetConnectionInfoConfigMapName() string { return oa.name + OneAgentConnectionInfoConfigMapSuffix } -func (oa *OneAgent) IsReadOnlyOneAgentsMode() bool { - return oa.IsCloudNativeFullstackMode() || (oa.IsHostMonitoringMode() && oa.IsCSIAvailable()) +func (oa *OneAgent) IsReadOnlyFSSupported() bool { + return oa.IsCloudNativeFullstackMode() || oa.IsHostMonitoringMode() } func (oa *OneAgent) IsAppInjectionNeeded() bool { @@ -326,3 +327,24 @@ func (oa *OneAgent) GetArgumentsMap() map[string][]string { return argMap } + +// GetHostPath provides the host path for the storage volume if CSI driver is absent. +func (oa *OneAgent) GetHostPath() string { + if oa.IsCloudNativeFullstackMode() { + if oa.CloudNativeFullStack.StorageHostPath != "" { + return oa.CloudNativeFullStack.StorageHostPath + } + + return storageVolumeDefaultHostPath + } + + if oa.IsHostMonitoringMode() { + if oa.HostMonitoring.StorageHostPath != "" { + return oa.HostMonitoring.StorageHostPath + } + + return storageVolumeDefaultHostPath + } + + return "" +} diff --git a/pkg/api/v1beta4/dynakube/oneagent/props_test.go b/pkg/api/v1beta4/dynakube/oneagent/props_test.go index 85d55630fa..f5b8a9c9a6 100644 --- a/pkg/api/v1beta4/dynakube/oneagent/props_test.go +++ b/pkg/api/v1beta4/dynakube/oneagent/props_test.go @@ -36,7 +36,7 @@ func TestNeedsReadonlyOneagent(t *testing.T) { CloudNativeFullStack: &CloudNativeFullStackSpec{}, }, } - assert.True(t, oneagent.IsReadOnlyOneAgentsMode()) + assert.True(t, oneagent.IsReadOnlyFSSupported()) }) t.Run("host monitoring with readonly host agent", func(t *testing.T) { @@ -45,7 +45,7 @@ func TestNeedsReadonlyOneagent(t *testing.T) { HostMonitoring: &HostInjectSpec{}, }, } - assert.True(t, oneAgent.IsReadOnlyOneAgentsMode()) + assert.True(t, oneAgent.IsReadOnlyFSSupported()) }) t.Run("host monitoring without readonly host agent", func(t *testing.T) { @@ -56,7 +56,7 @@ func TestNeedsReadonlyOneagent(t *testing.T) { HostMonitoring: &HostInjectSpec{}, }, } - assert.False(t, oneAgent.IsReadOnlyOneAgentsMode()) + assert.True(t, oneAgent.IsReadOnlyFSSupported()) }) } diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index 8758e4a9b0..f36fabd742 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -131,7 +131,7 @@ func mapKeysToString(m map[string]bool, sep string) string { func publicImageSetWithoutReadOnlyMode(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { if dk.OneAgent().GetCustomImage() != "" { - if dk.OneAgent().IsReadOnlyOneAgentsMode() { + if dk.OneAgent().IsReadOnlyFSSupported() { return "" } @@ -197,7 +197,7 @@ func unsupportedOneAgentImage(_ context.Context, _ *Validator, dk *dynakube.Dyna func conflictingOneAgentVolumeStorageSettings(_ context.Context, _ *Validator, dk *dynakube.DynaKube) string { volumeStorageEnabled, volumeStorageSet := hasOneAgentVolumeStorageEnabled(dk) - if dk.OneAgent().IsReadOnlyOneAgentsMode() && volumeStorageSet && !volumeStorageEnabled { + if dk.OneAgent().IsReadOnlyFSSupported() && volumeStorageSet && !volumeStorageEnabled { return errorVolumeStorageReadOnlyModeConflict } diff --git a/pkg/api/validation/dynakube/oneagent_test.go b/pkg/api/validation/dynakube/oneagent_test.go index fcbe40bd0c..cbcc8a7795 100644 --- a/pkg/api/validation/dynakube/oneagent_test.go +++ b/pkg/api/validation/dynakube/oneagent_test.go @@ -585,7 +585,7 @@ func TestIsOneAgentVersionValid(t *testing.T) { func TestPublicImageSetWithReadOnlyMode(t *testing.T) { t.Run("reject dk with hostMon without csi and custom image", func(t *testing.T) { setupDisabledCSIEnv(t) - assertAllowedWithWarnings(t, 1, + assertAllowedWithoutWarnings(t, &dynakube.DynaKube{ ObjectMeta: defaultDynakubeObjectMeta, Spec: dynakube.DynaKubeSpec{ diff --git a/pkg/controllers/csi/metadata/correctness.go b/pkg/controllers/csi/metadata/correctness.go index 230dc78193..8028816dff 100644 --- a/pkg/controllers/csi/metadata/correctness.go +++ b/pkg/controllers/csi/metadata/correctness.go @@ -94,7 +94,7 @@ func (checker *CorrectnessChecker) migrateHostMounts(ctx context.Context) { } for _, dk := range dks { - if !dk.OneAgent().IsReadOnlyOneAgentsMode() { + if !dk.OneAgent().IsReadOnlyFSSupported() { continue } @@ -147,7 +147,7 @@ func GetRelevantDynaKubes(ctx context.Context, apiReader client.Reader) ([]dynak var relevantDks []dynakube.DynaKube for _, dk := range dkList.Items { - if dk.OneAgent().IsAppInjectionNeeded() || dk.OneAgent().IsReadOnlyOneAgentsMode() { + if dk.OneAgent().IsAppInjectionNeeded() || dk.OneAgent().IsReadOnlyFSSupported() { relevantDks = append(relevantDks, dk) } } diff --git a/pkg/controllers/csi/provisioner/cleanup/hostmounts.go b/pkg/controllers/csi/provisioner/cleanup/hostmounts.go index 8847af05e7..d3f64c185f 100644 --- a/pkg/controllers/csi/provisioner/cleanup/hostmounts.go +++ b/pkg/controllers/csi/provisioner/cleanup/hostmounts.go @@ -53,7 +53,7 @@ func (c *Cleaner) collectRelevantHostDirs(dks []dynakube.DynaKube) map[string]bo hostDirs := map[string]bool{} for _, dk := range dks { - if !dk.OneAgent().IsReadOnlyOneAgentsMode() { + if !dk.OneAgent().IsReadOnlyFSSupported() { continue } diff --git a/pkg/controllers/csi/provisioner/controller.go b/pkg/controllers/csi/provisioner/controller.go index 29784ba311..4442945089 100644 --- a/pkg/controllers/csi/provisioner/controller.go +++ b/pkg/controllers/csi/provisioner/controller.go @@ -151,7 +151,7 @@ func (provisioner *OneAgentProvisioner) Reconcile(ctx context.Context, request r } func isProvisionerNeeded(dk *dynakube.DynaKube) bool { - return dk.OneAgent().IsAppInjectionNeeded() || dk.OneAgent().IsReadOnlyOneAgentsMode() + return dk.OneAgent().IsAppInjectionNeeded() || dk.OneAgent().IsReadOnlyFSSupported() } func (provisioner *OneAgentProvisioner) setupFileSystem(dk dynakube.DynaKube) error { diff --git a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go index 3738a380b1..c7713a4e79 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/daemonset.go @@ -41,6 +41,8 @@ const ( csiStorageVolumeName = "osagent-storage" csiStorageVolumeMount = "/mnt/volume_storage_mount" + storageVolumeName = "volume-storage" + podName = "dynatrace-oneagent" inframonHostIdSource = "k8s-node-name" @@ -319,7 +321,7 @@ func (b *builder) imagePullSecrets() []corev1.LocalObjectReference { func (b *builder) securityContext() *corev1.SecurityContext { var securityContext corev1.SecurityContext - if b.dk != nil && b.dk.OneAgent().IsReadOnlyOneAgentsMode() { + if b.dk != nil && b.dk.OneAgent().IsReadOnlyFSSupported() { securityContext.RunAsNonRoot = ptr.To(true) securityContext.RunAsUser = ptr.To(int64(1000)) securityContext.RunAsGroup = ptr.To(int64(1000)) @@ -415,7 +417,7 @@ func (b *builder) getReadinessProbe() *corev1.Probe { // if the version is not set, ie.: unknown, we consider the OneAgent to support `ReadOnlyRootFilesystem`. func (b *builder) isRootFsReadonly() bool { if b.dk != nil && - b.dk.OneAgent().IsReadOnlyOneAgentsMode() && + b.dk.OneAgent().IsReadOnlyFSSupported() && b.dk.OneAgent().GetVersion() != "" && b.dk.OneAgent().GetVersion() != string(status.CustomImageVersionSource) { agentSemver, err := dtversion.ToSemver(b.dk.OneAgent().GetVersion()) diff --git a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go index 49958c8715..0bc50a8736 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/env_vars.go @@ -122,7 +122,7 @@ func (b *builder) addProxyEnv(envVarMap *prioritymap.Map) { } func (b *builder) addReadOnlyEnv(envVarMap *prioritymap.Map) { - if b.dk != nil && b.dk.OneAgent().IsReadOnlyOneAgentsMode() { + if b.dk != nil && b.dk.OneAgent().IsReadOnlyFSSupported() { addDefaultValue(envVarMap, oneagentReadOnlyMode, "true") } } diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go index fff4a391e8..043c27404b 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" ) func prepareVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { @@ -15,22 +16,32 @@ func prepareVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { volumeMounts = append(volumeMounts, getOneAgentSecretVolumeMount()) - if dk != nil && dk.OneAgent().IsReadOnlyOneAgentsMode() { + if dk == nil { + volumeMounts = append(volumeMounts, getRootMount()) + + return volumeMounts + } + + if dk.OneAgent().IsReadOnlyFSSupported() { volumeMounts = append(volumeMounts, getReadOnlyRootMount()) - volumeMounts = append(volumeMounts, getCSIStorageMount()) + if dk.OneAgent().IsCSIAvailable() { + volumeMounts = append(volumeMounts, getCSIStorageMount()) + } else { + volumeMounts = append(volumeMounts, getStorageVolumeMount(dk)) + } } else { volumeMounts = append(volumeMounts, getRootMount()) } - if dk != nil && dk.Spec.TrustedCAs != "" { + if dk.Spec.TrustedCAs != "" { volumeMounts = append(volumeMounts, getClusterCaCertVolumeMount()) } - if dk != nil && dk.ActiveGate().HasCaCert() { + if dk.ActiveGate().HasCaCert() { volumeMounts = append(volumeMounts, getActiveGateCaCertVolumeMount()) } - if dk != nil && dk.NeedsOneAgentProxy() { + if dk.NeedsOneAgentProxy() { volumeMounts = append(volumeMounts, getHttpProxyMount()) } @@ -81,6 +92,17 @@ func getCSIStorageMount() corev1.VolumeMount { } } +func getStorageVolumeMount(dk *dynakube.DynaKube) corev1.VolumeMount { + // the TenantUUID is already set + tenant, _ := dk.TenantUUID() + + return corev1.VolumeMount{ + Name: storageVolumeName, + SubPath: tenant, + MountPath: csiStorageVolumeMount, + } +} + func getHttpProxyMount() corev1.VolumeMount { return proxy.BuildVolumeMount() } @@ -94,8 +116,12 @@ func prepareVolumes(dk *dynakube.DynaKube) []corev1.Volume { volumes = append(volumes, getOneAgentSecretVolume(dk)) - if dk.OneAgent().IsReadOnlyOneAgentsMode() { - volumes = append(volumes, getCSIStorageVolume(dk)) + if dk.OneAgent().IsReadOnlyFSSupported() { + if dk.OneAgent().IsCSIAvailable() { + volumes = append(volumes, getCSIStorageVolume(dk)) + } else { + volumes = append(volumes, getStorageVolume(dk)) + } } if dk.Spec.TrustedCAs != "" { @@ -147,6 +173,18 @@ func getCSIStorageVolume(dk *dynakube.DynaKube) corev1.Volume { } } +func getStorageVolume(dk *dynakube.DynaKube) corev1.Volume { + return corev1.Volume{ + Name: storageVolumeName, + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: dk.OneAgent().GetHostPath(), + Type: ptr.To(corev1.HostPathDirectoryOrCreate), + }, + }, + } +} + func getActiveGateCaCertVolume(dk *dynakube.DynaKube) corev1.Volume { return corev1.Volume{ Name: activeGateCaCertVolumeName, diff --git a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go index efe4b3aa34..9b98cd5f6c 100644 --- a/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/oneagent/daemonset/volumes_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy" + "github.com/Dynatrace/dynatrace-operator/pkg/util/installconfig" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -299,3 +300,141 @@ func TestPrepareVolumeMounts(t *testing.T) { assert.NotContains(t, mounts, getHttpProxyMount()) }) } + +func TestVolumesAndVolumeMountsVsCSIDriver(t *testing.T) { + dkHostMonitoring := &dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + OneAgent: oneagent.Spec{ + HostMonitoring: &oneagent.HostInjectSpec{}, + }, + }, + } + dkCloudNativeFullStack := &dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + OneAgent: oneagent.Spec{ + CloudNativeFullStack: &oneagent.CloudNativeFullStackSpec{}, + }, + }, + } + dkClassicFullStack := &dynakube.DynaKube{ + Spec: dynakube.DynaKubeSpec{ + OneAgent: oneagent.Spec{ + ClassicFullStack: &oneagent.HostInjectSpec{}, + }, + }, + } + + type oneAgentVolumeTest struct { + testName string + dk *dynakube.DynaKube + csi bool + csiVolume bool + storageVolume bool + rootReadOnlyVolumeMount bool + } + + testCases := []oneAgentVolumeTest{ + { + testName: "hostMonitoring w/ CSI driver", + dk: dkHostMonitoring, + csi: true, + csiVolume: true, + storageVolume: false, + rootReadOnlyVolumeMount: true, + }, + { + testName: "hostMonitoring w/o CSI driver", + dk: dkHostMonitoring, + csi: false, + csiVolume: false, + storageVolume: true, + rootReadOnlyVolumeMount: true, + }, + + { + testName: "cloudNativeFullStack w/ CSI driver", + dk: dkCloudNativeFullStack, + csi: true, + csiVolume: true, + storageVolume: false, + rootReadOnlyVolumeMount: true, + }, + { + testName: "cloudNativeFullStack w/o CSI driver", + dk: dkCloudNativeFullStack, + csi: false, + csiVolume: false, + storageVolume: true, + rootReadOnlyVolumeMount: true, + }, + + { + testName: "classicFullStack w/o CSI driver", + dk: dkClassicFullStack, + csi: false, + csiVolume: false, + storageVolume: false, + rootReadOnlyVolumeMount: false, + }, + } + + for _, tc := range testCases { + t.Run("Volumes:"+tc.testName, func(t *testing.T) { + testVolumesVsCSIDriver(t, tc.dk, tc.csi, tc.csiVolume, tc.storageVolume) + }) + + t.Run("VolumeMounts:"+tc.testName, func(t *testing.T) { + testVolumeMountsVsCSIDriver(t, tc.dk, tc.csi, tc.csiVolume, tc.storageVolume, tc.rootReadOnlyVolumeMount) + }) + } +} + +func testVolumesVsCSIDriver(t *testing.T, dk *dynakube.DynaKube, csi bool, csiVolume bool, storageVolume bool) { + if csi { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: true}) + } else { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + } + + volumes := prepareVolumes(dk) + + if csiVolume { + assert.Contains(t, volumes, getCSIStorageVolume(dk)) + } else { + assert.NotContains(t, volumes, getCSIStorageVolume(dk)) + } + + if storageVolume { + assert.Contains(t, volumes, getStorageVolume(dk)) + } else { + assert.NotContains(t, volumes, getStorageVolume(dk)) + } +} + +func testVolumeMountsVsCSIDriver(t *testing.T, dk *dynakube.DynaKube, csi bool, csiVolume bool, storageVolume bool, rootReadOnlyVolumeMount bool) { //nolint:revive + if csi { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: true}) + } else { + installconfig.SetModulesOverride(t, installconfig.Modules{CSIDriver: false}) + } + + volumeMounts := prepareVolumeMounts(dk) + + if csiVolume { + assert.Contains(t, volumeMounts, getCSIStorageMount()) + } else { + assert.NotContains(t, volumeMounts, getCSIStorageMount()) + } + + if storageVolume { + assert.Contains(t, volumeMounts, getStorageVolumeMount(dk)) + } else { + assert.NotContains(t, volumeMounts, getStorageVolumeMount(dk)) + } + + if rootReadOnlyVolumeMount { + assert.Contains(t, volumeMounts, getReadOnlyRootMount()) + } else { + assert.Contains(t, volumeMounts, getRootMount()) + } +} diff --git a/test/features/cloudnative/default/default.go b/test/features/cloudnative/default/default.go index af0af50a9b..a81cabc454 100644 --- a/test/features/cloudnative/default/default.go +++ b/test/features/cloudnative/default/default.go @@ -47,7 +47,7 @@ import ( // // Sample application Deployment is installed and restarted to check if OneAgent is // injected and VERSION environment variable is correct. -func Feature(t *testing.T, istioEnabled bool) features.Feature { +func Feature(t *testing.T, istioEnabled bool, withCSI bool) features.Feature { builder := features.New("cloudnative") t.Logf("istio enabled: %v", istioEnabled) secretConfig := tenant.GetSingleTenantSecret(t) @@ -80,7 +80,9 @@ func Feature(t *testing.T, istioEnabled bool) features.Feature { istio.AssessIstio(builder, testDynakube, *sampleApp) } - builder.Assess(fmt.Sprintf("check %s has no conn info", codemodules.RuxitAgentProcFile), codemodules.CheckRuxitAgentProcFileHasNoConnInfo(testDynakube)) + if withCSI { + builder.Assess(fmt.Sprintf("check %s has no conn info", codemodules.RuxitAgentProcFile), codemodules.CheckRuxitAgentProcFileHasNoConnInfo(testDynakube)) + } // Register sample, dynakube and operator uninstall builder.Teardown(sampleApp.Uninstall()) diff --git a/test/features/hostmonitoring/without_csi.go b/test/features/hostmonitoring/without_csi.go new file mode 100644 index 0000000000..4813642336 --- /dev/null +++ b/test/features/hostmonitoring/without_csi.go @@ -0,0 +1,38 @@ +//go:build e2e + +package hostmonitoring + +import ( + "testing" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/test/helpers" + "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/daemonset" + "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" + "sigs.k8s.io/e2e-framework/pkg/features" +) + +// ApplicationMonitoring deployment without CSI driver +func WithoutCSI(t *testing.T) features.Feature { + builder := features.New("host-monitoring-without-csi") + secretConfig := tenant.GetSingleTenantSecret(t) + + options := []dynakube.Option{ + dynakube.WithApiUrl(secretConfig.ApiUrl), + dynakube.WithHostMonitoringSpec(&oneagent.HostInjectSpec{}), + } + testDynakube := *dynakube.New(options...) + + // Register dynakube install + dynakube.Install(builder, helpers.LevelAssess, &secretConfig, testDynakube) + + builder.Assess("one agent started", daemonset.WaitForDaemonset(testDynakube.OneAgent().GetDaemonsetName(), testDynakube.Namespace)) + + // Register sample, dynakube and operator uninstall + dynakube.Delete(builder, helpers.LevelTeardown, testDynakube) + + builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(testDynakube.Name, testDynakube.Namespace)) + + return builder.Feature() +} diff --git a/test/helpers/components/dynakube/options.go b/test/helpers/components/dynakube/options.go index 9f1d246ce1..072f3f3928 100644 --- a/test/helpers/components/dynakube/options.go +++ b/test/helpers/components/dynakube/options.go @@ -152,6 +152,12 @@ func WithCloudNativeSpec(cloudNativeFullStackSpec *oneagent.CloudNativeFullStack } } +func WithHostMonitoringSpec(hostInjectSpec *oneagent.HostInjectSpec) Option { + return func(dk *dynakube.DynaKube) { + dk.Spec.OneAgent.HostMonitoring = hostInjectSpec + } +} + func WithApplicationMonitoringSpec(applicationMonitoringSpec *oneagent.ApplicationMonitoringSpec) Option { return func(dk *dynakube.DynaKube) { dk.Spec.OneAgent.ApplicationMonitoring = applicationMonitoringSpec diff --git a/test/scenarios/istio/istio_test.go b/test/scenarios/istio/istio_test.go index a6ac20b451..c6f93279f6 100644 --- a/test/scenarios/istio/istio_test.go +++ b/test/scenarios/istio/istio_test.go @@ -51,7 +51,7 @@ func TestIstio(t *testing.T) { feats := []features.Feature{ networkProblems.ResilienceFeature(t), // TODO: Fix so order do not matter, because its the first feature here for a reason => we don’t want to have any downloaded codemodules in the filesystem of the CSI-driver, and we can't clean the filesystem between features as the operator is not reinstalled and therefore the csi-driver is running, and you would have to mess with the database because removing it just bricks things. activegate.Feature(t, proxy.ProxySpec), - cloudnativeDefault.Feature(t, true), + cloudnativeDefault.Feature(t, true, true), codemodules.WithProxy(t, proxy.ProxySpec), codemodules.WithProxyAndAGCert(t, proxy.ProxySpec), codemodules.WithProxyAndAutomaticAGCert(t, proxy.ProxySpec), diff --git a/test/scenarios/no_csi/no_csi_test.go b/test/scenarios/no_csi/no_csi_test.go index 2c3f4d6e4d..b69fbc25fd 100644 --- a/test/scenarios/no_csi/no_csi_test.go +++ b/test/scenarios/no_csi/no_csi_test.go @@ -9,8 +9,10 @@ import ( "github.com/Dynatrace/dynatrace-operator/test/features/applicationmonitoring" "github.com/Dynatrace/dynatrace-operator/test/features/bootstrapper" "github.com/Dynatrace/dynatrace-operator/test/features/classic" + cloudnativeDefault "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/default" "github.com/Dynatrace/dynatrace-operator/test/features/edgeconnect" "github.com/Dynatrace/dynatrace-operator/test/features/extensions" + "github.com/Dynatrace/dynatrace-operator/test/features/hostmonitoring" "github.com/Dynatrace/dynatrace-operator/test/features/logmonitoring" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" @@ -53,6 +55,8 @@ func TestNoCSI(t *testing.T) { classic.Feature(t), bootstrapper.NoCSI(t), logmonitoring.Feature(t), + hostmonitoring.WithoutCSI(t), + cloudnativeDefault.Feature(t, false, false), } testEnv.Test(t, scenarios.FilterFeatures(*cfg, feats)...) diff --git a/test/scenarios/standard/standard_test.go b/test/scenarios/standard/standard_test.go index be2219c927..eac133d398 100644 --- a/test/scenarios/standard/standard_test.go +++ b/test/scenarios/standard/standard_test.go @@ -44,7 +44,7 @@ func TestMain(m *testing.M) { func TestStandard(t *testing.T) { feats := []features.Feature{ - cloudnativeDefault.Feature(t, false), + cloudnativeDefault.Feature(t, false, true), applicationmonitoring.ReadOnlyCSIVolume(t), codemodules.InstallFromImage(t), publicregistry.Feature(t), From 938f3053418c4a3001177190fcce154711eb7942 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Thu, 27 Mar 2025 15:56:05 +0100 Subject: [PATCH 375/426] Migrate google-marketplace deployer image build to gh action (#4672) --- .github/actions/build-image/action.yaml | 2 +- .github/workflows/release.yaml | 50 ++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index d279c901f1..2808a2f123 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -50,7 +50,7 @@ runs: shell: bash run: | set -x - podman save --format oci-archive -o /tmp/operator-${{ inputs.platform }}.tar operator-${{ inputs.platform }}:${{ inputs.image-tag }} + podman save --format oci-archive -o /tmp/operator-${{ inputs.platform }}.tar operator-${{ inputs.platform }}:${{ inputs.image-tag }} - name: Upload artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index da59d303fb..c82f66da02 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -20,16 +20,28 @@ jobs: id: prep run: | hack/build/ci/prepare-build-variables.sh + - name: Docker metadata uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 id: meta with: images: dynatrace/dynatrace-operator - tags: ${{ steps.prep.outputs.docker_image_tag }} + tags: | + type=semver,pattern={{major}}.{{minor}} + ${{ steps.prep.outputs.docker_image_tag }} labels: | ${{ steps.prep.outputs.docker_image_labels }} vcs-ref=${{ github.sha }} + - name: Prepare major_minor tag + shell: bash + id: prepare-major-minor-tag + run: | + set -x + tag="${{ join(fromJSON(steps.meta.outputs.json).tags[0]) }}" + version_with_major_minor=${tag##*:} + echo "version_with_major_minor=$version_with_major_minor" >> $GITHUB_OUTPUT outputs: + version_with_major_minor: ${{ steps.prepare-major-minor-tag.outputs.version_with_major_minor }} labels: ${{ steps.meta.outputs.labels }} version: ${{ steps.prep.outputs.docker_image_tag }} version_without_prefix: ${{ steps.prep.outputs.docker_image_tag_without_prefix }} @@ -256,6 +268,42 @@ jobs: signing-key: ${{ secrets.COSIGN_PRIVATE_KEY }} signing-password: ${{ secrets.COSIGN_PASSWORD }} + build-gcr-deployer: + name: Build GCR deployer image + environment: Release + runs-on: ubuntu-latest + needs: [ prepare ] + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Login to GCR + uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 + with: + registry: gcr.io + username: ${{ secrets.GCR_USERNAME }} + password: ${{ secrets.GCR_JSON_KEY }} + - name: Build target + id: build-image + uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2.13 + with: + oci: true + context: ./config/helm/ + containerfiles: | + ./config/helm/Dockerfile + tags: ${{ needs.prepare.outputs.version_with_major_minor }} ${{ needs.prepare.outputs.version_without_prefix }} + image: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }} + extra-args: | + --annotation=com.googleapis.cloudmarketplace.product.service.name=services/dynatrace-operator-dynatrace-marketplace-prod.cloudpartnerservices.goog + - name: Push To gcr + id: push-to-gcr + uses: redhat-actions/push-to-registry@5ed88d269cf581ea9ef6dd6806d01562096bee9c # v2.8 + with: + image: ${{ secrets.GCR_REPOSITORY_DEPLOYER }} + registry: gcr.io + tags: ${{ needs.prepare.outputs.version_with_major_minor }} ${{ needs.prepare.outputs.version_without_prefix }} + username: ${{ secrets.GCR_USERNAME }} + password: ${{ secrets.GCR_JSON_KEY }} + run-preflight-rhcc: name: Run preflight for rhcc environment: Release From 777cc13f72d70c4d0c004b5903c80153e52de750 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Thu, 27 Mar 2025 16:06:02 +0100 Subject: [PATCH 376/426] Remove obsolete otlpIngest feature from Dynakube (#4669) --- pkg/api/v1beta3/dynakube/activegate/spec.go | 3 +- pkg/api/v1beta4/dynakube/activegate/props.go | 4 - pkg/api/v1beta4/dynakube/activegate/spec.go | 3 +- pkg/api/v1beta4/dynakube/activegate_props.go | 1 - pkg/api/v1beta4/dynakube/dynakube_types.go | 2 - pkg/api/v1beta4/dynakube/otlp_props.go | 5 -- .../activegate/capability/capability.go | 2 +- .../activegate/capability/capability_test.go | 85 +++++-------------- .../internal/statefulset/statefulset.go | 2 +- 9 files changed, 23 insertions(+), 84 deletions(-) delete mode 100644 pkg/api/v1beta4/dynakube/otlp_props.go diff --git a/pkg/api/v1beta3/dynakube/activegate/spec.go b/pkg/api/v1beta3/dynakube/activegate/spec.go index d3954050aa..bb95ff1a3a 100644 --- a/pkg/api/v1beta3/dynakube/activegate/spec.go +++ b/pkg/api/v1beta3/dynakube/activegate/spec.go @@ -66,11 +66,10 @@ type ActiveGate struct { // dependencies is a collection of possible other feature/components that need an ActiveGate, but is not directly configured in the ActiveGate section. type dependencies struct { extensions bool - otlpIngest bool } func (d dependencies) Any() bool { - return d.extensions || d.otlpIngest // kspm is a dependency too, but blocked by validation webhook to not run standalone + return d.extensions // kspm is a dependency too, but blocked by validation webhook to not run standalone } // +kubebuilder:object:generate=true diff --git a/pkg/api/v1beta4/dynakube/activegate/props.go b/pkg/api/v1beta4/dynakube/activegate/props.go index f8c91f62ed..905a53797c 100644 --- a/pkg/api/v1beta4/dynakube/activegate/props.go +++ b/pkg/api/v1beta4/dynakube/activegate/props.go @@ -31,10 +31,6 @@ func (ag *Spec) SetExtensionsDependency(isEnabled bool) { ag.enabledDependencies.extensions = isEnabled } -func (ag *Spec) SetOTLPingestDependency(isEnabled bool) { - ag.enabledDependencies.otlpIngest = isEnabled -} - func (ag *Spec) apiUrlHost() string { parsedUrl, err := url.Parse(ag.apiUrl) if err != nil { diff --git a/pkg/api/v1beta4/dynakube/activegate/spec.go b/pkg/api/v1beta4/dynakube/activegate/spec.go index 2dcbdbda81..d32417a344 100644 --- a/pkg/api/v1beta4/dynakube/activegate/spec.go +++ b/pkg/api/v1beta4/dynakube/activegate/spec.go @@ -66,11 +66,10 @@ type ActiveGate struct { // dependencies is a collection of possible other feature/components that need an ActiveGate, but is not directly configured in the ActiveGate section. type dependencies struct { extensions bool - otlpIngest bool } func (d dependencies) Any() bool { - return d.extensions || d.otlpIngest // kspm is a dependency too, but blocked by validation webhook to not run standalone + return d.extensions // kspm is a dependency too, but blocked by validation webhook to not run standalone } // +kubebuilder:object:generate=true diff --git a/pkg/api/v1beta4/dynakube/activegate_props.go b/pkg/api/v1beta4/dynakube/activegate_props.go index 9f82b1d60b..2547e1c570 100644 --- a/pkg/api/v1beta4/dynakube/activegate_props.go +++ b/pkg/api/v1beta4/dynakube/activegate_props.go @@ -9,7 +9,6 @@ func (dk *DynaKube) ActiveGate() *activegate.ActiveGate { dk.Spec.ActiveGate.SetName(dk.Name) dk.Spec.ActiveGate.SetAutomaticTLSCertificate(dk.FeatureActiveGateAutomaticTLSCertificate()) dk.Spec.ActiveGate.SetExtensionsDependency(dk.IsExtensionsEnabled()) - dk.Spec.ActiveGate.SetOTLPingestDependency(dk.IsOTLPingestEnabled()) return &activegate.ActiveGate{ Spec: &dk.Spec.ActiveGate, diff --git a/pkg/api/v1beta4/dynakube/dynakube_types.go b/pkg/api/v1beta4/dynakube/dynakube_types.go index 51d99d4169..e91ce74e9b 100644 --- a/pkg/api/v1beta4/dynakube/dynakube_types.go +++ b/pkg/api/v1beta4/dynakube/dynakube_types.go @@ -151,8 +151,6 @@ type DynaKubeSpec struct { //nolint:revive // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Enable Istio automatic management",order=9,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} EnableIstio bool `json:"enableIstio,omitempty"` - - EnableOTLPingest bool `json:"-"` } type TemplatesSpec struct { diff --git a/pkg/api/v1beta4/dynakube/otlp_props.go b/pkg/api/v1beta4/dynakube/otlp_props.go deleted file mode 100644 index 3504d7e038..0000000000 --- a/pkg/api/v1beta4/dynakube/otlp_props.go +++ /dev/null @@ -1,5 +0,0 @@ -package dynakube - -func (dk *DynaKube) IsOTLPingestEnabled() bool { - return dk.Spec.EnableOTLPingest -} diff --git a/pkg/controllers/dynakube/activegate/capability/capability.go b/pkg/controllers/dynakube/activegate/capability/capability.go index 924063a02f..c68a5ca992 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability.go +++ b/pkg/controllers/dynakube/activegate/capability/capability.go @@ -103,7 +103,7 @@ func NewMultiCapability(dk *dynakube.DynaKube) Capability { capabilityDisplayNames = append(capabilityDisplayNames, "extension-controller") } - if dk.IsOTLPingestEnabled() || dk.TelemetryIngest().IsEnabled() { + if dk.TelemetryIngest().IsEnabled() { capabilityNames = append(capabilityNames, "log_analytics_collector", "generic_ingest", "otlp_ingest") capabilityDisplayNames = append(capabilityDisplayNames, "log_analytics-collector", "generic-ingest", "otlp-ingest") } diff --git a/pkg/controllers/dynakube/activegate/capability/capability_test.go b/pkg/controllers/dynakube/activegate/capability/capability_test.go index 7ad0dbda58..5f3355c979 100644 --- a/pkg/controllers/dynakube/activegate/capability/capability_test.go +++ b/pkg/controllers/dynakube/activegate/capability/capability_test.go @@ -13,18 +13,15 @@ import ( ) const ( - testNamespace = "test-namespace" - testName = "test-name" - testApiUrl = "https://demo.dev.dynatracelabs.com/api" - expectedShortName = "activegate" - expectedArgName = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface" - expectedArgNameWithDebugging = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,debugging" - expectedArgNameWithExtensions = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller" - expectedArgNameWithExtensionsOnly = "extension_controller" - expectedArgNameWithOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest,otlp_ingest" - expectedArgNameWithOTLPingestOnly = "log_analytics_collector,generic_ingest,otlp_ingest" - expectedArgNameWithExtensionsAndOTLPingest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller,log_analytics_collector,generic_ingest,otlp_ingest" - expectedArgNameWithTelemetryIngest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest,otlp_ingest" + testNamespace = "test-namespace" + testName = "test-name" + testApiUrl = "https://demo.dev.dynatracelabs.com/api" + expectedShortName = "activegate" + expectedArgName = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface" + expectedArgNameWithDebugging = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,debugging" + expectedArgNameWithExtensions = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,extension_controller" + expectedArgNameWithExtensionsOnly = "extension_controller" + expectedArgNameWithTelemetryIngest = "MSGrouter,kubernetes_monitoring,metrics_ingest,restInterface,log_analytics_collector,generic_ingest,otlp_ingest" ) var capabilities = []activegate.CapabilityDisplayName{ @@ -34,7 +31,7 @@ var capabilities = []activegate.CapabilityDisplayName{ activegate.DynatraceApiCapability.DisplayName, } -func buildDynakube(capabilities []activegate.CapabilityDisplayName, enableExtensions bool, enableOTLPingest bool, enableTelemetryIngest bool) *dynakube.DynaKube { +func buildDynakube(capabilities []activegate.CapabilityDisplayName, enableExtensions bool, enableTelemetryIngest bool) *dynakube.DynaKube { extensionsSpec := &dynakube.ExtensionsSpec{} if !enableExtensions { extensionsSpec = nil @@ -54,9 +51,8 @@ func buildDynakube(capabilities []activegate.CapabilityDisplayName, enableExtens ActiveGate: activegate.Spec{ Capabilities: capabilities, }, - Extensions: extensionsSpec, - EnableOTLPingest: enableOTLPingest, - TelemetryIngest: telemetryIngestSpec, + Extensions: extensionsSpec, + TelemetryIngest: telemetryIngestSpec, }, } } @@ -81,7 +77,7 @@ func TestBuildServiceName(t *testing.T) { func TestNewMultiCapability(t *testing.T) { t.Run(`creates new multicapability`, func(t *testing.T) { - dk := buildDynakube(capabilities, false, false, false) + dk := buildDynakube(capabilities, false, false) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.True(t, mc.Enabled()) @@ -90,7 +86,7 @@ func TestNewMultiCapability(t *testing.T) { }) t.Run(`creates new multicapability without capabilities set in dynakube`, func(t *testing.T) { var emptyCapabilites []activegate.CapabilityDisplayName - dk := buildDynakube(emptyCapabilites, false, false, false) + dk := buildDynakube(emptyCapabilites, false, false) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.False(t, mc.Enabled()) @@ -101,7 +97,7 @@ func TestNewMultiCapability(t *testing.T) { func TestNewMultiCapabilityWithExtensions(t *testing.T) { t.Run(`creates new multicapability with Extensions enabled`, func(t *testing.T) { - dk := buildDynakube(capabilities, true, false, false) + dk := buildDynakube(capabilities, true, false) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.True(t, mc.Enabled()) @@ -110,7 +106,7 @@ func TestNewMultiCapabilityWithExtensions(t *testing.T) { }) t.Run(`creates new multicapability without capabilities set in dynakube and Extensions enabled`, func(t *testing.T) { var emptyCapabilites []activegate.CapabilityDisplayName - dk := buildDynakube(emptyCapabilites, true, false, false) + dk := buildDynakube(emptyCapabilites, true, false) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.True(t, mc.Enabled()) @@ -119,40 +115,9 @@ func TestNewMultiCapabilityWithExtensions(t *testing.T) { }) } -func TestNewMultiCapabilityWithOTLPingest(t *testing.T) { - t.Run(`creates new multicapability with OTLPingest enabled`, func(t *testing.T) { - dk := buildDynakube(capabilities, false, true, false) - mc := NewMultiCapability(dk) - require.NotNil(t, mc) - assert.True(t, mc.Enabled()) - assert.Equal(t, expectedShortName, mc.ShortName()) - assert.Equal(t, expectedArgNameWithOTLPingest, mc.ArgName()) - }) - t.Run(`creates new multicapability without capabilities set in dynakube and OTLPingest enabled`, func(t *testing.T) { - var emptyCapabilites []activegate.CapabilityDisplayName - dk := buildDynakube(emptyCapabilites, false, true, false) - mc := NewMultiCapability(dk) - require.NotNil(t, mc) - assert.True(t, mc.Enabled()) - assert.Equal(t, expectedShortName, mc.ShortName()) - assert.Equal(t, expectedArgNameWithOTLPingestOnly, mc.ArgName()) - }) -} - -func TestNewMultiCapabilityWithExtensionsAndOTLPingest(t *testing.T) { - t.Run(`creates new multicapability with Extensions and OTLPingest enabled`, func(t *testing.T) { - dk := buildDynakube(capabilities, true, true, false) - mc := NewMultiCapability(dk) - require.NotNil(t, mc) - assert.True(t, mc.Enabled()) - assert.Equal(t, expectedShortName, mc.ShortName()) - assert.Equal(t, expectedArgNameWithExtensionsAndOTLPingest, mc.ArgName()) - }) -} - func TestNewMultiCapabilityWithTelemetryIngest(t *testing.T) { t.Run(`creates new multicapability with TelemetryIngest enabled`, func(t *testing.T) { - dk := buildDynakube(capabilities, false, false, true) + dk := buildDynakube(capabilities, false, true) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.True(t, mc.Enabled()) @@ -161,7 +126,7 @@ func TestNewMultiCapabilityWithTelemetryIngest(t *testing.T) { }) t.Run(`creates new multicapability without capabilities set in dynakube and TelemetryIngest enabled`, func(t *testing.T) { var emptyCapabilites []activegate.CapabilityDisplayName - dk := buildDynakube(emptyCapabilites, false, false, true) + dk := buildDynakube(emptyCapabilites, false, true) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.False(t, mc.Enabled()) @@ -170,21 +135,9 @@ func TestNewMultiCapabilityWithTelemetryIngest(t *testing.T) { }) } -func TestNewMultiCapabilityWithOTLPingestAndTelemetryIngest(t *testing.T) { - t.Run(`creates new multicapability without capabilities set in dynakube and with OTLPingest and TelemetryIngest enabled`, func(t *testing.T) { - var emptyCapabilites []activegate.CapabilityDisplayName - dk := buildDynakube(emptyCapabilites, false, true, true) - mc := NewMultiCapability(dk) - require.NotNil(t, mc) - assert.True(t, mc.Enabled()) - assert.Equal(t, expectedShortName, mc.ShortName()) - assert.Equal(t, expectedArgNameWithOTLPingestOnly, mc.ArgName()) - }) -} - func TestNewMultiCapabilityWithDebugging(t *testing.T) { t.Run(`creates new multicapability with debugging capability enabled`, func(t *testing.T) { - dk := buildDynakube(append(capabilities, activegate.DebuggingCapability.DisplayName), false, false, false) + dk := buildDynakube(append(capabilities, activegate.DebuggingCapability.DisplayName), false, false) mc := NewMultiCapability(dk) require.NotNil(t, mc) assert.True(t, mc.Enabled()) diff --git a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go index 9109098a6a..b6d7d6ee11 100644 --- a/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go +++ b/pkg/controllers/dynakube/activegate/internal/statefulset/statefulset.go @@ -278,7 +278,7 @@ func (statefulSetBuilder Builder) nodeAffinity() *corev1.Affinity { } func isDefaultPVCNeeded(dk dynakube.DynaKube) bool { - return (dk.TelemetryIngest().IsEnabled() || dk.IsOTLPingestEnabled()) && !dk.Spec.ActiveGate.UseEphemeralVolume + return dk.TelemetryIngest().IsEnabled() && !dk.Spec.ActiveGate.UseEphemeralVolume } func (statefulSetBuilder Builder) addPersistentVolumeClaim(sts *appsv1.StatefulSet) { From e89a374c31761acfe77a6853b793e4470cbe5b73 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 28 Mar 2025 02:56:40 +0000 Subject: [PATCH 377/426] fix(deps): update module golang.org/x/net to v0.38.0 (main) (#4673) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4c342165aa..99bb0e5188 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.24.0 - golang.org/x/net v0.37.0 + golang.org/x/net v0.38.0 golang.org/x/oauth2 v0.28.0 golang.org/x/sys v0.31.0 google.golang.org/grpc v1.71.0 diff --git a/go.sum b/go.sum index 25b3b2394f..d676069834 100644 --- a/go.sum +++ b/go.sum @@ -322,8 +322,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 5a8ea505261e133380a24a1d91641808a785d5f8 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Fri, 28 Mar 2025 09:30:55 +0100 Subject: [PATCH 378/426] E2E tests for `telemetryIngest` (#4668) --- .github/actions/run-e2e/action.yaml | 8 + .github/scripts/run-e2e-tests.sh | 3 + .github/workflows/e2e-tests-ondemand.yaml | 3 +- .github/workflows/e2e-tests.yaml | 4 + doc/e2e/features.md | 77 +++- hack/make/tests/e2e.mk | 16 + .../dynakube/otelc/service/reconciler.go | 72 ++-- .../dynakube/otelc/service/reconciler_test.go | 44 +- test/features/consts/consts.go | 12 +- .../telemetryingest/telemetryingest.go | 389 ++++++++++++++++++ test/helpers/components/dynakube/options.go | 30 ++ test/helpers/logs/logs.go | 12 + test/helpers/tenant/secrets.go | 11 +- test/helpers/tls/tls.go | 34 ++ test/scenarios/no_csi/no_csi_test.go | 5 + test/testdata/custom-cas/README.md | 6 + .../custom-cas/tls-telemetry-ingest.crt | 21 + .../custom-cas/tls-telemetry-ingest.key | 28 ++ 18 files changed, 719 insertions(+), 56 deletions(-) create mode 100644 test/features/telemetryingest/telemetryingest.go create mode 100644 test/helpers/tls/tls.go create mode 100644 test/testdata/custom-cas/tls-telemetry-ingest.crt create mode 100644 test/testdata/custom-cas/tls-telemetry-ingest.key diff --git a/.github/actions/run-e2e/action.yaml b/.github/actions/run-e2e/action.yaml index 4423a4304e..51cac21920 100644 --- a/.github/actions/run-e2e/action.yaml +++ b/.github/actions/run-e2e/action.yaml @@ -17,6 +17,9 @@ inputs: tenant1-apitoken: description: The API token of Tenant 1 required: true + tenant1-dataingesttoken: + description: The data ingest token of Tenant 1 + required: true tenant1-oauth-client-id: description: The OAuth client ID of Tenant 1 required: true @@ -32,6 +35,9 @@ inputs: tenant2-apitoken: description: The API token of Tenant 2 required: true + tenant2-dataingesttoken: + description: The data ingest token of Tenant 2 + required: true github-token: description: The GitHub token required: true @@ -75,11 +81,13 @@ runs: TARGET_BRANCH: ${{ inputs.target-branch || 'main' }} TENANT1_NAME: ${{ inputs.tenant1-name }} TENANT1_APITOKEN: ${{ inputs.tenant1-apitoken }} + TENANT1_DATAINGESTTOKEN: ${{ inputs.tenant1-dataingesttoken }} TENANT1_OAUTH_CLIENT_ID: ${{ inputs.tenant1-oauth-client-id }} TENANT1_OAUTH_SECRET: ${{ inputs.tenant1-oauth-secret }} TENANT1_OAUTH_URN: ${{ inputs.tenant1-oauth-urn }} TENANT2_NAME: ${{ inputs.tenant2-name }} TENANT2_APITOKEN: ${{ inputs.tenant2-apitoken }} + TENANT2_DATAINGESTTOKEN: ${{ inputs.tenant2-dataingesttoken }} - name: Destroy cluster shell: bash run: ref/.github/scripts/destroy-cluster.sh diff --git a/.github/scripts/run-e2e-tests.sh b/.github/scripts/run-e2e-tests.sh index 82360335db..16b8fb360b 100755 --- a/.github/scripts/run-e2e-tests.sh +++ b/.github/scripts/run-e2e-tests.sh @@ -26,6 +26,7 @@ cat << EOF > single-tenant.yaml tenantUid: $TENANT1_NAME apiUrl: https://$TENANT1_NAME.dev.dynatracelabs.com/api apiToken: $TENANT1_APITOKEN +dataIngestToken: $TENANT1_DATAINGESTTOKEN EOF cat << EOF > multi-tenant.yaml @@ -33,9 +34,11 @@ tenants: - tenantUid: $TENANT1_NAME apiUrl: https://$TENANT1_NAME.dev.dynatracelabs.com/api apiToken: $TENANT1_APITOKEN + dataIngestToken: $TENANT1_DATAINGESTTOKEN - tenantUid: $TENANT2_NAME apiUrl: https://$TENANT2_NAME.dev.dynatracelabs.com/api apiToken: $TENANT2_APITOKEN + dataIngestToken: $TENANT2_DATAINGESTTOKEN EOF cat << EOF > edgeconnect-tenant.yaml diff --git a/.github/workflows/e2e-tests-ondemand.yaml b/.github/workflows/e2e-tests-ondemand.yaml index e94dbb5c83..f45bede8ea 100644 --- a/.github/workflows/e2e-tests-ondemand.yaml +++ b/.github/workflows/e2e-tests-ondemand.yaml @@ -67,14 +67,15 @@ jobs: target-branch: ${{ env.branch }} tenant1-name: ${{ secrets.TENANT1_NAME }} tenant1-apitoken: ${{ secrets.TENANT1_APITOKEN }} + tenant1-dataingesttoken: ${{ secrets.TENANT1_DATAINGESTTOKEN }} tenant1-oauth-client-id: ${{ secrets.TENANT1_OAUTH_CLIENT_ID }} tenant1-oauth-secret: ${{ secrets.TENANT1_OAUTH_SECRET }} tenant1-oauth-urn: ${{ secrets.TENANT1_OAUTH_URN }} tenant2-name: ${{ secrets.TENANT2_NAME }} tenant2-apitoken: ${{ secrets.TENANT2_APITOKEN }} + tenant2-dataingesttoken: ${{ secrets.TENANT2_DATAINGESTTOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }} - notify-failure: name: Notify failure in Slack environment: E2E diff --git a/.github/workflows/e2e-tests.yaml b/.github/workflows/e2e-tests.yaml index 9cb9b003be..06513209cf 100644 --- a/.github/workflows/e2e-tests.yaml +++ b/.github/workflows/e2e-tests.yaml @@ -32,11 +32,13 @@ jobs: target-branch: ${{ github.event.inputs.target }} tenant1-name: ${{ secrets.TENANT1_NAME }} tenant1-apitoken: ${{ secrets.TENANT1_APITOKEN }} + tenant1-dataingesttoken: ${{ secrets.TENANT1_DATAINGESTTOKEN }} tenant1-oauth-client-id: ${{ secrets.TENANT1_OAUTH_CLIENT_ID }} tenant1-oauth-secret: ${{ secrets.TENANT1_OAUTH_SECRET }} tenant1-oauth-urn: ${{ secrets.TENANT1_OAUTH_URN }} tenant2-name: ${{ secrets.TENANT2_NAME }} tenant2-apitoken: ${{ secrets.TENANT2_APITOKEN }} + tenant2-dataingesttoken: ${{ secrets.TENANT2_DATAINGESTTOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }} run-in-ocp: name: Run in OpenShift latest (${{ github.event.inputs.target || 'main' }}) @@ -55,11 +57,13 @@ jobs: target-branch: ${{ github.event.inputs.target }} tenant1-name: ${{ secrets.TENANT1_NAME }} tenant1-apitoken: ${{ secrets.TENANT1_APITOKEN }} + tenant1-dataingesttoken: ${{ secrets.TENANT1_DATAINGESTTOKEN }} tenant1-oauth-client-id: ${{ secrets.TENANT1_OAUTH_CLIENT_ID }} tenant1-oauth-secret: ${{ secrets.TENANT1_OAUTH_SECRET }} tenant1-oauth-urn: ${{ secrets.TENANT1_OAUTH_URN }} tenant2-name: ${{ secrets.TENANT2_NAME }} tenant2-apitoken: ${{ secrets.TENANT2_APITOKEN }} + tenant2-dataingesttoken: ${{ secrets.TENANT2_DATAINGESTTOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }} notify-slack: name: Notify test results in Slack diff --git a/doc/e2e/features.md b/doc/e2e/features.md index a5746cad0d..450b0f14b0 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -433,11 +433,13 @@ const ( AgCertificateAndPrivateKey = "custom-cas/agcrtkey.p12" AgCertificateAndPrivateKeyField = "server.p12" AgSecretName = "ag-ca" - DevRegistryPullSecretName = "devregistry" - EecImageRepo = "478983378254.dkr.ecr.us-east-1.amazonaws.com/dynatrace/dynatrace-eec" - EecImageTag = "1.303.0.20240930-183404" - LogMonitoringImageRepo = "public.ecr.aws/dynatrace/dynatrace-logmodule" - LogMonitoringImageTag = "1.309.59.20250319-140247" + TelemetryIngestTLSSecretName = "telemetry-ingest-tls" + + DevRegistryPullSecretName = "devregistry" + EecImageRepo = "478983378254.dkr.ecr.us-east-1.amazonaws.com/dynatrace/dynatrace-eec" + EecImageTag = "1.303.0.20240930-183404" + LogMonitoringImageRepo = "public.ecr.aws/dynatrace/dynatrace-logmodule" + LogMonitoringImageTag = "1.309.59.20250319-140247" ) ``` @@ -591,3 +593,68 @@ type CustomResources struct { // contains filtered or unexported fields } ``` + +# telemetryingest + +```go +import "github.com/Dynatrace/dynatrace-operator/test/features/telemetryingest" +``` + +## Index + +- [Constants](<#constants>) +- [func OtelCollectorConfigUpdate(t *testing.T) features.Feature](<#OtelCollectorConfigUpdate>) +- [func WithLocalActiveGateAndCleanup(t *testing.T) features.Feature](<#WithLocalActiveGateAndCleanup>) +- [func WithPublicActiveGate(t *testing.T) features.Feature](<#WithPublicActiveGate>) +- [func WithTelemetryIngestEndpointTLS(t *testing.T) features.Feature](<#WithTelemetryIngestEndpointTLS>) + +## Constants + + + +```go +const ( + TelemetryIngestTLSCrt = "custom-cas/tls-telemetry-ingest.crt" + TelemetryIngestTLSKey = "custom-cas/tls-telemetry-ingest.key" +) +``` + + + +## func [OtelCollectorConfigUpdate]() + +```go +func OtelCollectorConfigUpdate(t *testing.T) features.Feature +``` + +Make sure the Otel collector configuration is updated and pods are restarted when protocols for telemetryIngest change + + + +## func [WithLocalActiveGateAndCleanup]() + +```go +func WithLocalActiveGateAndCleanup(t *testing.T) features.Feature +``` + +Rollout of OTel collector and a local in-cluster ActiveGate. Make sure that components are cleaned up after telemetryIngest gets disabled. + + + +## func [WithPublicActiveGate]() + +```go +func WithPublicActiveGate(t *testing.T) features.Feature +``` + +Rollout of OTel collector when no ActiveGate is configured in the Dynakube + + + +## func [WithTelemetryIngestEndpointTLS]() + +```go +func WithTelemetryIngestEndpointTLS(t *testing.T) features.Feature +``` + +Rollout of OTel collector with TLS secret to secure the telemetryIngest endpoints diff --git a/hack/make/tests/e2e.mk b/hack/make/tests/e2e.mk index 2d1f01febb..895e64ea4e 100644 --- a/hack/make/tests/e2e.mk +++ b/hack/make/tests/e2e.mk @@ -161,3 +161,19 @@ test/e2e/hostmonitoring/withoutcsi: manifests/crd/helm ## Runs CloudNative default e2e test only test/e2e/cloudnative/withoutcsi: manifests/crd/helm go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "cloudnative" $(SKIPCLEANUP) + +## Runs TelemetryIngest related e2e tests +test/e2e/telemetryingest: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "telemetryingest-.*" $(SKIPCLEANUP) + +test/e2e/telemetryingest/public-active-gate: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "telemetryingest-with-public-ag-components-rollout" $(SKIPCLEANUP) + +test/e2e/telemetryingest/local-active-gate-and-cleanup: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "telemetryingest-with-local-active-gate-component-rollout-and-cleanup-after-disable" $(SKIPCLEANUP) + +test/e2e/telemetryingest/otel-collector-endpoint-tls: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "telemetryingest-with-otel-collector-endpoint-tls" $(SKIPCLEANUP) + +test/e2e/telemetryingest/otel-collector-config-udpate: manifests/crd/helm + go test -v -tags "$(shell ./hack/build/create_go_build_tags.sh true)" -timeout 20m -count=1 ./test/scenarios/no_csi -args --feature "telemetryingest-configuration-update" $(SKIPCLEANUP) diff --git a/pkg/controllers/dynakube/otelc/service/reconciler.go b/pkg/controllers/dynakube/otelc/service/reconciler.go index cf07365027..5b51c6ac10 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler.go @@ -14,14 +14,22 @@ import ( ) const ( - portNameZipkin = "zipkin" - portNameOtlpGrpc = "otlp-grpc" - portNameOtlpHttp = "otlp-http" - portNameJaegerGrpc = "jaeger-grpc" - portNameJaegerThriftBinary = "jaeger-thrift-binary" - portNameJaegerThriftCompact = "jaeger-thrift-compact" - portNameJaegerThriftHttp = "jaeger-thrift-http" - portNameStatsd = "statsd" + zipkinPortName = "zipkin" + zipkinPort = 9411 + otlpGrpcPortName = "otlp-grpc" + otlpGrpcPort = 4317 + otlpHttpPortName = "otlp-http" + otlpHttpPort = 4318 + jaegerGrpcPortName = "jaeger-grpc" + jaegerGrpcPort = 14250 + jaegerThriftBinaryPortName = "jaeger-thrift-binary" + jaegerThriftBinaryPort = 6832 + jaegerThriftCompactPortName = "jaeger-thrift-compact" + jaegerThriftCompactPort = 6831 + jaegerThriftHttpPortName = "jaeger-thrift-http" + jaegerThriftHttpPort = 14268 + statsdPortName = "statsd" + statsdPort = 8125 ) type Reconciler struct { @@ -135,58 +143,58 @@ func buildServicePortList(protocols []otelcgen.Protocol) []corev1.ServicePort { switch protocol { case otelcgen.ZipkinProtocol: svcPorts = append(svcPorts, corev1.ServicePort{ - Name: portNameZipkin, - Port: 9411, + Name: zipkinPortName, + Port: zipkinPort, Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromInt32(9411), + TargetPort: intstr.FromInt32(zipkinPort), }) case otelcgen.OtlpProtocol: svcPorts = append(svcPorts, corev1.ServicePort{ - Name: portNameOtlpGrpc, - Port: 4317, + Name: otlpGrpcPortName, + Port: otlpGrpcPort, Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromInt32(4317), + TargetPort: intstr.FromInt32(otlpGrpcPort), }, corev1.ServicePort{ - Name: portNameOtlpHttp, - Port: 4318, + Name: otlpHttpPortName, + Port: otlpHttpPort, Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromInt32(4318), + TargetPort: intstr.FromInt32(otlpHttpPort), }) case otelcgen.JaegerProtocol: svcPorts = append(svcPorts, corev1.ServicePort{ - Name: portNameJaegerGrpc, - Port: 14250, + Name: jaegerGrpcPortName, + Port: jaegerGrpcPort, Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromInt32(14250), + TargetPort: intstr.FromInt32(jaegerGrpcPort), }, corev1.ServicePort{ - Name: portNameJaegerThriftBinary, - Port: 6832, + Name: jaegerThriftBinaryPortName, + Port: jaegerThriftBinaryPort, Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromInt32(6832), + TargetPort: intstr.FromInt32(jaegerThriftBinaryPort), }, corev1.ServicePort{ - Name: portNameJaegerThriftCompact, - Port: 6831, + Name: jaegerThriftCompactPortName, + Port: jaegerThriftCompactPort, Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromInt32(6831), + TargetPort: intstr.FromInt32(jaegerThriftCompactPort), }, corev1.ServicePort{ - Name: portNameJaegerThriftHttp, - Port: 14268, + Name: jaegerThriftHttpPortName, + Port: jaegerThriftHttpPort, Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromInt32(14268), + TargetPort: intstr.FromInt32(jaegerThriftHttpPort), }) case otelcgen.StatsdProtocol: svcPorts = append(svcPorts, corev1.ServicePort{ - Name: portNameStatsd, - Port: 8125, + Name: statsdPortName, + Port: statsdPort, Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromInt32(8125), + TargetPort: intstr.FromInt32(statsdPort), }) default: log.Info("unknown telemetry service protocol ignored", "protocol", protocol) diff --git a/pkg/controllers/dynakube/otelc/service/reconciler_test.go b/pkg/controllers/dynakube/otelc/service/reconciler_test.go index a606b25fdc..f5c5826548 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler_test.go @@ -49,14 +49,38 @@ func TestService(t *testing.T) { require.NoError(t, err) require.Len(t, service.Spec.Ports, 8) - assert.Equal(t, portNameOtlpGrpc, service.Spec.Ports[0].Name) - assert.Equal(t, portNameOtlpHttp, service.Spec.Ports[1].Name) - assert.Equal(t, portNameJaegerGrpc, service.Spec.Ports[2].Name) - assert.Equal(t, portNameJaegerThriftBinary, service.Spec.Ports[3].Name) - assert.Equal(t, portNameJaegerThriftCompact, service.Spec.Ports[4].Name) - assert.Equal(t, portNameJaegerThriftHttp, service.Spec.Ports[5].Name) - assert.Equal(t, portNameStatsd, service.Spec.Ports[6].Name) - assert.Equal(t, portNameZipkin, service.Spec.Ports[7].Name) + assert.Equal(t, otlpGrpcPortName, service.Spec.Ports[0].Name) + assert.Equal(t, int32(4317), service.Spec.Ports[0].Port) + assert.Equal(t, int32(4317), service.Spec.Ports[0].TargetPort.IntVal) + + assert.Equal(t, otlpHttpPortName, service.Spec.Ports[1].Name) + assert.Equal(t, int32(4318), service.Spec.Ports[1].Port) + assert.Equal(t, int32(4318), service.Spec.Ports[1].TargetPort.IntVal) + + assert.Equal(t, jaegerGrpcPortName, service.Spec.Ports[2].Name) + assert.Equal(t, int32(14250), service.Spec.Ports[2].Port) + assert.Equal(t, int32(14250), service.Spec.Ports[2].TargetPort.IntVal) + + assert.Equal(t, jaegerThriftBinaryPortName, service.Spec.Ports[3].Name) + assert.Equal(t, int32(6832), service.Spec.Ports[3].Port) + assert.Equal(t, int32(6832), service.Spec.Ports[3].TargetPort.IntVal) + + assert.Equal(t, jaegerThriftCompactPortName, service.Spec.Ports[4].Name) + assert.Equal(t, int32(6831), service.Spec.Ports[4].Port) + assert.Equal(t, int32(6831), service.Spec.Ports[4].TargetPort.IntVal) + + assert.Equal(t, jaegerThriftHttpPortName, service.Spec.Ports[5].Name) + assert.Equal(t, int32(14268), service.Spec.Ports[5].Port) + assert.Equal(t, int32(14268), service.Spec.Ports[5].TargetPort.IntVal) + + assert.Equal(t, statsdPortName, service.Spec.Ports[6].Name) + assert.Equal(t, int32(8125), service.Spec.Ports[6].Port) + assert.Equal(t, int32(8125), service.Spec.Ports[6].TargetPort.IntVal) + + assert.Equal(t, zipkinPortName, service.Spec.Ports[7].Name) + assert.Equal(t, int32(9411), service.Spec.Ports[7].Port) + assert.Equal(t, int32(9411), service.Spec.Ports[7].TargetPort.IntVal) + require.Len(t, dk.Status.Conditions, 1) assert.Equal(t, serviceConditionType, dk.Status.Conditions[0].Type) assert.Equal(t, conditions.ServiceCreatedReason, dk.Status.Conditions[0].Reason) @@ -78,8 +102,8 @@ func TestService(t *testing.T) { require.NoError(t, err) require.Len(t, service.Spec.Ports, 2) - assert.Equal(t, portNameZipkin, service.Spec.Ports[0].Name) - assert.Equal(t, portNameStatsd, service.Spec.Ports[1].Name) + assert.Equal(t, zipkinPortName, service.Spec.Ports[0].Name) + assert.Equal(t, statsdPortName, service.Spec.Ports[1].Name) require.Len(t, dk.Status.Conditions, 1) assert.Equal(t, serviceConditionType, dk.Status.Conditions[0].Type) diff --git a/test/features/consts/consts.go b/test/features/consts/consts.go index 74d27c9971..8a2bd0c1ba 100644 --- a/test/features/consts/consts.go +++ b/test/features/consts/consts.go @@ -5,9 +5,11 @@ const ( AgCertificateAndPrivateKey = "custom-cas/agcrtkey.p12" AgCertificateAndPrivateKeyField = "server.p12" AgSecretName = "ag-ca" - DevRegistryPullSecretName = "devregistry" - EecImageRepo = "478983378254.dkr.ecr.us-east-1.amazonaws.com/dynatrace/dynatrace-eec" - EecImageTag = "1.303.0.20240930-183404" - LogMonitoringImageRepo = "public.ecr.aws/dynatrace/dynatrace-logmodule" - LogMonitoringImageTag = "1.309.59.20250319-140247" + TelemetryIngestTLSSecretName = "telemetry-ingest-tls" + + DevRegistryPullSecretName = "devregistry" + EecImageRepo = "478983378254.dkr.ecr.us-east-1.amazonaws.com/dynatrace/dynatrace-eec" + EecImageTag = "1.303.0.20240930-183404" + LogMonitoringImageRepo = "public.ecr.aws/dynatrace/dynatrace-logmodule" + LogMonitoringImageTag = "1.309.59.20250319-140247" ) diff --git a/test/features/telemetryingest/telemetryingest.go b/test/features/telemetryingest/telemetryingest.go new file mode 100644 index 0000000000..0ccaca747c --- /dev/null +++ b/test/features/telemetryingest/telemetryingest.go @@ -0,0 +1,389 @@ +//go:build e2e + +package telemetryingest + +import ( + "context" + "os" + "path" + "strings" + "testing" + "time" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + otelcconsts "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" + "github.com/Dynatrace/dynatrace-operator/test/features/consts" + "github.com/Dynatrace/dynatrace-operator/test/helpers" + componentActiveGate "github.com/Dynatrace/dynatrace-operator/test/helpers/components/activegate" + componentDynakube "github.com/Dynatrace/dynatrace-operator/test/helpers/components/dynakube" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/pod" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/secret" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/statefulset" + "github.com/Dynatrace/dynatrace-operator/test/helpers/logs" + "github.com/Dynatrace/dynatrace-operator/test/helpers/tenant" + "github.com/Dynatrace/dynatrace-operator/test/helpers/tls" + "github.com/Dynatrace/dynatrace-operator/test/project" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/e2e-framework/klient/wait" + "sigs.k8s.io/e2e-framework/klient/wait/conditions" + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" +) + +const ( + activeGateComponent = "activegate" + TelemetryIngestTLSCrt = "custom-cas/tls-telemetry-ingest.crt" + TelemetryIngestTLSKey = "custom-cas/tls-telemetry-ingest.key" +) + +// Rollout of OTel collector when no ActiveGate is configured in the Dynakube +func WithPublicActiveGate(t *testing.T) features.Feature { + builder := features.New("telemetryingest-with-public-ag-components-rollout") + + secretConfig := tenant.GetSingleTenantSecret(t) + + options := []componentDynakube.Option{ + componentDynakube.WithApiUrl(secretConfig.ApiUrl), + componentDynakube.WithTelemetryIngestEnabled(true), + } + + testDynakube := *componentDynakube.New(options...) + + componentDynakube.Install(builder, helpers.LevelAssess, &secretConfig, testDynakube) + + builder.Assess("otel collector started", statefulset.WaitFor(testDynakube.OtelCollectorStatefulsetName(), testDynakube.Namespace)) + builder.Assess("otel collector config created", checkOtelCollectorConfig(&testDynakube)) + builder.Assess("otel collector service created", checkOtelCollectorService(&testDynakube)) + + componentDynakube.Delete(builder, helpers.LevelTeardown, testDynakube) + + builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(testDynakube.Name, testDynakube.Namespace)) + + return builder.Feature() +} + +// Rollout of OTel collector and a local in-cluster ActiveGate. Make sure that components are cleaned up after telemetryIngest gets disabled. +func WithLocalActiveGateAndCleanup(t *testing.T) features.Feature { + builder := features.New("telemetryingest-with-local-active-gate-component-rollout-and-cleanup-after-disable") + + secretConfig := tenant.GetSingleTenantSecret(t) + + optionsTelemetryIngestEnabled := []componentDynakube.Option{ + componentDynakube.WithApiUrl(secretConfig.ApiUrl), + componentDynakube.WithTelemetryIngestEnabled(true, "zipkin"), + componentDynakube.WithActiveGateModules(activegate.KubeMonCapability.DisplayName), + componentDynakube.WithActiveGateTLSSecret(consts.AgSecretName), + } + + testDynakube := *componentDynakube.New(optionsTelemetryIngestEnabled...) + + agSecret, err := createAgTlsSecret(testDynakube.Namespace) + require.NoError(t, err, "failed to create ag-tls secret") + builder.Assess("create AG TLS secret", secret.Create(agSecret)) + + componentDynakube.Install(builder, helpers.LevelAssess, &secretConfig, testDynakube) + builder.Assess("active gate pod is running", checkActiveGateContainer(&testDynakube)) + + builder.Assess("otel collector started", statefulset.WaitFor(testDynakube.OtelCollectorStatefulsetName(), testDynakube.Namespace)) + builder.Assess("otel collector config created", checkOtelCollectorConfig(&testDynakube)) + builder.Assess("otel collector service created", checkOtelCollectorService(&testDynakube)) + + optionsTelemetryIngestDisabled := []componentDynakube.Option{ + componentDynakube.WithApiUrl(secretConfig.ApiUrl), + componentDynakube.WithTelemetryIngestEnabled(false), + componentDynakube.WithActiveGateModules(activegate.KubeMonCapability.DisplayName), + componentDynakube.WithActiveGateTLSSecret(consts.AgSecretName), + } + + testDynakubeNoTelemetryIngest := *componentDynakube.New(optionsTelemetryIngestDisabled...) + componentDynakube.Update(builder, helpers.LevelAssess, testDynakubeNoTelemetryIngest) + + builder.Assess("otel collector shutdown", waitForShutdown(testDynakubeNoTelemetryIngest.OtelCollectorStatefulsetName(), testDynakubeNoTelemetryIngest.Namespace)) + builder.Assess("otel collector config removed", checkOtelCollectorConfigRemoved(&testDynakubeNoTelemetryIngest)) + builder.Assess("otel collector service removed", checkOtelCollectorServiceRemoved(&testDynakubeNoTelemetryIngest)) + + componentDynakube.Delete(builder, helpers.LevelTeardown, testDynakubeNoTelemetryIngest) + + builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(testDynakubeNoTelemetryIngest.Name, testDynakubeNoTelemetryIngest.Namespace)) + + return builder.Feature() +} + +// Rollout of OTel collector with TLS secret to secure the telemetryIngest endpoints +func WithTelemetryIngestEndpointTLS(t *testing.T) features.Feature { + builder := features.New("telemetryingest-with-otel-collector-endpoint-tls") + + secretConfig := tenant.GetSingleTenantSecret(t) + + options := []componentDynakube.Option{ + componentDynakube.WithApiUrl(secretConfig.ApiUrl), + componentDynakube.WithTelemetryIngestEnabled(true), + componentDynakube.WithTelemetryIngestEndpointTLS(consts.TelemetryIngestTLSSecretName), + } + + testDynakube := *componentDynakube.New(options...) + + tlsSecret, err := tls.CreateTestdataTLSSecret(testDynakube.Namespace, consts.TelemetryIngestTLSSecretName, TelemetryIngestTLSKey, TelemetryIngestTLSCrt) + require.NoError(t, err, "failed to create TLS secret for otel collector endpoints") + + builder.Assess("create OTel collector endpoint TLS secret", secret.Create(tlsSecret)) + + componentDynakube.Install(builder, helpers.LevelAssess, &secretConfig, testDynakube) + + builder.Assess("otel collector started", statefulset.WaitFor(testDynakube.OtelCollectorStatefulsetName(), testDynakube.Namespace)) + builder.Assess("otel collector config created", checkOtelCollectorConfig(&testDynakube)) + builder.Assess("otel collector service created", checkOtelCollectorService(&testDynakube)) + + componentDynakube.Delete(builder, helpers.LevelTeardown, testDynakube) + builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(testDynakube.Name, testDynakube.Namespace)) + builder.WithTeardown("deleted OTel collector endpoint TLS secret", secret.Delete(tlsSecret)) + + return builder.Feature() +} + +// Make sure the Otel collector configuration is updated and pods are restarted when protocols for telemetryIngest change +func OtelCollectorConfigUpdate(t *testing.T) features.Feature { + builder := features.New("telemetryingest-configuration-update") + + secretConfig := tenant.GetSingleTenantSecret(t) + + optionsZipkin := []componentDynakube.Option{ + componentDynakube.WithApiUrl(secretConfig.ApiUrl), + componentDynakube.WithTelemetryIngestEnabled(true, "zipkin"), + } + + testDynakubeZipkin := *componentDynakube.New(optionsZipkin...) + + componentDynakube.Install(builder, helpers.LevelAssess, &secretConfig, testDynakubeZipkin) + + builder.Assess("otel collector started", statefulset.WaitFor(testDynakubeZipkin.OtelCollectorStatefulsetName(), testDynakubeZipkin.Namespace)) + builder.Assess("otel collector config created", checkOtelCollectorConfig(&testDynakubeZipkin)) + builder.Assess("otel collector service created", checkOtelCollectorService(&testDynakubeZipkin)) + + var zipkinConfigResourceVersion string + builder.Assess("otel collector configuration timestamp", getOtelCollectorConfigResourceVersion(&testDynakubeZipkin, &zipkinConfigResourceVersion)) + + var zipkinPodStartTs time.Time + builder.Assess("otel collector pod creation timestamp", getOtelCollectorPodTimestamp(&testDynakubeZipkin, &zipkinPodStartTs)) + + optionsJaeger := []componentDynakube.Option{ + componentDynakube.WithApiUrl(secretConfig.ApiUrl), + componentDynakube.WithTelemetryIngestEnabled(true, "jaeger"), + } + + testDynakubeJaeger := *componentDynakube.New(optionsJaeger...) + componentDynakube.Update(builder, helpers.LevelAssess, testDynakubeJaeger) + + builder.Assess("otel collector started", statefulset.WaitFor(testDynakubeJaeger.OtelCollectorStatefulsetName(), testDynakubeJaeger.Namespace)) + builder.Assess("otel collector config created", checkOtelCollectorConfig(&testDynakubeJaeger)) + builder.Assess("otel collector service created", checkOtelCollectorService(&testDynakubeJaeger)) + + var jaegerConfigResourceVersion string + builder.Assess("otel collector configuration timestamp", getOtelCollectorConfigResourceVersion(&testDynakubeJaeger, &jaegerConfigResourceVersion)) + builder.Assess("otel collector configuration updated", func(ctx context.Context, t *testing.T, config *envconf.Config) context.Context { + assert.NotEqual(t, jaegerConfigResourceVersion, zipkinConfigResourceVersion) + + return ctx + }) + + var jaegerPodStartTs time.Time + builder.Assess("otel collector pod creation timestamp", getOtelCollectorPodTimestamp(&testDynakubeJaeger, &jaegerPodStartTs)) + builder.Assess("otel collector pod restarted", func(ctx context.Context, t *testing.T, config *envconf.Config) context.Context { + assert.Greater(t, jaegerPodStartTs, zipkinPodStartTs) + + return ctx + }) + + componentDynakube.Delete(builder, helpers.LevelTeardown, testDynakubeJaeger) + + builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(testDynakubeJaeger.Name, testDynakubeJaeger.Namespace)) + + return builder.Feature() +} + +func checkActiveGateContainer(dk *dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + resources := envConfig.Client().Resources() + + var activeGatePod corev1.Pod + require.NoError(t, resources.WithNamespace(dk.Namespace).Get(ctx, componentActiveGate.GetActiveGatePodName(dk, activeGateComponent), dk.Namespace, &activeGatePod)) + + require.NotNil(t, activeGatePod.Spec) + require.NotEmpty(t, activeGatePod.Spec.Containers) + + assertTelemetryIngestActiveGateModulesAreActive(ctx, t, envConfig, dk) + + return ctx + } +} + +func assertTelemetryIngestActiveGateModulesAreActive(ctx context.Context, t *testing.T, envConfig *envconf.Config, dk *dynakube.DynaKube) { + var expectedModules = []string{"log_analytics_collector", "otlp_ingest"} + var expectedServices = []string{"generic_ingest"} + + log := componentActiveGate.ReadActiveGateLog(ctx, t, envConfig, dk, activeGateComponent) + + /* componentActiveGate 2025-03-24 15:08:02 UTC INFO [] [, ServicesManager] Services active: [generic_filecache, local_support_archive, generic_ingest] */ + servicesLog := logs.FindLineContainingText(log, "Services active:") + for _, service := range expectedServices { + assert.Contains(t, servicesLog, service, "ActiveGate services is not active: '"+service+"'") + } + + head := strings.SplitAfter(log, "[, ModulesManager] Modules:") + require.Len(t, head, 2, "list of AG active modules not found") + + tail := strings.SplitAfter(head[1], "Lifecycle listeners:") + require.Len(t, head, 2, "list of AG active modules not found") + + /* + Expected log messages of the Gateway process: + `Active: + log_analytics_collector" + generic_ingest" + otlp_ingest" + Lifecycle listeners:` + + Warning: modules are printed in random order. + */ + for _, module := range expectedModules { + assert.Contains(t, tail[0], module, "ActiveGate module is not active: '"+module+"'") + } +} + +func checkOtelCollectorConfig(dk *dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + otelCollectorConfig, err := getOtelCollectorConfigMap(dk, ctx, envConfig) + require.NoError(t, err, "failed to get otel collector config") + + require.NotNil(t, otelCollectorConfig.Data) + + return ctx + } +} + +func checkOtelCollectorConfigRemoved(dk *dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + _, err := getOtelCollectorConfigMap(dk, ctx, envConfig) + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err), "ConfigMap still exists") + + return ctx + } +} + +func getOtelCollectorConfigResourceVersion(dk *dynakube.DynaKube, resourceVersion *string) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + otelCollectorConfig, err := getOtelCollectorConfigMap(dk, ctx, envConfig) + require.NoError(t, err, "failed to get otel collector config") + + *resourceVersion = otelCollectorConfig.ResourceVersion + + return ctx + } +} + +func checkOtelCollectorService(dk *dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + otelCollectorService, err := getOtelCollectorService(dk, ctx, envConfig) + require.NoError(t, err) + require.NotEmpty(t, otelCollectorService.Spec.Ports) + + return ctx + } +} + +func checkOtelCollectorServiceRemoved(dk *dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + _, err := getOtelCollectorService(dk, ctx, envConfig) + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err), "Service still exists") + + return ctx + } +} + +func getOtelCollectorPodTimestamp(dk *dynakube.DynaKube, startTimestamp *time.Time) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + resources := envConfig.Client().Resources() + + podList := pod.GetPodsForOwner(ctx, t, resources, dk.OtelCollectorStatefulsetName(), dk.Namespace) + + expectedPodCount := 1 + if dk.Spec.Templates.OpenTelemetryCollector.Replicas != nil && *dk.Spec.Templates.OpenTelemetryCollector.Replicas >= 1 { + expectedPodCount = int(*dk.Spec.Templates.OpenTelemetryCollector.Replicas) + } + assert.Len(t, podList.Items, expectedPodCount) + + require.NotEmpty(t, podList.Items) + *startTimestamp = podList.Items[0].Status.StartTime.Time + + return ctx + } +} + +func getOtelCollectorConfigMap(dk *dynakube.DynaKube, ctx context.Context, envConfig *envconf.Config) (*corev1.ConfigMap, error) { + resources := envConfig.Client().Resources() + + var otelCollectorConfig corev1.ConfigMap + err := resources.WithNamespace(dk.Namespace).Get(ctx, dk.Name+otelcconsts.TelemetryCollectorConfigmapSuffix, dk.Namespace, &otelCollectorConfig) + + if err != nil { + return nil, err + } + + return &otelCollectorConfig, nil +} + +func getOtelCollectorService(dk *dynakube.DynaKube, ctx context.Context, envConfig *envconf.Config) (*corev1.Service, error) { + resources := envConfig.Client().Resources() + + var otelCollectorService corev1.Service + err := resources.WithNamespace(dk.Namespace).Get(ctx, dk.TelemetryIngest().GetServiceName(), dk.Namespace, &otelCollectorService) + + if err != nil { + return nil, err + } + + return &otelCollectorService, nil +} + +func waitForShutdown(name string, namespace string) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + resources := envConfig.Client().Resources() + + err := wait.For(conditions.New(resources).ResourceDeleted(&appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + }), wait.WithTimeout(10*time.Minute)) + + require.NoError(t, err) + + return ctx + } +} + +func createAgTlsSecret(namespace string) (corev1.Secret, error) { + agCrt, err := os.ReadFile(path.Join(project.TestDataDir(), consts.AgCertificate)) + if err != nil { + return corev1.Secret{}, err + } + + agP12, err := os.ReadFile(path.Join(project.TestDataDir(), consts.AgCertificateAndPrivateKey)) + if err != nil { + return corev1.Secret{}, err + } + + return secret.New(consts.AgSecretName, namespace, + map[string][]byte{ + dynakube.TLSCertKey: agCrt, + consts.AgCertificateAndPrivateKeyField: agP12, + }), nil +} diff --git a/test/helpers/components/dynakube/options.go b/test/helpers/components/dynakube/options.go index 072f3f3928..aef24f2776 100644 --- a/test/helpers/components/dynakube/options.go +++ b/test/helpers/components/dynakube/options.go @@ -9,6 +9,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/logmonitoring" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -72,6 +73,15 @@ func WithActiveGate() Option { } } +func WithActiveGateModules(capabilities ...activegate.CapabilityDisplayName) Option { + return func(dk *dynakube.DynaKube) { + dk.Spec.ActiveGate = activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{}, + } + dk.Spec.ActiveGate.Capabilities = append(dk.Spec.ActiveGate.Capabilities, capabilities...) + } +} + func WithMetadataEnrichment() Option { return func(dk *dynakube.DynaKube) { dk.Spec.MetadataEnrichment.Enabled = ptr.To(true) @@ -206,3 +216,23 @@ func WithLogMonitoringImageRefSpec(repo, tag string) Option { } } } + +func WithTelemetryIngestEnabled(enabled bool, protocols ...string) Option { + return func(dk *dynakube.DynaKube) { + if enabled { + dk.Spec.TelemetryIngest = &telemetryingest.Spec{} + dk.Spec.TelemetryIngest.Protocols = append(dk.Spec.TelemetryIngest.Protocols, protocols...) + } else { + dk.Spec.TelemetryIngest = nil + } + } +} + +func WithTelemetryIngestEndpointTLS(secretName string) Option { + return func(dk *dynakube.DynaKube) { + if dk.Spec.TelemetryIngest == nil { + dk.Spec.TelemetryIngest = &telemetryingest.Spec{} + } + dk.Spec.TelemetryIngest.TlsRefName = secretName + } +} diff --git a/test/helpers/logs/logs.go b/test/helpers/logs/logs.go index 666a95219f..fe418b40dc 100644 --- a/test/helpers/logs/logs.go +++ b/test/helpers/logs/logs.go @@ -6,6 +6,7 @@ import ( "bytes" "context" "io" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -44,3 +45,14 @@ func AssertContains(t *testing.T, logStream io.ReadCloser, contains string) { require.Equal(t, int64(buffer.Len()), copied) assert.Contains(t, buffer.String(), contains) } + +func FindLineContainingText(log, searchText string) string { + lines := strings.Split(log, "\n") + for _, line := range lines { + if strings.Contains(line, searchText) { + return line + } + } + + return "" +} diff --git a/test/helpers/tenant/secrets.go b/test/helpers/tenant/secrets.go index cb3468b0c0..22f80541cd 100644 --- a/test/helpers/tenant/secrets.go +++ b/test/helpers/tenant/secrets.go @@ -30,9 +30,10 @@ type Secrets struct { } type Secret struct { - TenantUid string `yaml:"tenantUid"` - ApiUrl string `yaml:"apiUrl"` - ApiToken string `yaml:"apiToken"` + TenantUid string `yaml:"tenantUid"` + ApiUrl string `yaml:"apiUrl"` + ApiToken string `yaml:"apiToken"` + DataIngestToken string `yaml:"dataIngestToken"` } type EdgeConnectSecret struct { @@ -117,6 +118,10 @@ func CreateTenantSecret(secretConfig Secret, name, namespace string) features.Fu }, } + if secretConfig.DataIngestToken != "" { + defaultSecret.Data["dataIngestToken"] = []byte(secretConfig.DataIngestToken) + } + err := envConfig.Client().Resources().Create(ctx, &defaultSecret) if k8serrors.IsAlreadyExists(err) { diff --git a/test/helpers/tls/tls.go b/test/helpers/tls/tls.go new file mode 100644 index 0000000000..d75c0ba123 --- /dev/null +++ b/test/helpers/tls/tls.go @@ -0,0 +1,34 @@ +//go:build e2e + +package tls + +import ( + "os" + "path" + + operatorconsts "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/secret" + "github.com/Dynatrace/dynatrace-operator/test/project" + corev1 "k8s.io/api/core/v1" +) + +func CreateTestdataTLSSecret(namespace string, name string, keyFile string, crtFile string) (corev1.Secret, error) { + tlsCrt, err := os.ReadFile(path.Join(project.TestDataDir(), crtFile)) + if err != nil { + return corev1.Secret{}, err + } + + tlsKey, err := os.ReadFile(path.Join(project.TestDataDir(), keyFile)) + if err != nil { + return corev1.Secret{}, err + } + + tlsSecret := secret.New(name, namespace, + map[string][]byte{ + operatorconsts.TLSCrtDataName: tlsCrt, + operatorconsts.TLSKeyDataName: tlsKey, + }) + tlsSecret.Type = corev1.SecretTypeTLS + + return tlsSecret, nil +} diff --git a/test/scenarios/no_csi/no_csi_test.go b/test/scenarios/no_csi/no_csi_test.go index b69fbc25fd..59225c84c1 100644 --- a/test/scenarios/no_csi/no_csi_test.go +++ b/test/scenarios/no_csi/no_csi_test.go @@ -14,6 +14,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/test/features/extensions" "github.com/Dynatrace/dynatrace-operator/test/features/hostmonitoring" "github.com/Dynatrace/dynatrace-operator/test/features/logmonitoring" + "github.com/Dynatrace/dynatrace-operator/test/features/telemetryingest" "github.com/Dynatrace/dynatrace-operator/test/helpers" "github.com/Dynatrace/dynatrace-operator/test/helpers/components/operator" "github.com/Dynatrace/dynatrace-operator/test/helpers/kubeobjects/environment" @@ -57,6 +58,10 @@ func TestNoCSI(t *testing.T) { logmonitoring.Feature(t), hostmonitoring.WithoutCSI(t), cloudnativeDefault.Feature(t, false, false), + telemetryingest.WithLocalActiveGateAndCleanup(t), + telemetryingest.WithPublicActiveGate(t), + telemetryingest.WithTelemetryIngestEndpointTLS(t), + telemetryingest.OtelCollectorConfigUpdate(t), } testEnv.Test(t, scenarios.FilterFeatures(*cfg, feats)...) diff --git a/test/testdata/custom-cas/README.md b/test/testdata/custom-cas/README.md index 03975c19f0..ce79b56553 100644 --- a/test/testdata/custom-cas/README.md +++ b/test/testdata/custom-cas/README.md @@ -33,3 +33,9 @@ append root certificate to agcrt.pem > openssl x509 -text -noout -in agcrt.pem > > openssl pkcs12 -info -in agcrtkey.p12 -nodes + +## Create telemetry ingest TLS certificate + +> openssl genpkey -algorithm RSA -out tls-telemetry-ingest.key -pkeyopt rsa_keygen_bits:2048 +> openssl req -new -key tls-telemetry-ingest.key -out tls-telemetry-ingest.csr +> openssl x509 -req -in tls-telemetry-ingest.csr -signkey tls-telemetry-ingest.key -out tls-telemetry-ingest.crt -days 36500 -subj '/CN=dynakube-telemetry-ingest.dynatrace' diff --git a/test/testdata/custom-cas/tls-telemetry-ingest.crt b/test/testdata/custom-cas/tls-telemetry-ingest.crt new file mode 100644 index 0000000000..0bc1337f48 --- /dev/null +++ b/test/testdata/custom-cas/tls-telemetry-ingest.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfzCCAmcCFCMpB+z5EszqgCcYvc7IZdKnhy+MMA0GCSqGSIb3DQEBCwUAMHsx +CzAJBgNVBAYTAkFUMRUwEwYDVQQIDAxFMkVUZXN0U3RhdGUxFDASBgNVBAcMC0Uy +RVRlc3RDaXR5MRMwEQYDVQQKDApGb29iYXIgTHRkMRcwFQYDVQQLDA5UZXN0RGVw +YXJ0bWVudDERMA8GA1UEAwwISm9obiBEb2UwIBcNMjUwMzI2MDc1OTA2WhgPMjEy +NTAzMDIwNzU5MDZaMHsxCzAJBgNVBAYTAkFUMRUwEwYDVQQIDAxFMkVUZXN0U3Rh +dGUxFDASBgNVBAcMC0UyRVRlc3RDaXR5MRMwEQYDVQQKDApGb29iYXIgTHRkMRcw +FQYDVQQLDA5UZXN0RGVwYXJ0bWVudDERMA8GA1UEAwwISm9obiBEb2UwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCevAPX5+OrGEL2xdtw5hcMbrN8gaX4 +TOlTFz08Ak+yFQaLbpVgWUsU/Bgn+/75E/I4a2wwFT8K3ooGQAzd/JrIrmILt+9g +vPUsWF7BMbctzDgAi8nlGj9Xu/EZgzrMD6L0p4zbLPQm/fk8VWkokfnahbGN1aLf +Q2O+WCgO15S/2N5OcFcVG40Yi2q1w75R78ytp/OSa62BkKXA2UHvS7NJWdwbRahI +erEEGoozlt85gnhS5+iLeq3K/jn2evrBCWKTPPiOwrg1Q2Mof7q6YsY4dfJKbfw2 +cYj/UH6Yhd7FqjT7Brfyb6VjKFDfWnRVYd/EVEUqWi2VYt2fzV8BLjZvAgMBAAEw +DQYJKoZIhvcNAQELBQADggEBAI92qc9QDbHuWsqSTqjHd1KcZENUE4mrZ6Uc3lB6 +DU9nCozSNDjYIXFT4xusQRjY1sJmT0eYcZWv6VJxWm7tSlMtgfDq/qmV/p47B9NA +FamwxnwAEgdBFfOe5WEgvHLfeNYabsd75cWNor+N3D7J9RVWMGXCg/yuEyCP/PCG +yUX6/0RDq7ICT+Gwl09gDvXSxKAmojBxfw+z5qH4kx0dCteM9xKCFakV/zWfZvZs +Wt2LekBue/532ZH1cvwkcZRQPQ+wSepZsDdWRFlmJwdyzMEuc85gN7TuxTLk788l +ndmghop06v7mUtZj8VKTfCU1UGhed7P39Ihq93g4uZMGl84= +-----END CERTIFICATE----- diff --git a/test/testdata/custom-cas/tls-telemetry-ingest.key b/test/testdata/custom-cas/tls-telemetry-ingest.key new file mode 100644 index 0000000000..b1129e5634 --- /dev/null +++ b/test/testdata/custom-cas/tls-telemetry-ingest.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCevAPX5+OrGEL2 +xdtw5hcMbrN8gaX4TOlTFz08Ak+yFQaLbpVgWUsU/Bgn+/75E/I4a2wwFT8K3ooG +QAzd/JrIrmILt+9gvPUsWF7BMbctzDgAi8nlGj9Xu/EZgzrMD6L0p4zbLPQm/fk8 +VWkokfnahbGN1aLfQ2O+WCgO15S/2N5OcFcVG40Yi2q1w75R78ytp/OSa62BkKXA +2UHvS7NJWdwbRahIerEEGoozlt85gnhS5+iLeq3K/jn2evrBCWKTPPiOwrg1Q2Mo +f7q6YsY4dfJKbfw2cYj/UH6Yhd7FqjT7Brfyb6VjKFDfWnRVYd/EVEUqWi2VYt2f +zV8BLjZvAgMBAAECggEATOe61Pg8jcCLcRQbZW+U6ykXPNNzngFlaiRwPorAIf+d +1CAXrz6T6e7ZpUWqGvNW/47MM9+XU6TOKokNst+X/nK+ff73s17ZSkrmXaPApCe1 +Wk5f2ugEmHUuMrYp3oQU54Pl8qqs/9c80cZv1IAlFYKAq7890f3MbYQ4pDg+kVO1 +oGrEf6/h8kDRln/DyJ3j90KzsYnmoUFhp3Pq2LGPo7RsGOTmLnmgq2xfRmWW0JES +qZ35HJzmw+iCWNsZIKIT9cie7uHoLfiUyY5iN1AnW4cZQr3UWsbE3mxTxm+dExQj +091xNfN3WATw6wX5CrksbalP7QLM9ofkmgp4HJRDwQKBgQDSKc47M9ZcIDJT8LOe +SGkzv7Cs3J4w61w8JiyV/mbhs/dRtB/xxhVT3Kw3fFV5vw2Kf4zXBLXbcn6bBhlJ ++HKBK+cyqwwdlK/X2BJumeeJIgD+iQHHFueZrAD2iVXcPC9uF5IuhIhbkvjzGaP/ +QSR/oy9/9F81yvA+Hpyd+jj0qwKBgQDBWr7WEkE+Xm3TsgZNgazwF4O7rcJ0sTrn +TscZGiNhgTpsXhv7HCpJ9POO3zTG41We2ye0XiZh+vrD4uv2WU0evoB/lrGUoTcX ++J324Gn2n8oeLn/SoINsWUys/td83yAp1M2zAR51IQiHog2g3m3SXj5Eawqwov/J +vImuln/dTQKBgGOtNkX3+QQqtRQAxoAc4eCMWxQxcsnK5y0UAfOF/G+x9mwG3VvD +Uhw7Pmb2jme2yIpWoorcjhAtxoRqKRZfQpenJflvDMj+20OpFFzmm9z7hrMycehm +IaRN4wsK6fERjoFNpqRvcWjVVUOfdpu63r+2uvGaCoot3THpPOjkY50PAoGANb4r +XQUl7VgB3t2UsuZgUzu1+eyKKDU60iArZubE/s0UmBpwXJOvjW7wY73WxZFasxTn +LFMfCAzitp/URlz7+peoz83q/gzxa1BHV994lHxFia4TCVBkNzF7BnqvGp5KKlZj +9mVROe08mbaJYzVwAREA7bNy/TXRMxmci1J5p+ECgYAE8frZjCGisRDb5wZ9Vzni +f8travqyk5VlHLEXqylSfoe4CzV88n2tvF3pypg/li8xG3CICznpw0VSCTR/jR5h +iVh4bPv3gC6KcktKSAEwWblyMa0Egzl2x3ZYFV81Hy2Xi4oZg8JENShPHpKhuGET +9VVS9UFtedFjWJLfxZYFLw== +-----END PRIVATE KEY----- From 2a8ce98bf02d9b0800301771ffb6f3cbc5a8c5a8 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Mon, 31 Mar 2025 12:42:40 +0200 Subject: [PATCH 379/426] Uses ConfigMap instead of Secret for DT API endpoint. (#4674) --- doc/e2e/features.md | 4 +- .../dynakube/otelc/consts/consts.go | 2 +- .../dynakube/otelc/endpoint/conditions.go | 5 + .../otelc/{secret => endpoint}/config.go | 2 +- .../dynakube/otelc/endpoint/reconciler.go | 136 +++++++++++++ .../otelc/endpoint/reconciler_test.go | 168 ++++++++++++++++ pkg/controllers/dynakube/otelc/reconciler.go | 8 +- .../dynakube/otelc/secret/conditions.go | 5 - .../dynakube/otelc/secret/reconciler.go | 136 ------------- .../dynakube/otelc/secret/reconciler_test.go | 184 ------------------ .../dynakube/otelc/statefulset/env.go | 4 +- .../dynakube/otelc/statefulset/env_test.go | 4 +- .../telemetryingest/telemetryingest.go | 37 ++++ 13 files changed, 358 insertions(+), 337 deletions(-) create mode 100644 pkg/controllers/dynakube/otelc/endpoint/conditions.go rename pkg/controllers/dynakube/otelc/{secret => endpoint}/config.go (89%) create mode 100644 pkg/controllers/dynakube/otelc/endpoint/reconciler.go create mode 100644 pkg/controllers/dynakube/otelc/endpoint/reconciler_test.go delete mode 100644 pkg/controllers/dynakube/otelc/secret/conditions.go delete mode 100644 pkg/controllers/dynakube/otelc/secret/reconciler.go delete mode 100644 pkg/controllers/dynakube/otelc/secret/reconciler_test.go diff --git a/doc/e2e/features.md b/doc/e2e/features.md index 450b0f14b0..04139aa523 100644 --- a/doc/e2e/features.md +++ b/doc/e2e/features.md @@ -621,7 +621,7 @@ const ( -## func [OtelCollectorConfigUpdate]() +## func [OtelCollectorConfigUpdate]() ```go func OtelCollectorConfigUpdate(t *testing.T) features.Feature @@ -651,7 +651,7 @@ Rollout of OTel collector when no ActiveGate is configured in the Dynakube -## func [WithTelemetryIngestEndpointTLS]() +## func [WithTelemetryIngestEndpointTLS]() ```go func WithTelemetryIngestEndpointTLS(t *testing.T) features.Feature diff --git a/pkg/controllers/dynakube/otelc/consts/consts.go b/pkg/controllers/dynakube/otelc/consts/consts.go index d84f3373c5..d781099742 100644 --- a/pkg/controllers/dynakube/otelc/consts/consts.go +++ b/pkg/controllers/dynakube/otelc/consts/consts.go @@ -1,7 +1,7 @@ package consts const ( - TelemetryApiCredentialsSecretName = "dynatrace-telemetry-api-credentials" + OtlpApiEndpointConfigMapName = "dynatrace-otlp-api-endpoint" ConfigFieldName = "telemetry.yaml" TelemetryCollectorConfigmapSuffix = "-telemetry-collector-config" diff --git a/pkg/controllers/dynakube/otelc/endpoint/conditions.go b/pkg/controllers/dynakube/otelc/endpoint/conditions.go new file mode 100644 index 0000000000..9419975d45 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/endpoint/conditions.go @@ -0,0 +1,5 @@ +package endpoint + +const ( + configMapConditionType = "OtelpApiEndpointConfigMap" +) diff --git a/pkg/controllers/dynakube/otelc/secret/config.go b/pkg/controllers/dynakube/otelc/endpoint/config.go similarity index 89% rename from pkg/controllers/dynakube/otelc/secret/config.go rename to pkg/controllers/dynakube/otelc/endpoint/config.go index 864bf9f281..70bf7ad36a 100644 --- a/pkg/controllers/dynakube/otelc/secret/config.go +++ b/pkg/controllers/dynakube/otelc/endpoint/config.go @@ -1,4 +1,4 @@ -package secret +package endpoint import "github.com/Dynatrace/dynatrace-operator/pkg/logd" diff --git a/pkg/controllers/dynakube/otelc/endpoint/reconciler.go b/pkg/controllers/dynakube/otelc/endpoint/reconciler.go new file mode 100644 index 0000000000..8b98c5b9f7 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/endpoint/reconciler.go @@ -0,0 +1,136 @@ +package endpoint + +import ( + "context" + "fmt" + + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" + k8sconfigmap "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/configmap" + k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Reconciler struct { + client client.Client + apiReader client.Reader + dk *dynakube.DynaKube +} + +type ReconcilerBuilder func(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler + +func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler { + return &Reconciler{ + client: client, + dk: dk, + apiReader: apiReader, + } +} + +func (r *Reconciler) Reconcile(ctx context.Context) error { + if r.dk.TelemetryIngest().IsEnabled() { + return r.ensureOtlpApiEndpointConfigMap(ctx) + } + + return r.removeOtlpApiEndpointConfigMap(ctx) +} + +func (r *Reconciler) ensureOtlpApiEndpointConfigMap(ctx context.Context) error { + query := k8sconfigmap.Query(r.client, r.apiReader, log) + _, err := query.Get(ctx, types.NamespacedName{Name: consts.OtlpApiEndpointConfigMapName, Namespace: r.dk.Namespace}) + + if err != nil && k8serrors.IsNotFound(err) { + log.Info("creating new config map for telemetry api endpoint") + + configMap, err := r.generateOtlpApiEndpointConfigMap(consts.OtlpApiEndpointConfigMapName) + + if err != nil { + conditions.SetConfigMapGenFailed(r.dk.Conditions(), configMapConditionType, err) + + return err + } + + _, err = hasher.GenerateHash(configMap.Data) + if err != nil { + conditions.SetConfigMapGenFailed(r.dk.Conditions(), configMapConditionType, err) + + return err + } + + err = query.Create(ctx, configMap) + if err != nil { + log.Info("could not create secret for telemetry api credentials", "name", configMap.Name) + conditions.SetKubeApiError(r.dk.Conditions(), configMapConditionType, err) + + return err + } + + conditions.SetConfigMapCreatedOrUpdated(r.dk.Conditions(), configMapConditionType, consts.OtlpApiEndpointConfigMapName) + } else if err != nil { + conditions.SetKubeApiError(r.dk.Conditions(), configMapConditionType, err) + + return err + } + + return nil +} + +func (r *Reconciler) getDtEndpoint() (string, error) { + if r.dk.ActiveGate().IsEnabled() { + tenantUUID, err := r.dk.TenantUUID() + if err != nil { + return "", err + } + + return fmt.Sprintf("https://%s-activegate.dynatrace.svc/e/%s/api/v2/otlp", r.dk.Name, tenantUUID), nil + } + + return r.dk.ApiUrl() + "/v2/otlp", nil +} + +func (r *Reconciler) generateOtlpApiEndpointConfigMap(name string) (secret *corev1.ConfigMap, err error) { + data := make(map[string]string) + + dtEndpoint, err := r.getDtEndpoint() + if err != nil { + return nil, err + } + + data["DT_ENDPOINT"] = dtEndpoint + + configMap, err := k8sconfigmap.Build(r.dk, + name, + data, + k8sconfigmap.SetLabels(k8slabels.NewCoreLabels(r.dk.Name, k8slabels.OtelCComponentLabel).BuildLabels()), + ) + + if err != nil { + return nil, err + } + + return configMap, nil +} + +func (r *Reconciler) removeOtlpApiEndpointConfigMap(ctx context.Context) error { + if meta.FindStatusCondition(*r.dk.Conditions(), configMapConditionType) == nil { + return nil // no condition == nothing is there to clean up + } + + query := k8sconfigmap.Query(r.client, r.apiReader, log) + err := query.Delete(ctx, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: consts.OtlpApiEndpointConfigMapName, Namespace: r.dk.Namespace}}) + + if err != nil { + log.Error(err, "could not delete apiEndpoint config map", "name", consts.OtlpApiEndpointConfigMapName) + } + + meta.RemoveStatusCondition(r.dk.Conditions(), configMapConditionType) + + return nil +} diff --git a/pkg/controllers/dynakube/otelc/endpoint/reconciler_test.go b/pkg/controllers/dynakube/otelc/endpoint/reconciler_test.go new file mode 100644 index 0000000000..913d047eb9 --- /dev/null +++ b/pkg/controllers/dynakube/otelc/endpoint/reconciler_test.go @@ -0,0 +1,168 @@ +package endpoint + +import ( + "context" + "fmt" + "testing" + + schemeFake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" + "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" + "github.com/Dynatrace/dynatrace-operator/pkg/api/status" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" + dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" + "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/configmap" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +const ( + testApiToken = "apiTokenValue" + testTenantUUID = "abc12345" + testKubeSystemUUID = "12345" +) + +func TestConfigMapCreation(t *testing.T) { + ctx := context.Background() + + t.Run("creates config map if it does not exist", func(t *testing.T) { + dk := createDynaKube(true) + + testConfigMap, err := configmap.Build(&dk, dk.Name, map[string]string{ + dtclient.ApiToken: testApiToken, + }) + require.NoError(t, err) + + clt := fake.NewFakeClient(testConfigMap) + + r := NewReconciler(clt, clt, &dk) + + err = r.ensureOtlpApiEndpointConfigMap(ctx) + require.NoError(t, err) + + var apiEndpointConfigMap corev1.ConfigMap + err = clt.Get(ctx, types.NamespacedName{Name: consts.OtlpApiEndpointConfigMapName, Namespace: dk.Namespace}, &apiEndpointConfigMap) + require.NoError(t, err) + assert.NotEmpty(t, apiEndpointConfigMap) + require.NotNil(t, meta.FindStatusCondition(*dk.Conditions(), configMapConditionType)) + assert.Equal(t, conditions.ConfigMapCreatedOrUpdatedReason, meta.FindStatusCondition(*dk.Conditions(), configMapConditionType).Reason) + }) + + t.Run("removes secret if exists but we don't need it", func(t *testing.T) { + dk := createDynaKube(false) + conditions.SetConfigMapCreatedOrUpdated(dk.Conditions(), configMapConditionType, consts.OtlpApiEndpointConfigMapName) + + objs := []client.Object{ + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: consts.OtlpApiEndpointConfigMapName, + Namespace: dk.Namespace, + }, + }, + } + + clt := schemeFake.NewClient(objs...) + r := NewReconciler(clt, clt, &dk) + + err := r.Reconcile(ctx) + require.NoError(t, err) + + var apiEndpointConfigmap corev1.ConfigMap + err = clt.Get(ctx, types.NamespacedName{Name: consts.OtlpApiEndpointConfigMapName, Namespace: dk.Namespace}, &apiEndpointConfigmap) + + require.Error(t, err) + assert.Empty(t, apiEndpointConfigmap) + }) +} + +func TestEndpoint(t *testing.T) { + tests := []struct { + name string + apiUrl string + expectedEndpoint string + inClusterAg bool + }{ + { + name: "in-cluster ActiveGate", + apiUrl: fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", testTenantUUID), + inClusterAg: true, + expectedEndpoint: fmt.Sprintf("https://test-dk-activegate.dynatrace.svc/e/%s/api/v2/otlp", testTenantUUID), + }, + { + name: "public ActiveGate", + apiUrl: fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", testTenantUUID), + inClusterAg: false, + expectedEndpoint: fmt.Sprintf("https://%s.dev.dynatracelabs.com/api/v2/otlp", testTenantUUID), + }, + { + name: "managed ActiveGate", + apiUrl: "https://dynatrace.foobar.com/e/abcdefgh-1234-5678-9abc-deadbeef/api", + inClusterAg: false, + expectedEndpoint: "https://dynatrace.foobar.com/e/abcdefgh-1234-5678-9abc-deadbeef/api/v2/otlp", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dk := createDynaKube(true) + dk.Spec.APIURL = tt.apiUrl + + if tt.inClusterAg { + dk.Spec.ActiveGate = activegate.Spec{ + Capabilities: []activegate.CapabilityDisplayName{"dynatrace-api"}, + } + } + + objs := []client.Object{ + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: consts.OtlpApiEndpointConfigMapName, + Namespace: dk.Namespace, + }, + }, + } + + clt := schemeFake.NewClient(objs...) + r := NewReconciler(clt, clt, &dk) + + endpoint, err := r.getDtEndpoint() + require.NoError(t, err) + assert.Equal(t, tt.expectedEndpoint, endpoint) + }) + } +} + +func createDynaKube(telemetryIngestEnabled bool) dynakube.DynaKube { + dk := dynakube.DynaKube{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-dk", + }, + Spec: dynakube.DynaKubeSpec{}, + Status: dynakube.DynaKubeStatus{ + ActiveGate: activegate.Status{ + ConnectionInfo: communication.ConnectionInfo{ + TenantUUID: testTenantUUID, + }, + VersionStatus: status.VersionStatus{}, + }, + KubeSystemUUID: testKubeSystemUUID, + }, + } + + if telemetryIngestEnabled { + dk.TelemetryIngest().Spec = &telemetryingest.Spec{} + } else { + dk.TelemetryIngest().Spec = nil + } + + return dk +} diff --git a/pkg/controllers/dynakube/otelc/reconciler.go b/pkg/controllers/dynakube/otelc/reconciler.go index e5849d41b0..15dd5ad277 100644 --- a/pkg/controllers/dynakube/otelc/reconciler.go +++ b/pkg/controllers/dynakube/otelc/reconciler.go @@ -6,7 +6,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/configuration" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/secret" + "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/endpoint" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/service" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/statefulset" "sigs.k8s.io/controller-runtime/pkg/client" @@ -18,7 +18,7 @@ type Reconciler struct { dk *dynakube.DynaKube statefulsetReconciler controllers.Reconciler serviceReconciler *service.Reconciler - secretReconciler *secret.Reconciler + endpointReconciler *endpoint.Reconciler configurationReconciler *configuration.Reconciler } @@ -31,7 +31,7 @@ func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.D dk: dk, statefulsetReconciler: statefulset.NewReconciler(client, apiReader, dk), serviceReconciler: service.NewReconciler(client, apiReader, dk), - secretReconciler: secret.NewReconciler(client, apiReader, dk), + endpointReconciler: endpoint.NewReconciler(client, apiReader, dk), configurationReconciler: configuration.NewReconciler(client, apiReader, dk), } } @@ -42,7 +42,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { return err } - err = r.secretReconciler.Reconcile(ctx) + err = r.endpointReconciler.Reconcile(ctx) if err != nil { return err } diff --git a/pkg/controllers/dynakube/otelc/secret/conditions.go b/pkg/controllers/dynakube/otelc/secret/conditions.go deleted file mode 100644 index ca554ad8a1..0000000000 --- a/pkg/controllers/dynakube/otelc/secret/conditions.go +++ /dev/null @@ -1,5 +0,0 @@ -package secret - -const ( - secretConditionType = "TelemetryIngestApiCredentialsSecret" -) diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler.go b/pkg/controllers/dynakube/otelc/secret/reconciler.go deleted file mode 100644 index 465c514ba2..0000000000 --- a/pkg/controllers/dynakube/otelc/secret/reconciler.go +++ /dev/null @@ -1,136 +0,0 @@ -package secret - -import ( - "context" - "fmt" - - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" - "github.com/Dynatrace/dynatrace-operator/pkg/util/hasher" - k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" - k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -type Reconciler struct { - client client.Client - apiReader client.Reader - dk *dynakube.DynaKube -} - -type ReconcilerBuilder func(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler - -func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.DynaKube) *Reconciler { - return &Reconciler{ - client: client, - dk: dk, - apiReader: apiReader, - } -} - -func (r *Reconciler) Reconcile(ctx context.Context) error { - if r.dk.TelemetryIngest().IsEnabled() { - return r.ensureTelemetryIngestApiCredentialsSecret(ctx) - } - - return r.removeTelemetryIngestApiCredentialsSecret(ctx) -} - -func (r *Reconciler) ensureTelemetryIngestApiCredentialsSecret(ctx context.Context) error { - query := k8ssecret.Query(r.client, r.apiReader, log) - _, err := query.Get(ctx, types.NamespacedName{Name: consts.TelemetryApiCredentialsSecretName, Namespace: r.dk.Namespace}) - - if err != nil && k8serrors.IsNotFound(err) { - log.Info("creating new secret for telemetry api credentials") - - secretConfig, err := r.generateTelemetryIngestApiCredentialsSecret(consts.TelemetryApiCredentialsSecretName) - - if err != nil { - conditions.SetSecretGenFailed(r.dk.Conditions(), secretConditionType, err) - - return err - } - - _, err = hasher.GenerateHash(secretConfig.Data) - if err != nil { - conditions.SetSecretGenFailed(r.dk.Conditions(), secretConditionType, err) - - return err - } - - err = query.Create(ctx, secretConfig) - if err != nil { - log.Info("could not create secret for telemetry api credentials", "name", secretConfig.Name) - conditions.SetKubeApiError(r.dk.Conditions(), secretConditionType, err) - - return err - } - - conditions.SetSecretCreated(r.dk.Conditions(), secretConditionType, consts.TelemetryApiCredentialsSecretName) - } else if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), secretConditionType, err) - - return err - } - - return nil -} - -func (r *Reconciler) getDtEndpoint() ([]byte, error) { - if r.dk.ActiveGate().IsEnabled() { - tenantUUID, err := r.dk.TenantUUID() - if err != nil { - return nil, err - } - - return []byte(fmt.Sprintf("https://%s-activegate.dynatrace.svc/e/%s/api/v2/otlp", r.dk.Name, tenantUUID)), nil - } - - return []byte(r.dk.ApiUrl() + "/v2/otlp"), nil -} - -func (r *Reconciler) generateTelemetryIngestApiCredentialsSecret(name string) (secret *corev1.Secret, err error) { - secretData := make(map[string][]byte) - - dtEndpoint, err := r.getDtEndpoint() - if err != nil { - return nil, err - } - - secretData["DT_ENDPOINT"] = dtEndpoint - - secretConfig, err := k8ssecret.Build(r.dk, - name, - secretData, - k8ssecret.SetLabels(k8slabels.NewCoreLabels(r.dk.Name, k8slabels.OtelCComponentLabel).BuildLabels()), - ) - - if err != nil { - return nil, err - } - - return secretConfig, nil -} - -func (r *Reconciler) removeTelemetryIngestApiCredentialsSecret(ctx context.Context) error { - if meta.FindStatusCondition(*r.dk.Conditions(), secretConditionType) == nil { - return nil // no condition == nothing is there to clean up - } - - query := k8ssecret.Query(r.client, r.apiReader, log) - err := query.Delete(ctx, &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: consts.TelemetryApiCredentialsSecretName, Namespace: r.dk.Namespace}}) - - if err != nil { - log.Error(err, "could not delete apiCredential secret", "name", consts.TelemetryApiCredentialsSecretName) - } - - meta.RemoveStatusCondition(r.dk.Conditions(), secretConditionType) - - return nil -} diff --git a/pkg/controllers/dynakube/otelc/secret/reconciler_test.go b/pkg/controllers/dynakube/otelc/secret/reconciler_test.go deleted file mode 100644 index bdc9c2915e..0000000000 --- a/pkg/controllers/dynakube/otelc/secret/reconciler_test.go +++ /dev/null @@ -1,184 +0,0 @@ -package secret - -import ( - "context" - "fmt" - "testing" - - schemeFake "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" - "github.com/Dynatrace/dynatrace-operator/pkg/api/shared/communication" - "github.com/Dynatrace/dynatrace-operator/pkg/api/status" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/activegate" - "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/telemetryingest" - dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/otelc/consts" - "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" - "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" -) - -const ( - testApiToken = "apiTokenValue" - testTenantUUID = "abc12345" - testKubeSystemUUID = "12345" -) - -func TestSecretCreation(t *testing.T) { - ctx := context.Background() - - t.Run("creates secret if it does not exist", func(t *testing.T) { - dk := createDynaKube(true) - - testSecret, err := secret.Build(&dk, dk.Name, map[string][]byte{ - dtclient.ApiToken: []byte(testApiToken), - }) - require.NoError(t, err) - - clt := fake.NewFakeClient(testSecret) - - r := NewReconciler(clt, clt, &dk) - - err = r.ensureTelemetryIngestApiCredentialsSecret(ctx) - require.NoError(t, err) - - var apiCredsSecret corev1.Secret - err = clt.Get(ctx, types.NamespacedName{Name: consts.TelemetryApiCredentialsSecretName, Namespace: dk.Namespace}, &apiCredsSecret) - require.NoError(t, err) - assert.NotEmpty(t, apiCredsSecret) - require.NotNil(t, meta.FindStatusCondition(*dk.Conditions(), secretConditionType)) - assert.Equal(t, conditions.SecretCreatedReason, meta.FindStatusCondition(*dk.Conditions(), secretConditionType).Reason) - }) - - t.Run("removes secret if exists but we don't need it", func(t *testing.T) { - dk := createDynaKube(false) - conditions.SetSecretCreated(dk.Conditions(), secretConditionType, consts.TelemetryApiCredentialsSecretName) - - objs := []client.Object{ - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: consts.TelemetryApiCredentialsSecretName, - Namespace: dk.Namespace, - }, - }, - } - - clt := schemeFake.NewClient(objs...) - r := NewReconciler(clt, clt, &dk) - - err := r.Reconcile(ctx) - require.NoError(t, err) - - var apiTokenSecret corev1.Secret - err = clt.Get(ctx, types.NamespacedName{Name: consts.TelemetryApiCredentialsSecretName, Namespace: dk.Namespace}, &apiTokenSecret) - - require.Error(t, err) - assert.Empty(t, apiTokenSecret) - }) -} - -func TestEndpoint(t *testing.T) { - t.Run("in-cluster ActiveGate", func(t *testing.T) { - dk := createDynaKube(true) - apiUrl := fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", testTenantUUID) - dk.Spec.APIURL = apiUrl - dk.Spec.ActiveGate = activegate.Spec{ - Capabilities: []activegate.CapabilityDisplayName{"dynatrace-api"}, - } - - objs := []client.Object{ - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: consts.TelemetryApiCredentialsSecretName, - Namespace: dk.Namespace, - }, - }, - } - - clt := schemeFake.NewClient(objs...) - r := NewReconciler(clt, clt, &dk) - - endpoint, err := r.getDtEndpoint() - require.NoError(t, err) - - expected := fmt.Sprintf("https://%s-activegate.dynatrace.svc/e/%s/api/v2/otlp", dk.Name, testTenantUUID) - assert.Equal(t, expected, string(endpoint)) - }) - - t.Run("public ActiveGate", func(t *testing.T) { - dk := createDynaKube(true) - apiUrl := fmt.Sprintf("https://%s.dev.dynatracelabs.com/api", testTenantUUID) - dk.Spec.APIURL = apiUrl - - objs := []client.Object{ - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: consts.TelemetryApiCredentialsSecretName, - Namespace: dk.Namespace, - }, - }, - } - - clt := schemeFake.NewClient(objs...) - r := NewReconciler(clt, clt, &dk) - - endpoint, err := r.getDtEndpoint() - require.NoError(t, err) - assert.Equal(t, apiUrl+"/v2/otlp", string(endpoint)) - }) - - t.Run("managed ActiveGate", func(t *testing.T) { - dk := createDynaKube(true) - apiUrl := "https://dynatrace.foobar.com/e/abcdefgh-1234-5678-9abc-deadbeef/api" - dk.Spec.APIURL = apiUrl - - objs := []client.Object{ - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: consts.TelemetryApiCredentialsSecretName, - Namespace: dk.Namespace, - }, - }, - } - - clt := schemeFake.NewClient(objs...) - r := NewReconciler(clt, clt, &dk) - - endpoint, err := r.getDtEndpoint() - require.NoError(t, err) - assert.Equal(t, apiUrl+"/v2/otlp", string(endpoint)) - }) -} - -func createDynaKube(telemetryIngestEnabled bool) dynakube.DynaKube { - dk := dynakube.DynaKube{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-dk", - }, - Spec: dynakube.DynaKubeSpec{}, - Status: dynakube.DynaKubeStatus{ - ActiveGate: activegate.Status{ - ConnectionInfo: communication.ConnectionInfo{ - TenantUUID: testTenantUUID, - }, - VersionStatus: status.VersionStatus{}, - }, - KubeSystemUUID: testKubeSystemUUID, - }, - } - - if telemetryIngestEnabled { - dk.TelemetryIngest().Spec = &telemetryingest.Spec{} - } else { - dk.TelemetryIngest().Spec = nil - } - - return dk -} diff --git a/pkg/controllers/dynakube/otelc/statefulset/env.go b/pkg/controllers/dynakube/otelc/statefulset/env.go index 727c2a225e..db99b55dbd 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env.go @@ -95,8 +95,8 @@ func getEnvs(dk *dynakube.DynaKube) []corev1.EnvVar { if dk.TelemetryIngest().IsEnabled() { envs = append(envs, corev1.EnvVar{Name: envDTendpoint, ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: otelcConsts.TelemetryApiCredentialsSecretName}, + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: otelcConsts.OtlpApiEndpointConfigMapName}, Key: envDTendpoint, }, }}, diff --git a/pkg/controllers/dynakube/otelc/statefulset/env_test.go b/pkg/controllers/dynakube/otelc/statefulset/env_test.go index b796b567b3..a90e6bc274 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/env_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/env_test.go @@ -90,8 +90,8 @@ func TestEnvironmentVariables(t *testing.T) { assert.Equal(t, corev1.EnvVar{Name: envDTentityK8sCluster, Value: dk.Status.KubernetesClusterMEID}, statefulSet.Spec.Template.Spec.Containers[0].Env[8]) assert.Equal(t, corev1.EnvVar{Name: envDTendpoint, ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: otelcConsts.TelemetryApiCredentialsSecretName}, + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: otelcConsts.OtlpApiEndpointConfigMapName}, Key: envDTendpoint, }, }}, statefulSet.Spec.Template.Spec.Containers[0].Env[9]) diff --git a/test/features/telemetryingest/telemetryingest.go b/test/features/telemetryingest/telemetryingest.go index 0ccaca747c..08a30b0104 100644 --- a/test/features/telemetryingest/telemetryingest.go +++ b/test/features/telemetryingest/telemetryingest.go @@ -93,6 +93,7 @@ func WithLocalActiveGateAndCleanup(t *testing.T) features.Feature { builder.Assess("otel collector started", statefulset.WaitFor(testDynakube.OtelCollectorStatefulsetName(), testDynakube.Namespace)) builder.Assess("otel collector config created", checkOtelCollectorConfig(&testDynakube)) builder.Assess("otel collector service created", checkOtelCollectorService(&testDynakube)) + builder.Assess("otel collector endpoint configmap created", checkOtelCollectorEndpointConfigMap(&testDynakube)) optionsTelemetryIngestDisabled := []componentDynakube.Option{ componentDynakube.WithApiUrl(secretConfig.ApiUrl), @@ -107,6 +108,7 @@ func WithLocalActiveGateAndCleanup(t *testing.T) features.Feature { builder.Assess("otel collector shutdown", waitForShutdown(testDynakubeNoTelemetryIngest.OtelCollectorStatefulsetName(), testDynakubeNoTelemetryIngest.Namespace)) builder.Assess("otel collector config removed", checkOtelCollectorConfigRemoved(&testDynakubeNoTelemetryIngest)) builder.Assess("otel collector service removed", checkOtelCollectorServiceRemoved(&testDynakubeNoTelemetryIngest)) + builder.Assess("otel collector endpoint configmap removed", checkOtelCollectorEndpointConfigMapRemoved(&testDynakubeNoTelemetryIngest)) componentDynakube.Delete(builder, helpers.LevelTeardown, testDynakubeNoTelemetryIngest) @@ -139,6 +141,7 @@ func WithTelemetryIngestEndpointTLS(t *testing.T) features.Feature { builder.Assess("otel collector started", statefulset.WaitFor(testDynakube.OtelCollectorStatefulsetName(), testDynakube.Namespace)) builder.Assess("otel collector config created", checkOtelCollectorConfig(&testDynakube)) builder.Assess("otel collector service created", checkOtelCollectorService(&testDynakube)) + builder.Assess("otel collector endpoint configmap created", checkOtelCollectorEndpointConfigMap(&testDynakube)) componentDynakube.Delete(builder, helpers.LevelTeardown, testDynakube) builder.WithTeardown("deleted tenant secret", tenant.DeleteTenantSecret(testDynakube.Name, testDynakube.Namespace)) @@ -165,6 +168,7 @@ func OtelCollectorConfigUpdate(t *testing.T) features.Feature { builder.Assess("otel collector started", statefulset.WaitFor(testDynakubeZipkin.OtelCollectorStatefulsetName(), testDynakubeZipkin.Namespace)) builder.Assess("otel collector config created", checkOtelCollectorConfig(&testDynakubeZipkin)) builder.Assess("otel collector service created", checkOtelCollectorService(&testDynakubeZipkin)) + builder.Assess("otel collector endpoint configmap created", checkOtelCollectorEndpointConfigMap(&testDynakubeZipkin)) var zipkinConfigResourceVersion string builder.Assess("otel collector configuration timestamp", getOtelCollectorConfigResourceVersion(&testDynakubeZipkin, &zipkinConfigResourceVersion)) @@ -298,6 +302,16 @@ func checkOtelCollectorService(dk *dynakube.DynaKube) features.Func { } } +func checkOtelCollectorEndpointConfigMap(dk *dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + cm, err := getOtelCollectorEndpointConfigMap(dk, ctx, envConfig) + require.NoError(t, err) + assert.NotNil(t, cm) + + return ctx + } +} + func checkOtelCollectorServiceRemoved(dk *dynakube.DynaKube) features.Func { return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { _, err := getOtelCollectorService(dk, ctx, envConfig) @@ -308,6 +322,16 @@ func checkOtelCollectorServiceRemoved(dk *dynakube.DynaKube) features.Func { } } +func checkOtelCollectorEndpointConfigMapRemoved(dk *dynakube.DynaKube) features.Func { + return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { + _, err := getOtelCollectorEndpointConfigMap(dk, ctx, envConfig) + require.Error(t, err) + assert.True(t, k8serrors.IsNotFound(err), "Service still exists") + + return ctx + } +} + func getOtelCollectorPodTimestamp(dk *dynakube.DynaKube, startTimestamp *time.Time) features.Func { return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { resources := envConfig.Client().Resources() @@ -353,6 +377,19 @@ func getOtelCollectorService(dk *dynakube.DynaKube, ctx context.Context, envConf return &otelCollectorService, nil } +func getOtelCollectorEndpointConfigMap(dk *dynakube.DynaKube, ctx context.Context, envConfig *envconf.Config) (*corev1.ConfigMap, error) { + resources := envConfig.Client().Resources() + + var otelCollectorEndpointConfigMap corev1.ConfigMap + err := resources.WithNamespace(dk.Namespace).Get(ctx, otelcconsts.OtlpApiEndpointConfigMapName, dk.Namespace, &otelCollectorEndpointConfigMap) + + if err != nil { + return nil, err + } + + return &otelCollectorEndpointConfigMap, nil +} + func waitForShutdown(name string, namespace string) features.Func { return func(ctx context.Context, t *testing.T, envConfig *envconf.Config) context.Context { resources := envConfig.Client().Resources() From b8a5a7bd2df9d06d56d451cf14ceef3abe9db5b7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Apr 2025 01:40:34 +0000 Subject: [PATCH 380/426] fix(deps): update module go.opentelemetry.io/collector/confmap to v1.29.0 (main) (#4678) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 99bb0e5188..ce0df15026 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v1.28.1 - go.opentelemetry.io/collector/confmap v1.28.1 + go.opentelemetry.io/collector/confmap v1.29.0 go.opentelemetry.io/collector/pipeline v0.122.1 go.opentelemetry.io/collector/service v0.122.1 go.uber.org/zap v1.27.0 @@ -114,7 +114,7 @@ require ( go.opentelemetry.io/collector/extension v1.28.1 // indirect go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.1 // indirect go.opentelemetry.io/collector/extension/extensiontest v0.122.1 // indirect - go.opentelemetry.io/collector/featuregate v1.28.1 // indirect + go.opentelemetry.io/collector/featuregate v1.29.0 // indirect go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.1 // indirect go.opentelemetry.io/collector/internal/telemetry v0.122.1 // indirect go.opentelemetry.io/collector/pdata v1.28.1 // indirect diff --git a/go.sum b/go.sum index d676069834..2d123579cc 100644 --- a/go.sum +++ b/go.sum @@ -195,8 +195,8 @@ go.opentelemetry.io/collector/config/configretry v1.28.1 h1:WVRw9neCAsWilZU9C4Zz go.opentelemetry.io/collector/config/configretry v1.28.1/go.mod h1:QNnb+MCk7aS1k2EuGJMtlNCltzD7b8uC7Xel0Dxm1wQ= go.opentelemetry.io/collector/config/configtelemetry v0.122.1 h1:WABfddVAhIn5ZrTdisn6fOBufyYT/xYhKg6U0yYWQLA= go.opentelemetry.io/collector/config/configtelemetry v0.122.1/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= -go.opentelemetry.io/collector/confmap v1.28.1 h1:/zUmvpnERhFXrxVCVgubjJRgeOwdPbhTfUILZPUBfyw= -go.opentelemetry.io/collector/confmap v1.28.1/go.mod h1:2aJggo/KQl7uynFyMNNMbl7jvKkSD7CniOVEpCbjRng= +go.opentelemetry.io/collector/confmap v1.29.0 h1:1d43r3gQApgRxjyiQ86/qQd7OHW/BEbM6m/L36O5gKU= +go.opentelemetry.io/collector/confmap v1.29.0/go.mod h1:g8DLibnb2MEUWMMlyxHl1VviwFKUdwyBE5M1bxY1Pwg= go.opentelemetry.io/collector/confmap/xconfmap v0.122.1 h1:E8sdJens/sq+evv/VHzbDP3B28uZIAPkKjtB4mVVTso= go.opentelemetry.io/collector/confmap/xconfmap v0.122.1/go.mod h1:33HDN5uVKRihgLiShZZDzxN0qiTA1+t8hK41rrf1jls= go.opentelemetry.io/collector/connector v0.122.1 h1:E0qzq1YyT4gfUr961bPGZhYObvBTsWlgqY37XzDPRJo= @@ -227,8 +227,8 @@ go.opentelemetry.io/collector/extension/extensiontest v0.122.1 h1:Rc5XZSY8HEb0x3 go.opentelemetry.io/collector/extension/extensiontest v0.122.1/go.mod h1:fdsJ3X45rU5CeCWk8hscVrbr7u5MdO3DnnKCVWTMDEc= go.opentelemetry.io/collector/extension/xextension v0.122.1 h1:U7Ryv25DC+wzJq6xcveZFmWEnOwwFSJAcH2nr2tw3vI= go.opentelemetry.io/collector/extension/xextension v0.122.1/go.mod h1:gXcwe6qono7zK4/RyKn0j47qWz204IcRyMqa47GO360= -go.opentelemetry.io/collector/featuregate v1.28.1 h1:ZpvRAAFxxi4RLr1G0Fju28wA7NhTA20MNT60Ftv+ToY= -go.opentelemetry.io/collector/featuregate v1.28.1/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= +go.opentelemetry.io/collector/featuregate v1.29.0 h1:DTDeaokT53AA+SiYBH8GC893cmppThU65b3XyFfLPWw= +go.opentelemetry.io/collector/featuregate v1.29.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.1 h1:AphjgdUrg/SNIXAHJASVWFWQDYszn3zS9+P1tJHSdAU= go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.1/go.mod h1:jfe5dOMrkoWOJK6D9yTQjDEaOhBOkjcy3sKX6KBBT9c= go.opentelemetry.io/collector/internal/telemetry v0.122.1 h1:bB5yb/JECih7Nqrfu9+AtBasGioyiy3rBrAMLbcyaXQ= From eeca1875101a41268f462c4b97600d1104b14176 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Apr 2025 06:06:00 +0000 Subject: [PATCH 381/426] fix(deps): update module go.opentelemetry.io/collector/pipeline to v0.123.0 (main) (#4679) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ce0df15026..4a403e37fa 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/component v1.28.1 go.opentelemetry.io/collector/confmap v1.29.0 - go.opentelemetry.io/collector/pipeline v0.122.1 + go.opentelemetry.io/collector/pipeline v0.123.0 go.opentelemetry.io/collector/service v0.122.1 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 diff --git a/go.sum b/go.sum index 2d123579cc..c5c923ec08 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,8 @@ go.opentelemetry.io/collector/pdata/pprofile v0.122.1 h1:25Fs0eL/J/M2ZEaVplesbI1 go.opentelemetry.io/collector/pdata/pprofile v0.122.1/go.mod h1:+jSjgb4zRnNmr1R/zgVLVyTVSm9irfGrvGTrk3lDxSE= go.opentelemetry.io/collector/pdata/testdata v0.122.1 h1:9DO8nUUnPAGYMKmrep6wLAfOHprvKY4w/7LpE4jldPQ= go.opentelemetry.io/collector/pdata/testdata v0.122.1/go.mod h1:hYdNrn8KxFwq1nf44YYRgNhDjJTBzoyEr/Qa26pN0t4= -go.opentelemetry.io/collector/pipeline v0.122.1 h1:f0uuiDmanVyKwfYo6cWveJsGbLXidV7i+Z7u8QJwWxI= -go.opentelemetry.io/collector/pipeline v0.122.1/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= +go.opentelemetry.io/collector/pipeline v0.123.0 h1:LDcuCrwhCTx2yROJZqhNmq2v0CFkCkUEvxvvcRW0+2c= +go.opentelemetry.io/collector/pipeline v0.123.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= go.opentelemetry.io/collector/pipeline/xpipeline v0.122.1 h1:WhMVlMRjQoiu2k9/Haudy7VoDT4gismQzl1ZDxwvHQY= go.opentelemetry.io/collector/pipeline/xpipeline v0.122.1/go.mod h1:arZHihE9qPJ4WVWPUsSqUovhQdWZtOGLg2E/QKxbz7M= go.opentelemetry.io/collector/processor v0.122.1 h1:AvZvEujq8+FYdJsm9lmAMwuuae5Y2/vKIkOJwsoxsxQ= From 91c04953cdda6343591373b75ce71e01f0eb67a4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Apr 2025 06:59:29 +0000 Subject: [PATCH 382/426] fix(deps): update module go.opentelemetry.io/collector/service to v0.123.0 (main) (#4680) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 64 ++++++++++++------------- go.sum | 148 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 106 insertions(+), 106 deletions(-) diff --git a/go.mod b/go.mod index 4a403e37fa..b22ee53fbe 100644 --- a/go.mod +++ b/go.mod @@ -17,10 +17,10 @@ require ( github.com/spf13/afero v1.14.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 - go.opentelemetry.io/collector/component v1.28.1 + go.opentelemetry.io/collector/component v1.29.0 go.opentelemetry.io/collector/confmap v1.29.0 go.opentelemetry.io/collector/pipeline v0.123.0 - go.opentelemetry.io/collector/service v0.122.1 + go.opentelemetry.io/collector/service v0.123.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.24.0 @@ -98,35 +98,35 @@ require ( github.com/vladimirvivien/gexe v0.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/collector/component/componentstatus v0.122.1 // indirect - go.opentelemetry.io/collector/component/componenttest v0.122.1 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.122.1 // indirect - go.opentelemetry.io/collector/connector v0.122.1 // indirect - go.opentelemetry.io/collector/connector/connectortest v0.122.1 // indirect - go.opentelemetry.io/collector/connector/xconnector v0.122.1 // indirect - go.opentelemetry.io/collector/consumer v1.28.1 // indirect - go.opentelemetry.io/collector/consumer/consumererror v0.122.1 // indirect - go.opentelemetry.io/collector/consumer/consumertest v0.122.1 // indirect - go.opentelemetry.io/collector/consumer/xconsumer v0.122.1 // indirect - go.opentelemetry.io/collector/exporter v0.122.1 // indirect - go.opentelemetry.io/collector/exporter/exportertest v0.122.1 // indirect - go.opentelemetry.io/collector/exporter/xexporter v0.122.1 // indirect - go.opentelemetry.io/collector/extension v1.28.1 // indirect - go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.1 // indirect - go.opentelemetry.io/collector/extension/extensiontest v0.122.1 // indirect + go.opentelemetry.io/collector/component/componentstatus v0.123.0 // indirect + go.opentelemetry.io/collector/component/componenttest v0.123.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.123.0 // indirect + go.opentelemetry.io/collector/connector v0.123.0 // indirect + go.opentelemetry.io/collector/connector/connectortest v0.123.0 // indirect + go.opentelemetry.io/collector/connector/xconnector v0.123.0 // indirect + go.opentelemetry.io/collector/consumer v1.29.0 // indirect + go.opentelemetry.io/collector/consumer/consumererror v0.123.0 // indirect + go.opentelemetry.io/collector/consumer/consumertest v0.123.0 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.123.0 // indirect + go.opentelemetry.io/collector/exporter v0.123.0 // indirect + go.opentelemetry.io/collector/exporter/exportertest v0.123.0 // indirect + go.opentelemetry.io/collector/exporter/xexporter v0.123.0 // indirect + go.opentelemetry.io/collector/extension v1.29.0 // indirect + go.opentelemetry.io/collector/extension/extensioncapabilities v0.123.0 // indirect + go.opentelemetry.io/collector/extension/extensiontest v0.123.0 // indirect go.opentelemetry.io/collector/featuregate v1.29.0 // indirect - go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.1 // indirect - go.opentelemetry.io/collector/internal/telemetry v0.122.1 // indirect - go.opentelemetry.io/collector/pdata v1.28.1 // indirect - go.opentelemetry.io/collector/pdata/pprofile v0.122.1 // indirect - go.opentelemetry.io/collector/pdata/testdata v0.122.1 // indirect - go.opentelemetry.io/collector/pipeline/xpipeline v0.122.1 // indirect - go.opentelemetry.io/collector/processor v0.122.1 // indirect - go.opentelemetry.io/collector/processor/processortest v0.122.1 // indirect - go.opentelemetry.io/collector/processor/xprocessor v0.122.1 // indirect - go.opentelemetry.io/collector/receiver v1.28.1 // indirect - go.opentelemetry.io/collector/receiver/receivertest v0.122.1 // indirect - go.opentelemetry.io/collector/receiver/xreceiver v0.122.1 // indirect + go.opentelemetry.io/collector/internal/fanoutconsumer v0.123.0 // indirect + go.opentelemetry.io/collector/internal/telemetry v0.123.0 // indirect + go.opentelemetry.io/collector/pdata v1.29.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.123.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.123.0 // indirect + go.opentelemetry.io/collector/pipeline/xpipeline v0.123.0 // indirect + go.opentelemetry.io/collector/processor v1.29.0 // indirect + go.opentelemetry.io/collector/processor/processortest v0.123.0 // indirect + go.opentelemetry.io/collector/processor/xprocessor v0.123.0 // indirect + go.opentelemetry.io/collector/receiver v1.29.0 // indirect + go.opentelemetry.io/collector/receiver/receivertest v0.123.0 // indirect + go.opentelemetry.io/collector/receiver/xreceiver v0.123.0 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.10.0 // indirect go.opentelemetry.io/contrib/otelconf v0.15.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.35.0 // indirect @@ -155,10 +155,10 @@ require ( golang.org/x/text v0.23.0 // indirect golang.org/x/time v0.11.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - gonum.org/v1/gonum v0.15.1 // indirect + gonum.org/v1/gonum v0.16.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect - google.golang.org/protobuf v1.36.5 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index c5c923ec08..55aa833e4a 100644 --- a/go.sum +++ b/go.sum @@ -183,82 +183,82 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/collector v0.122.1 h1:CfjBnpaaE261Y1IeE+71VuGKC/AGGRz2R9kum9DpY1I= -go.opentelemetry.io/collector v0.122.1/go.mod h1:8t7TFg4nQHskvaOZrbfqAprB3r6+SZ2GQ2NYua0HEtg= -go.opentelemetry.io/collector/component v1.28.1 h1:JjwfvLR0UdadRDAANAdM4mOSwGmfGO3va2X+fdk4YdA= -go.opentelemetry.io/collector/component v1.28.1/go.mod h1:jwZRDML3tXo1whueZdRf+y6z3DeEYTLPBmb/O1ujB40= -go.opentelemetry.io/collector/component/componentstatus v0.122.1 h1:zMQC0y8ZBITa87GOwEANdOoAox5I4UgaIHxY79nwCbk= -go.opentelemetry.io/collector/component/componentstatus v0.122.1/go.mod h1:ZYwOgoXyPu4gGqfQ5DeaEpStpUCD/Clctz4rMd9qQYw= -go.opentelemetry.io/collector/component/componenttest v0.122.1 h1:HE4oeLub2FWVTUzCQG6SWwfnJfcK1FMknXhGQ2gOxnY= -go.opentelemetry.io/collector/component/componenttest v0.122.1/go.mod h1:o3Xq6z3C0aVhrd/fD56aKxShrILVnHnbgQVP5NoFuic= -go.opentelemetry.io/collector/config/configretry v1.28.1 h1:WVRw9neCAsWilZU9C4ZzXeQLw1L3dIRlCIqReqhzi70= -go.opentelemetry.io/collector/config/configretry v1.28.1/go.mod h1:QNnb+MCk7aS1k2EuGJMtlNCltzD7b8uC7Xel0Dxm1wQ= -go.opentelemetry.io/collector/config/configtelemetry v0.122.1 h1:WABfddVAhIn5ZrTdisn6fOBufyYT/xYhKg6U0yYWQLA= -go.opentelemetry.io/collector/config/configtelemetry v0.122.1/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= +go.opentelemetry.io/collector v0.123.0 h1:2aijJMaWk1Qn0ZLcJwEEfRWrQpvhxFFNIKZGUDw3QR0= +go.opentelemetry.io/collector v0.123.0/go.mod h1:HlBLICu+ZbxI9whVakFLg+h1yrco/n2M+aOIBhlq9Sk= +go.opentelemetry.io/collector/component v1.29.0 h1:SQDKqMb3EUNPyxZDrImkqgi8p682Hm986CMXBiiTkz0= +go.opentelemetry.io/collector/component v1.29.0/go.mod h1:qHoiz0iyBgyAYsT0F8FgtcJv8pTEQDvo1Ox3eO3qVlY= +go.opentelemetry.io/collector/component/componentstatus v0.123.0 h1:KL7nNmRoCLt8dVOr5kuvWDly2W5fLE5J6qZ8OdhEzw0= +go.opentelemetry.io/collector/component/componentstatus v0.123.0/go.mod h1:xZxBHdoU8bunn8NpcpRF9eEL1HhYFKXUFTqdMZRTqVk= +go.opentelemetry.io/collector/component/componenttest v0.123.0 h1:h0B/kBj0URKq+i9iMbMuLhc6/dZ2GWL0y9L6tqHRNuA= +go.opentelemetry.io/collector/component/componenttest v0.123.0/go.mod h1:4Y6EMvsgE9fUNM98G0eW5+LFXfcxdhTHQDhaOxJrgN8= +go.opentelemetry.io/collector/config/configretry v1.29.0 h1:Gm140dYwQk9TRQBQHF4hYybdvE2KvUhCLndPvZupTxM= +go.opentelemetry.io/collector/config/configretry v1.29.0/go.mod h1:QNnb+MCk7aS1k2EuGJMtlNCltzD7b8uC7Xel0Dxm1wQ= +go.opentelemetry.io/collector/config/configtelemetry v0.123.0 h1:Sml/reJ8At27NU5dgUmR/PBujSLr5Oa8aDrQ8IyoFWQ= +go.opentelemetry.io/collector/config/configtelemetry v0.123.0/go.mod h1:WXmlNatI0vwjv7whh/qF1Xy+UufCZDk7VLtYqML7QmA= go.opentelemetry.io/collector/confmap v1.29.0 h1:1d43r3gQApgRxjyiQ86/qQd7OHW/BEbM6m/L36O5gKU= go.opentelemetry.io/collector/confmap v1.29.0/go.mod h1:g8DLibnb2MEUWMMlyxHl1VviwFKUdwyBE5M1bxY1Pwg= -go.opentelemetry.io/collector/confmap/xconfmap v0.122.1 h1:E8sdJens/sq+evv/VHzbDP3B28uZIAPkKjtB4mVVTso= -go.opentelemetry.io/collector/confmap/xconfmap v0.122.1/go.mod h1:33HDN5uVKRihgLiShZZDzxN0qiTA1+t8hK41rrf1jls= -go.opentelemetry.io/collector/connector v0.122.1 h1:E0qzq1YyT4gfUr961bPGZhYObvBTsWlgqY37XzDPRJo= -go.opentelemetry.io/collector/connector v0.122.1/go.mod h1:ia6ams3PZGjAMXSXT0hm3cQb8MZ3x58zIR3+5eQhzs0= -go.opentelemetry.io/collector/connector/connectortest v0.122.1 h1:RgSAFzR/Wh/QF8DG1r/9/N7g7OJlu8nba4DBRvvTr00= -go.opentelemetry.io/collector/connector/connectortest v0.122.1/go.mod h1:IzWDkmJvf2HN3dmOR/g0xY5T8cmjB6KPLBCHx9sfVnw= -go.opentelemetry.io/collector/connector/xconnector v0.122.1 h1:yhMXzvi0gd/kbq4gaG+0ozeRfIJCHVunKS/JW2a8j5c= -go.opentelemetry.io/collector/connector/xconnector v0.122.1/go.mod h1:25VAcwl0MAAsKDcN3Xi7ZbLn9AVmX/zuWOSsxoqz1C0= -go.opentelemetry.io/collector/consumer v1.28.1 h1:3lHW2e0i7kEkbDqK1vErA8illqPpwDxMzgc5OUDsJ0Y= -go.opentelemetry.io/collector/consumer v1.28.1/go.mod h1:g0T16JPMYFN6T2noh+1YBxJSt5i5Zp+Y0Y6pvkMqsDQ= -go.opentelemetry.io/collector/consumer/consumererror v0.122.1 h1:/eL7rtfnKUMgjtiD+NXm6hd3QQ+tjD1oGc+ImPxFdIg= -go.opentelemetry.io/collector/consumer/consumererror v0.122.1/go.mod h1:sQ4liQ7KVpZAz0KXm7q1cCoeL6YY6C9Nxmut7Js42dY= -go.opentelemetry.io/collector/consumer/consumertest v0.122.1 h1:LKkLMdWwJCuOYyCMVzwc0OG9vncIqpl8Tp9+H8RikNg= -go.opentelemetry.io/collector/consumer/consumertest v0.122.1/go.mod h1:pYqWgx62ou3uUn8nlt2ohRyKod+7xLTf/uA3YfRwVkA= -go.opentelemetry.io/collector/consumer/xconsumer v0.122.1 h1:iK1hGbho/XICdBfGb4MnKwF9lnhLmv09yQ4YlVm+LGo= -go.opentelemetry.io/collector/consumer/xconsumer v0.122.1/go.mod h1:xYbRPP1oWcYUUDQJTlv78M/rlYb+qE4weiv++ObZRSU= -go.opentelemetry.io/collector/exporter v0.122.1 h1:Yr8gmIQWb9Zylr2Al69k0BhCNlWIae1xPZz01zDyAZM= -go.opentelemetry.io/collector/exporter v0.122.1/go.mod h1:CiIgKR/LG7oq+bogywL2zKkGtikiGyo3zTQaMGZNqDI= -go.opentelemetry.io/collector/exporter/exportertest v0.122.1 h1:izA26/JnJ819BOws089MJjo7oQB+uuM07Htfo8uE+Q4= -go.opentelemetry.io/collector/exporter/exportertest v0.122.1/go.mod h1:/usnN6Vl3jJL6Vo9U9x/FKmAv1l0DofnKIYAOzJmrVU= -go.opentelemetry.io/collector/exporter/xexporter v0.122.1 h1:SJt9kiCEyXAxyGWA4tBt1hqydmqVco9KDg9SkH4p7/o= -go.opentelemetry.io/collector/exporter/xexporter v0.122.1/go.mod h1:5cgaRnGaWp0VtPbrTIIU717Eu4rW7kj1L8KluFlPPp0= -go.opentelemetry.io/collector/extension v1.28.1 h1:2qiX/nuihDzHMmOxrVKZ5SURFL/oJBMlL6+kPDvb0+I= -go.opentelemetry.io/collector/extension v1.28.1/go.mod h1:IaovGuJib5XGgLejcBmpgwFS5/mCV4xnW/J2Towy5lM= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.1 h1:dl6IdeQ7kOCESkcidXL6mbsUm1JcHC+JepqdNoiWlDc= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.122.1/go.mod h1:BGX52Iu/y9Sunfm/7BTwPcgZiSO3N+4qRDKkFlcZXsw= -go.opentelemetry.io/collector/extension/extensiontest v0.122.1 h1:Rc5XZSY8HEb0x3RDnnNKk2VuvYkmx209dahs0JGFMJY= -go.opentelemetry.io/collector/extension/extensiontest v0.122.1/go.mod h1:fdsJ3X45rU5CeCWk8hscVrbr7u5MdO3DnnKCVWTMDEc= -go.opentelemetry.io/collector/extension/xextension v0.122.1 h1:U7Ryv25DC+wzJq6xcveZFmWEnOwwFSJAcH2nr2tw3vI= -go.opentelemetry.io/collector/extension/xextension v0.122.1/go.mod h1:gXcwe6qono7zK4/RyKn0j47qWz204IcRyMqa47GO360= +go.opentelemetry.io/collector/confmap/xconfmap v0.123.0 h1:7c5kmfweyEZG2AP/kxVXtmQQTmuMU5S4C7NKrWDHOuc= +go.opentelemetry.io/collector/confmap/xconfmap v0.123.0/go.mod h1:pNLcOJ/65QE12P8iwmn5RnkvzdplHF6AvebXeRClT3w= +go.opentelemetry.io/collector/connector v0.123.0 h1:B5vjKx/LGUnIkIvhF+65XkRXdndn/6b/mmqhLkjGiCA= +go.opentelemetry.io/collector/connector v0.123.0/go.mod h1:wVYmWz2ETJXP5i/IB5IUWQWEZi+PE4pQFTr4dzNLvcc= +go.opentelemetry.io/collector/connector/connectortest v0.123.0 h1:wytLYrZqzKhL+tts6VrQBf6rMBwlNZUj5SbjB15mcUA= +go.opentelemetry.io/collector/connector/connectortest v0.123.0/go.mod h1:pzIR5vPUVcccddMcvch/1D70IxoAIyEUDCOLFLUBu28= +go.opentelemetry.io/collector/connector/xconnector v0.123.0 h1:VHS7KLIGLMNyAhifa3LKIrbTYF8N8rgnym1ybrzaQqA= +go.opentelemetry.io/collector/connector/xconnector v0.123.0/go.mod h1:zMsvWvuZVt2vh1S3BcF1OjmiDswdrfFqaE+WiPQuR4Q= +go.opentelemetry.io/collector/consumer v1.29.0 h1:WOtwc7bY0/L47mZPE6fu/txD6Fg2dPI3c/Cq+H1RRNY= +go.opentelemetry.io/collector/consumer v1.29.0/go.mod h1:SRcOjDfuvTEk6pchJ0HuOBLsmbRG26+mZLrwXb9T3TQ= +go.opentelemetry.io/collector/consumer/consumererror v0.123.0 h1:/X32KeSGTLX+/YRlR1Wx6/GQkL2m1A6l3B0BYErnxC0= +go.opentelemetry.io/collector/consumer/consumererror v0.123.0/go.mod h1:A9oAkn1emXnenyXiBb5iJNteWCidrM5remnzRqXHOKc= +go.opentelemetry.io/collector/consumer/consumertest v0.123.0 h1:IGBan9tb/QJOzGO8AaQai/jv2DQ7V1DbsFhrTHhDSe8= +go.opentelemetry.io/collector/consumer/consumertest v0.123.0/go.mod h1:MN6OZWsjF1JpvxEzGy7xFu0+PGtbzOASQnN6GgX7olA= +go.opentelemetry.io/collector/consumer/xconsumer v0.123.0 h1:UJhwYgtAe3O/8ilQj+AiyLBz+PXnw/hrpPk3wkB7u9g= +go.opentelemetry.io/collector/consumer/xconsumer v0.123.0/go.mod h1:+LAk3gs6kQ3O0+jLZhZAfgPEWUinxKkFqb3nZkYbC6w= +go.opentelemetry.io/collector/exporter v0.123.0 h1:Dda4AJl6GB+3s6syq45EGpP/kq3xnjcYBBd9SL5A0iA= +go.opentelemetry.io/collector/exporter v0.123.0/go.mod h1:ZeRhRP7AfWmkWkQIBn6A9sIzPkhpjFSjC6Cr78kugr0= +go.opentelemetry.io/collector/exporter/exportertest v0.123.0 h1:TR8pmnyUvy6BnF/suwplZ8l/s7ozetlE1sRYeNfvpoc= +go.opentelemetry.io/collector/exporter/exportertest v0.123.0/go.mod h1:GHt8/K/1evqJ84IUT1QjYrpmBS5dtQOjc7moxik7rA0= +go.opentelemetry.io/collector/exporter/xexporter v0.123.0 h1:7uAARN1ktH8OnhansCiJkhqYcfjp4UtdjUimeORJCYc= +go.opentelemetry.io/collector/exporter/xexporter v0.123.0/go.mod h1:k8TLjOKKm7RxoXIk/aA7CF7CdsoCFYx+4Sfnjd2rR5U= +go.opentelemetry.io/collector/extension v1.29.0 h1:xydxgo+UwDSZtcYGjEbj2UJtfevBSqRhPYyDuOC2VSI= +go.opentelemetry.io/collector/extension v1.29.0/go.mod h1:s/8CiRG1UdAEmovkO7zGACoxBqhqo0UaHciK4Ud+5P4= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.123.0 h1:0VCC+lxhrO+ugsW+m3yNm0Wj6nAzKmR0YOHIJyAbmio= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.123.0/go.mod h1:aoh1Br9rFL+FHUr+pMPgXfM2Tk1u78q2X056P3NFgks= +go.opentelemetry.io/collector/extension/extensiontest v0.123.0 h1:QankUyQPcmx0UIBGWJX8ObpdESHULhCo0JDhXtagb0s= +go.opentelemetry.io/collector/extension/extensiontest v0.123.0/go.mod h1:JSnbeMyH55jFQqT77wZh04Xx8EnwcIY39A+MqnwDawk= +go.opentelemetry.io/collector/extension/xextension v0.123.0 h1:GA0Hp9+3aY+bCXlPTsSSkQKgRpK3TMJ7lke19DGyqXA= +go.opentelemetry.io/collector/extension/xextension v0.123.0/go.mod h1:qMBSQaxnFDL74poKWeVifhhuF5UCZ73GGD0mgyTI6SE= go.opentelemetry.io/collector/featuregate v1.29.0 h1:DTDeaokT53AA+SiYBH8GC893cmppThU65b3XyFfLPWw= go.opentelemetry.io/collector/featuregate v1.29.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.1 h1:AphjgdUrg/SNIXAHJASVWFWQDYszn3zS9+P1tJHSdAU= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.122.1/go.mod h1:jfe5dOMrkoWOJK6D9yTQjDEaOhBOkjcy3sKX6KBBT9c= -go.opentelemetry.io/collector/internal/telemetry v0.122.1 h1:bB5yb/JECih7Nqrfu9+AtBasGioyiy3rBrAMLbcyaXQ= -go.opentelemetry.io/collector/internal/telemetry v0.122.1/go.mod h1:Qor+QXnQN+UYUdD2qtglBdH3y0xoXlcONnx2FnvjAL0= -go.opentelemetry.io/collector/pdata v1.28.1 h1:ORl5WLpQJvjzBVpHu12lqKMdcf/qDBwRXMcUubhybiQ= -go.opentelemetry.io/collector/pdata v1.28.1/go.mod h1:asKE8MD/4SOKz1mCrGdAz4VO2U2HUNg8A6094uK7pq0= -go.opentelemetry.io/collector/pdata/pprofile v0.122.1 h1:25Fs0eL/J/M2ZEaVplesbI1H7pYx462zUUVxVOszpOg= -go.opentelemetry.io/collector/pdata/pprofile v0.122.1/go.mod h1:+jSjgb4zRnNmr1R/zgVLVyTVSm9irfGrvGTrk3lDxSE= -go.opentelemetry.io/collector/pdata/testdata v0.122.1 h1:9DO8nUUnPAGYMKmrep6wLAfOHprvKY4w/7LpE4jldPQ= -go.opentelemetry.io/collector/pdata/testdata v0.122.1/go.mod h1:hYdNrn8KxFwq1nf44YYRgNhDjJTBzoyEr/Qa26pN0t4= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.123.0 h1:1wM3XB46Lp0svAPJmL74ST3CMVJZpHIDxxqSBPFSBy8= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.123.0/go.mod h1:gTENSpqzDirGKm/9NM8WiHYVYpu9fFCdPiJqTJhZ4Kg= +go.opentelemetry.io/collector/internal/telemetry v0.123.0 h1:K6UMv22ulxcv/G8BkwywMN4LprpwuLl1rhTMWpnujqE= +go.opentelemetry.io/collector/internal/telemetry v0.123.0/go.mod h1:Qwh5XcqAlAT9NorjaaSaNcilDgaecs8S+OKljJ9hFno= +go.opentelemetry.io/collector/pdata v1.29.0 h1:ZXSZ2fROdAEbv4JKKiCspBpjIjYZ5XaNt71LNH4RpQw= +go.opentelemetry.io/collector/pdata v1.29.0/go.mod h1:9kb3zMtLFXBPA6WGWkBHbkFwlwwYL/OHk1m0ASWZpeY= +go.opentelemetry.io/collector/pdata/pprofile v0.123.0 h1:NjwE1btsQbzOWsIFYt7vfgrqDNCROO3hWiZwT1/KaZU= +go.opentelemetry.io/collector/pdata/pprofile v0.123.0/go.mod h1:af2WDdbCc+JA+FokOnsW3l+agsnW5ed8LkLn6CfneII= +go.opentelemetry.io/collector/pdata/testdata v0.123.0 h1:daMcuywv7L/O0pJMCKzlgsm/En8o7SeMSPWUZsPt+JM= +go.opentelemetry.io/collector/pdata/testdata v0.123.0/go.mod h1:lyARYT+2evYj7EdB0LLuo81lb48P7/yKKT86lRCEsmA= go.opentelemetry.io/collector/pipeline v0.123.0 h1:LDcuCrwhCTx2yROJZqhNmq2v0CFkCkUEvxvvcRW0+2c= go.opentelemetry.io/collector/pipeline v0.123.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= -go.opentelemetry.io/collector/pipeline/xpipeline v0.122.1 h1:WhMVlMRjQoiu2k9/Haudy7VoDT4gismQzl1ZDxwvHQY= -go.opentelemetry.io/collector/pipeline/xpipeline v0.122.1/go.mod h1:arZHihE9qPJ4WVWPUsSqUovhQdWZtOGLg2E/QKxbz7M= -go.opentelemetry.io/collector/processor v0.122.1 h1:AvZvEujq8+FYdJsm9lmAMwuuae5Y2/vKIkOJwsoxsxQ= -go.opentelemetry.io/collector/processor v0.122.1/go.mod h1:nYKctftba7SbdLml6LxgIrnYRXCShDe2bnNWjTIpF7g= -go.opentelemetry.io/collector/processor/processortest v0.122.1 h1:n4UOx1mq+kLaRiHGsu7vBLq+EGXfzWhSxyFweMjMl54= -go.opentelemetry.io/collector/processor/processortest v0.122.1/go.mod h1:8/NRWx18tNJMBwCQ8/YPWr4qsFUrwk27qE7/dXoJb1M= -go.opentelemetry.io/collector/processor/xprocessor v0.122.1 h1:Wfv4/7n4YK1HunAVTMS6yf0xmDjCkftJ6EECNcSwzfs= -go.opentelemetry.io/collector/processor/xprocessor v0.122.1/go.mod h1:9zMW3NQ9+DzcJ1cUq5BhZg3ajoUEMGhNY0ZdYjpX+VI= -go.opentelemetry.io/collector/receiver v1.28.1 h1:5Aw0qQVs+CcmY/YkiwPUq4+9BoLCMNv9GlL6uTOVIDw= -go.opentelemetry.io/collector/receiver v1.28.1/go.mod h1:i2Wj7MDpFnBagjFrglUssY9+tFsIThlnmK+a9JN2dzY= -go.opentelemetry.io/collector/receiver/receivertest v0.122.1 h1:QVkiAi7Pw+SrnY8zX+948W5TSsWLxuDvcuu7meOFbs4= -go.opentelemetry.io/collector/receiver/receivertest v0.122.1/go.mod h1:r++3FwxXK2hkTNaNVIwLPJkHP3iZdz9+dFsuocGpaLc= -go.opentelemetry.io/collector/receiver/xreceiver v0.122.1 h1:Mhh54HngMsJPg655MMsydJAt+rrmO3E/SIcaedP3ksQ= -go.opentelemetry.io/collector/receiver/xreceiver v0.122.1/go.mod h1:DdY1kn+y755wtelfTwv4/7WVK5caHwoW+X4oQ/OyMXc= -go.opentelemetry.io/collector/semconv v0.122.1 h1:WLzDi3QC4/+LpNMLY90zn5aMDJKyqg/ujW2O4T4sxHg= -go.opentelemetry.io/collector/semconv v0.122.1/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= -go.opentelemetry.io/collector/service v0.122.1 h1:JmogPurZ93XZJGIaortQnHmdo0/o8u01UiCL4cjNkZw= -go.opentelemetry.io/collector/service v0.122.1/go.mod h1:GwhQsH58lxxTCj8OUEIMruw6ACF5G8cs9CRl2l2nlz0= +go.opentelemetry.io/collector/pipeline/xpipeline v0.123.0 h1:YLymvvo0xdOljzZk7A1XYwtf+v4v6A+yu0GA33MZafs= +go.opentelemetry.io/collector/pipeline/xpipeline v0.123.0/go.mod h1:RmjT+wsknmOnI4L87BfMmAnQP0SO5cl8WXQJhT9kIys= +go.opentelemetry.io/collector/processor v1.29.0 h1:adymt63B45hxkMLm5Gj+XkB9hat6UafZtF3Leel6DfU= +go.opentelemetry.io/collector/processor v1.29.0/go.mod h1:slWQP4bt5rQzT05UM7BPGOOEK/6cvNBg33aY4CjKEHw= +go.opentelemetry.io/collector/processor/processortest v0.123.0 h1:oDC4eum91br/p7FfpKRpMp2k5tXE488foW+yUHzwudU= +go.opentelemetry.io/collector/processor/processortest v0.123.0/go.mod h1:Moj5M7Vm8NqGO6qCMhPPQVX4jWFJYvz/fWHdhbi7m6g= +go.opentelemetry.io/collector/processor/xprocessor v0.123.0 h1:9L9ssdId6DDeaiW7e3b+AVBlNX4ldVW9629bu7Atskw= +go.opentelemetry.io/collector/processor/xprocessor v0.123.0/go.mod h1:s51Bsyu5b4uXiB2tN4IaulqRhzYMnmglVzPzE6PHsTI= +go.opentelemetry.io/collector/receiver v1.29.0 h1:HK0bzpRlcqqdWBG2v/N76f0eauN8woIU91LloLLWeGM= +go.opentelemetry.io/collector/receiver v1.29.0/go.mod h1:4QoZQZl4r9bIrKa7VLRw3Rp7++ezc5QoXn9VoPZwfoI= +go.opentelemetry.io/collector/receiver/receivertest v0.123.0 h1:MB2x4v7Pg+npLyIQxBn/7rrW4RliV1JtcKqWM75iz1U= +go.opentelemetry.io/collector/receiver/receivertest v0.123.0/go.mod h1:eDcm8N4yFz//V5dSa6MeEdjuK5Nq1X+j9xP9kPJr8BU= +go.opentelemetry.io/collector/receiver/xreceiver v0.123.0 h1:oRExkR/d5axuvAUa3lcOf1ea+zL0hK+iGAhewqZz1NU= +go.opentelemetry.io/collector/receiver/xreceiver v0.123.0/go.mod h1:M3a0ACBOPHag90EV+GbIWKZhJkHXW7Ka2xabBGY25aw= +go.opentelemetry.io/collector/semconv v0.123.0 h1:hFjhLU1SSmsZ67pXVCVbIaejonkYf5XD/6u4qCQQPtc= +go.opentelemetry.io/collector/semconv v0.123.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= +go.opentelemetry.io/collector/service v0.123.0 h1:KPWMsbxsuesMGcyif4ulZ3JT8my5tq6MZXsJSvGjBhc= +go.opentelemetry.io/collector/service v0.123.0/go.mod h1:5VfeoadoI6wxbB11Fxu81mow9cxD05e+IL5pl+LtcJk= go.opentelemetry.io/contrib/bridges/otelzap v0.10.0 h1:ojdSRDvjrnm30beHOmwsSvLpoRF40MlwNCA+Oo93kXU= go.opentelemetry.io/contrib/bridges/otelzap v0.10.0/go.mod h1:oTTm4g7NEtHSV2i/0FeVdPaPgUIZPfQkFbq0vbzqnv0= go.opentelemetry.io/contrib/otelconf v0.15.0 h1:BLNiIUsrNcqhSKpsa6CnhE6LdrpY1A8X0szMVsu99eo= @@ -357,16 +357,16 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= -gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 4479b18eb57ceafa2282c2c7b29acdbc7ba52f43 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Tue, 1 Apr 2025 09:06:19 +0200 Subject: [PATCH 383/426] Improve CSI server logs (#4676) --- pkg/controllers/csi/driver/server.go | 37 ++++-- .../csi/driver/volumes/volume_config.go | 61 ++++++---- .../csi/driver/volumes/volume_config_test.go | 113 ++++++++++++------ 3 files changed, 143 insertions(+), 68 deletions(-) diff --git a/pkg/controllers/csi/driver/server.go b/pkg/controllers/csi/driver/server.go index 67be7015ab..59d437dc4a 100644 --- a/pkg/controllers/csi/driver/server.go +++ b/pkg/controllers/csi/driver/server.go @@ -181,7 +181,7 @@ func (srv *Server) NodePublishVolume(ctx context.Context, req *csi.NodePublishVo "mountflags", req.GetVolumeCapability().GetMount().GetMountFlags(), ) - return publisher.PublishVolume(ctx, volumeCfg) + return publisher.PublishVolume(ctx, &volumeCfg) } func (srv *Server) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) { @@ -190,7 +190,7 @@ func (srv *Server) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpubli return nil, err } - srv.unmount(*volumeInfo) + srv.unmount(volumeInfo) return &csi.NodeUnpublishVolumeResponse{}, nil } @@ -289,21 +289,38 @@ func grpcLimiter(maxGrpcRequests int32) grpc.UnaryServerInterceptor { return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { var methodName string + var logValues []any + switch info.FullMethod { case "/csi.v1.Node/NodePublishVolume": req := req.(*csi.NodePublishVolumeRequest) methodName = "NodePublishVolume" - log.Info("GRPC call", "method", methodName, "volume-id", req.GetVolumeId()) + vc, _ := csivolumes.ParseNodePublishVolumeRequest(req) + logValues = []any{ + "method", methodName, + "volume-id", vc.VolumeID, + "pod", vc.PodName, + "namespace", vc.PodNamespace, + "dynakube", vc.DynakubeName, + "mode", vc.Mode, + } + log.Info("GRPC call", logValues...) case "/csi.v1.Node/NodeUnpublishVolume": req := req.(*csi.NodeUnpublishVolumeRequest) methodName = "NodeUnpublishVolume" - log.Info("GRPC call", "method", methodName, "volume-id", req.GetVolumeId()) + vi, _ := csivolumes.ParseNodeUnpublishVolumeRequest(req) + logValues = []any{ // this is all we get + "method", methodName, + "volume-id", vi.VolumeID, + "target-path", vi.TargetPath, + } + log.Info("GRPC call", logValues...) default: log.Debug("GRPC call", "full_method", info.FullMethod) resp, err := handler(ctx, req) if err != nil { - log.Error(err, "GRPC failed", "full_method", info.FullMethod) + log.Info("GRPC failed", "full_method", info.FullMethod, "err", err.Error()) } return resp, err @@ -313,13 +330,19 @@ func grpcLimiter(maxGrpcRequests int32) grpc.UnaryServerInterceptor { defer counter.Add(-1) if counter.Load() > maxGrpcRequests { - return nil, status.Error(codes.ResourceExhausted, fmt.Sprintf("rate limit exceeded, current value %d more than max %d", counter.Load(), MaxGrpcRequests)) + msg := fmt.Sprintf("rate limit exceeded, current value %d more than max %d", counter.Load(), MaxGrpcRequests) + + log.Info(msg, logValues...) + + return nil, status.Error(codes.ResourceExhausted, msg) } resp, err := handler(ctx, req) if err != nil { - log.Error(err, "GRPC call failed", "method", methodName, "full_method", info.FullMethod) + logValues = append(logValues, "error", err.Error()) + + log.Info("GRPC call failed", logValues...) } return resp, err diff --git a/pkg/controllers/csi/driver/volumes/volume_config.go b/pkg/controllers/csi/driver/volumes/volume_config.go index c53bd2415c..69d0aea4cc 100644 --- a/pkg/controllers/csi/driver/volumes/volume_config.go +++ b/pkg/controllers/csi/driver/volumes/volume_config.go @@ -36,49 +36,61 @@ type VolumeConfig struct { } // Transforms the NodePublishVolumeRequest into a VolumeConfig -func ParseNodePublishVolumeRequest(req *csi.NodePublishVolumeRequest) (*VolumeConfig, error) { +func ParseNodePublishVolumeRequest(req *csi.NodePublishVolumeRequest) (VolumeConfig, error) { + volumeConfig := VolumeConfig{} + volumeInfo, err := newVolumeInfo(req) + volumeConfig.VolumeInfo = volumeInfo + if err != nil { - return nil, err + return volumeConfig, err } if req.GetVolumeCapability() == nil { - return nil, status.Error(codes.InvalidArgument, "Volume capability missing in request") + return volumeConfig, status.Error(codes.InvalidArgument, "Volume capability missing in request") } if req.GetVolumeCapability().GetBlock() != nil { - return nil, status.Error(codes.InvalidArgument, "cannot have block access type") + return volumeConfig, status.Error(codes.InvalidArgument, "cannot have block access type") } if req.GetVolumeCapability().GetMount() == nil { - return nil, status.Error(codes.InvalidArgument, "expecting to have mount access type") + return volumeConfig, status.Error(codes.InvalidArgument, "expecting to have mount access type") } volCtx := req.GetVolumeContext() if volCtx == nil { - return nil, status.Error(codes.InvalidArgument, "Publish context missing in request") + return volumeConfig, status.Error(codes.InvalidArgument, "Publish context missing in request") } podName := volCtx[PodNameContextKey] if podName == "" { - return nil, status.Error(codes.InvalidArgument, "No Pod Name included in request") + return volumeConfig, status.Error(codes.InvalidArgument, "No Pod Name included in request") } + volumeConfig.PodName = podName + podNamespace := volCtx[PodNamespaceContextKey] if podNamespace == "" { - return nil, status.Error(codes.InvalidArgument, "No Pod Namespace included in request") + return volumeConfig, status.Error(codes.InvalidArgument, "No Pod Namespace included in request") } + volumeConfig.PodNamespace = podNamespace + mode := volCtx[CSIVolumeAttributeModeField] if mode == "" { - return nil, status.Error(codes.InvalidArgument, "No mode attribute included in request") + return volumeConfig, status.Error(codes.InvalidArgument, "No mode attribute included in request") } + volumeConfig.Mode = mode + dynakubeName := volCtx[CSIVolumeAttributeDynakubeField] if dynakubeName == "" { - return nil, status.Error(codes.InvalidArgument, "No dynakube attribute included in request") + return volumeConfig, status.Error(codes.InvalidArgument, "No dynakube attribute included in request") } + volumeConfig.DynakubeName = dynakubeName + retryTimeoutValue := volCtx[CSIVolumeAttributeRetryTimeout] if retryTimeoutValue == "" { retryTimeoutValue = dynakube.DefaultMaxCsiMountTimeout @@ -86,21 +98,16 @@ func ParseNodePublishVolumeRequest(req *csi.NodePublishVolumeRequest) (*VolumeCo retryTimeout, err := time.ParseDuration(retryTimeoutValue) if err != nil { - return nil, status.Error(codes.InvalidArgument, "The retryTimeout attribute has incorrect format") + return volumeConfig, status.Error(codes.InvalidArgument, "The retryTimeout attribute has incorrect format") } - return &VolumeConfig{ - VolumeInfo: *volumeInfo, - PodName: podName, - PodNamespace: podNamespace, - Mode: mode, - DynakubeName: dynakubeName, - RetryTimeout: retryTimeout, - }, nil + volumeConfig.RetryTimeout = retryTimeout + + return volumeConfig, nil } // Transforms the NodeUnpublishVolumeRequest into a VolumeInfo -func ParseNodeUnpublishVolumeRequest(req *csi.NodeUnpublishVolumeRequest) (*VolumeInfo, error) { +func ParseNodeUnpublishVolumeRequest(req *csi.NodeUnpublishVolumeRequest) (VolumeInfo, error) { return newVolumeInfo(req) } @@ -109,16 +116,22 @@ type baseRequest interface { GetTargetPath() string } -func newVolumeInfo(req baseRequest) (*VolumeInfo, error) { +func newVolumeInfo(req baseRequest) (VolumeInfo, error) { + info := VolumeInfo{} + volumeID := req.GetVolumeId() if volumeID == "" { - return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request") + return info, status.Error(codes.InvalidArgument, "Volume ID missing in request") } + info.VolumeID = volumeID + targetPath := req.GetTargetPath() if targetPath == "" { - return nil, status.Error(codes.InvalidArgument, "Target path missing in request") + return info, status.Error(codes.InvalidArgument, "Target path missing in request") } - return &VolumeInfo{volumeID, targetPath}, nil + info.TargetPath = targetPath + + return info, nil } diff --git a/pkg/controllers/csi/driver/volumes/volume_config_test.go b/pkg/controllers/csi/driver/volumes/volume_config_test.go index f546fd9f71..15b75cd4c9 100644 --- a/pkg/controllers/csi/driver/volumes/volume_config_test.go +++ b/pkg/controllers/csi/driver/volumes/volume_config_test.go @@ -17,32 +17,36 @@ const ( ) func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { - t.Run(`No volume id`, func(t *testing.T) { + t.Run("No volume id", func(t *testing.T) { request := &csi.NodePublishVolumeRequest{} volumeCfg, err := ParseNodePublishVolumeRequest(request) require.EqualError(t, err, "rpc error: code = InvalidArgument desc = Volume ID missing in request") - assert.Nil(t, volumeCfg) + assert.NotNil(t, volumeCfg) }) - t.Run(`No target path`, func(t *testing.T) { + t.Run("No target path", func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeId: testVolumeId, } volumeCfg, err := ParseNodePublishVolumeRequest(request) require.EqualError(t, err, "rpc error: code = InvalidArgument desc = Target path missing in request") - assert.Nil(t, volumeCfg) + require.NotNil(t, volumeCfg) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) }) - t.Run(`No volume capability`, func(t *testing.T) { - volumeCfg, err := ParseNodePublishVolumeRequest(&csi.NodePublishVolumeRequest{ + t.Run("No volume capability", func(t *testing.T) { + request := &csi.NodePublishVolumeRequest{ VolumeId: testVolumeId, TargetPath: testTargetPath, - }) + } + volumeCfg, err := ParseNodePublishVolumeRequest(request) require.EqualError(t, err, "rpc error: code = InvalidArgument desc = Volume capability missing in request") - assert.Nil(t, volumeCfg) + require.NotNil(t, volumeCfg) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) + assert.Equal(t, request.GetTargetPath(), volumeCfg.TargetPath) }) - t.Run(`Access type is of type block access`, func(t *testing.T) { + t.Run("Access type is of type block access", func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeCapability: &csi.VolumeCapability{ AccessType: &csi.VolumeCapability_Block{ @@ -55,9 +59,11 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { volumeCfg, err := ParseNodePublishVolumeRequest(request) require.EqualError(t, err, "rpc error: code = InvalidArgument desc = cannot have block access type") - assert.Nil(t, volumeCfg) + require.NotNil(t, volumeCfg) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) + assert.Equal(t, request.GetTargetPath(), volumeCfg.TargetPath) }) - t.Run(`Access type is not of type mount access`, func(t *testing.T) { + t.Run("Access type is not of type mount access", func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeCapability: &csi.VolumeCapability{}, VolumeId: testVolumeId, @@ -66,9 +72,11 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { volumeCfg, err := ParseNodePublishVolumeRequest(request) require.EqualError(t, err, "rpc error: code = InvalidArgument desc = expecting to have mount access type") - assert.Nil(t, volumeCfg) + require.NotNil(t, volumeCfg) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) + assert.Equal(t, request.GetTargetPath(), volumeCfg.TargetPath) }) - t.Run(`No volume context`, func(t *testing.T) { + t.Run("No volume context", func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeCapability: &csi.VolumeCapability{ AccessType: &csi.VolumeCapability_Mount{ @@ -81,9 +89,29 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { volumeCfg, err := ParseNodePublishVolumeRequest(request) require.EqualError(t, err, "rpc error: code = InvalidArgument desc = Publish context missing in request") - assert.Nil(t, volumeCfg) + require.NotNil(t, volumeCfg) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) + assert.Equal(t, request.GetTargetPath(), volumeCfg.TargetPath) + }) + t.Run("Pod name missing from requests volume context", func(t *testing.T) { + request := &csi.NodePublishVolumeRequest{ + VolumeCapability: &csi.VolumeCapability{ + AccessType: &csi.VolumeCapability_Mount{ + Mount: &csi.VolumeCapability_MountVolume{}, + }, + }, + VolumeId: testVolumeId, + TargetPath: testTargetPath, + VolumeContext: map[string]string{}, + } + volumeCfg, err := ParseNodePublishVolumeRequest(request) + + require.Error(t, err) + require.NotNil(t, volumeCfg) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) + assert.Equal(t, request.GetTargetPath(), volumeCfg.TargetPath) }) - t.Run(`Pod name missing from requests volume context`, func(t *testing.T) { + t.Run("Pod namespace missing from requests volume context", func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeCapability: &csi.VolumeCapability{ AccessType: &csi.VolumeCapability_Mount{ @@ -93,17 +121,18 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { VolumeId: testVolumeId, TargetPath: testTargetPath, VolumeContext: map[string]string{ - CSIVolumeAttributeDynakubeField: testDynakubeName, - CSIVolumeAttributeModeField: "test", - CSIVolumeAttributeRetryTimeout: "5m", + PodNameContextKey: testPodUID, }, } volumeCfg, err := ParseNodePublishVolumeRequest(request) require.Error(t, err) - assert.Nil(t, volumeCfg) + require.NotNil(t, volumeCfg) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) + assert.Equal(t, request.GetTargetPath(), volumeCfg.TargetPath) + assert.Equal(t, request.GetVolumeContext()[PodNameContextKey], volumeCfg.PodName) }) - t.Run(`mode missing from requests volume context`, func(t *testing.T) { + t.Run("mode missing from requests volume context", func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeCapability: &csi.VolumeCapability{ AccessType: &csi.VolumeCapability_Mount{ @@ -113,17 +142,20 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { VolumeId: testVolumeId, TargetPath: testTargetPath, VolumeContext: map[string]string{ - PodNameContextKey: testPodUID, - CSIVolumeAttributeDynakubeField: testDynakubeName, - CSIVolumeAttributeRetryTimeout: "5m", + PodNameContextKey: testPodUID, + PodNamespaceContextKey: testNs, }, } volumeCfg, err := ParseNodePublishVolumeRequest(request) require.Error(t, err) - assert.Nil(t, volumeCfg) + require.NotNil(t, volumeCfg) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) + assert.Equal(t, request.GetTargetPath(), volumeCfg.TargetPath) + assert.Equal(t, request.GetVolumeContext()[PodNameContextKey], volumeCfg.PodName) + assert.Equal(t, request.GetVolumeContext()[PodNamespaceContextKey], volumeCfg.PodNamespace) }) - t.Run(`dynakube missing from requests volume context`, func(t *testing.T) { + t.Run("dk name missing from requests volume context", func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeCapability: &csi.VolumeCapability{ AccessType: &csi.VolumeCapability_Mount{ @@ -133,17 +165,23 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { VolumeId: testVolumeId, TargetPath: testTargetPath, VolumeContext: map[string]string{ - PodNameContextKey: testPodUID, - CSIVolumeAttributeModeField: "test", - CSIVolumeAttributeRetryTimeout: "5m", + PodNameContextKey: testPodUID, + PodNamespaceContextKey: testNs, + CSIVolumeAttributeModeField: "test", }, } volumeCfg, err := ParseNodePublishVolumeRequest(request) require.Error(t, err) - assert.Nil(t, volumeCfg) + require.NotNil(t, volumeCfg) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) + assert.Equal(t, request.GetTargetPath(), volumeCfg.TargetPath) + assert.Equal(t, request.GetVolumeContext()[PodNameContextKey], volumeCfg.PodName) + assert.Equal(t, request.GetVolumeContext()[PodNamespaceContextKey], volumeCfg.PodNamespace) + assert.Equal(t, request.GetVolumeContext()[CSIVolumeAttributeModeField], volumeCfg.Mode) }) - t.Run(`request is parsed correctly`, func(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { request := &csi.NodePublishVolumeRequest{ VolumeCapability: &csi.VolumeCapability{ AccessType: &csi.VolumeCapability_Mount{ @@ -155,19 +193,20 @@ func TestCSIDriverServer_ParsePublishVolumeRequest(t *testing.T) { VolumeContext: map[string]string{ PodNameContextKey: testPodUID, PodNamespaceContextKey: testNs, - CSIVolumeAttributeDynakubeField: testDynakubeName, CSIVolumeAttributeModeField: "test", + CSIVolumeAttributeDynakubeField: "dk", }, } volumeCfg, err := ParseNodePublishVolumeRequest(request) require.NoError(t, err) assert.NotNil(t, volumeCfg) - assert.Equal(t, testVolumeId, volumeCfg.VolumeID) - assert.Equal(t, testTargetPath, volumeCfg.TargetPath) - assert.Equal(t, testPodUID, volumeCfg.PodName) - assert.Equal(t, testNs, volumeCfg.PodNamespace) - assert.Equal(t, "test", volumeCfg.Mode) - assert.Equal(t, testDynakubeName, volumeCfg.DynakubeName) + assert.Equal(t, request.GetVolumeId(), volumeCfg.VolumeID) + assert.Equal(t, request.GetTargetPath(), volumeCfg.TargetPath) + assert.Equal(t, request.GetVolumeContext()[PodNameContextKey], volumeCfg.PodName) + assert.Equal(t, request.GetVolumeContext()[PodNamespaceContextKey], volumeCfg.PodNamespace) + assert.Equal(t, request.GetVolumeContext()[CSIVolumeAttributeModeField], volumeCfg.Mode) + assert.Equal(t, request.GetVolumeContext()[CSIVolumeAttributeDynakubeField], volumeCfg.DynakubeName) + assert.NotNil(t, volumeCfg.RetryTimeout) }) } From 2e7885b9cdce49cbd6bbc886d23b7b6897cb7e12 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Apr 2025 12:48:40 +0000 Subject: [PATCH 384/426] fix(deps): update module google.golang.org/grpc to v1.71.1 (main) (#4683) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b22ee53fbe..bc7c27a6bf 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( golang.org/x/net v0.38.0 golang.org/x/oauth2 v0.28.0 golang.org/x/sys v0.31.0 - google.golang.org/grpc v1.71.0 + google.golang.org/grpc v1.71.1 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.25.1 istio.io/client-go v1.25.1 diff --git a/go.sum b/go.sum index 55aa833e4a..f8667a2634 100644 --- a/go.sum +++ b/go.sum @@ -363,8 +363,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1: google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 391682987699f730ab89973e91871579d677bb13 Mon Sep 17 00:00:00 2001 From: aorcholski <84514340+aorcholski@users.noreply.github.com> Date: Tue, 1 Apr 2025 16:25:23 +0200 Subject: [PATCH 385/426] Fix kspm cert volume related to AG TLS secret (#4685) --- .../dynakube/kspm/daemonset/certs.go | 2 +- .../dynakube/kspm/daemonset/certs_test.go | 9 +++++ .../dynakube/kspm/daemonset/volumes_test.go | 36 ++++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/pkg/controllers/dynakube/kspm/daemonset/certs.go b/pkg/controllers/dynakube/kspm/daemonset/certs.go index 938409d740..3ee281d980 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/certs.go +++ b/pkg/controllers/dynakube/kspm/daemonset/certs.go @@ -16,7 +16,7 @@ func getCertVolume(dk dynakube.DynaKube) corev1.Volume { Name: certVolumeName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: dk.ActiveGate().TlsSecretName, + SecretName: dk.ActiveGate().GetTLSSecretName(), }, }, } diff --git a/pkg/controllers/dynakube/kspm/daemonset/certs_test.go b/pkg/controllers/dynakube/kspm/daemonset/certs_test.go index bbb6c5bfac..e982cf83f1 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/certs_test.go +++ b/pkg/controllers/dynakube/kspm/daemonset/certs_test.go @@ -16,3 +16,12 @@ func getDynaKubeWithCerts(t *testing.T) dynakube.DynaKube { return dk } + +func getDynaKubeWithAutomaticCerts(t *testing.T) dynakube.DynaKube { + t.Helper() + + dk := dynakube.DynaKube{} + dk.ActiveGate().Capabilities = []activegate.CapabilityDisplayName{activegate.KubeMonCapability.DisplayName} + + return dk +} diff --git a/pkg/controllers/dynakube/kspm/daemonset/volumes_test.go b/pkg/controllers/dynakube/kspm/daemonset/volumes_test.go index 01255049ff..652591319b 100644 --- a/pkg/controllers/dynakube/kspm/daemonset/volumes_test.go +++ b/pkg/controllers/dynakube/kspm/daemonset/volumes_test.go @@ -39,6 +39,19 @@ func TestGetMounts(t *testing.T) { assert.NotEmpty(t, mount.MountPath) } }) + + t.Run("get cert mount with automatic AG cert", func(t *testing.T) { + dk := getDynaKubeWithAutomaticCerts(t) + mounts := getMounts(dk) + + require.NotEmpty(t, mounts) + assert.Len(t, mounts, expectedMountLen+1) + + for _, mount := range mounts { + assert.NotEmpty(t, mount.Name) + assert.NotEmpty(t, mount.MountPath) + } + }) } func TestGetVolumes(t *testing.T) { @@ -64,7 +77,28 @@ func TestGetVolumes(t *testing.T) { for _, volume := range volumes { assert.NotEmpty(t, volume.Name) - assert.NotEmpty(t, volume.VolumeSource) + require.NotEmpty(t, volume.VolumeSource) + + if volume.Name == certVolumeName { + assert.NotEmpty(t, volume.VolumeSource.Secret.SecretName) + } + } + }) + + t.Run("add cert volume with automatic AG cert", func(t *testing.T) { + dk := getDynaKubeWithAutomaticCerts(t) + volumes := getVolumes(dk) + + require.NotEmpty(t, volumes) + assert.Len(t, volumes, expectedMountLen+1) + + for _, volume := range volumes { + assert.NotEmpty(t, volume.Name) + require.NotEmpty(t, volume.VolumeSource) + + if volume.Name == certVolumeName { + assert.NotEmpty(t, volume.VolumeSource.Secret.SecretName) + } } }) } From 32a888db81c111ff6e8b4c3c07732ab3054cbb5d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Apr 2025 22:21:45 +0000 Subject: [PATCH 386/426] chore(deps): update golang docker tag to v1.24.2 (main) (#4690) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ddae2c5b9a..eaab6cbfc4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # check=skip=RedundantTargetPlatform # setup build image -FROM --platform=$BUILDPLATFORM golang:1.24.1@sha256:c5adecdb7b3f8c5ca3c88648a861882849cc8b02fed68ece31e25de88ad13418 AS operator-build +FROM --platform=$BUILDPLATFORM golang:1.24.2@sha256:991aa6a6e4431f2f01e869a812934bd60fbc87fb939e4a1ea54b8494ab9d2fc6 AS operator-build WORKDIR /app From f49c537b834b1cda65f0af36fcf104e31c543f9e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 2 Apr 2025 08:00:54 +0000 Subject: [PATCH 387/426] chore(deps): update dependency json5 to v0.11.0 (main) (#4691) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/requirements.txt b/hack/requirements.txt index d6fa32b5ee..eb0dc739bf 100644 --- a/hack/requirements.txt +++ b/hack/requirements.txt @@ -1,4 +1,4 @@ argparse==1.4.0 pyyaml==6.0.2 -json5==0.10.0 +json5==0.11.0 ruamel.yaml==0.18.10 From 5875110ad7ff503163990ffd56cc37d6038a77ba Mon Sep 17 00:00:00 2001 From: Christoph Muellner <33160506+chrismuellner@users.noreply.github.com> Date: Wed, 2 Apr 2025 16:11:18 +0200 Subject: [PATCH 388/426] Update samples (#4694) --- .../v1beta3/applicationMonitoring.yaml | 161 +++++++++++- .../dynakube/v1beta3/classicFullStack.yaml | 218 +++++++++++++++- .../v1beta3/cloudNativeFullStack.yaml | 245 +++++++++++++++++- .../dynakube/v1beta3/hostMonitoring.yaml | 218 +++++++++++++++- .../v1beta3/kubernetesObservability.yaml | 129 ++++++++- .../kubernetesSecurityPostureManagement.yaml | 193 ++++++++++++-- .../dynakube/v1beta3/logMonitoring.yaml | 213 +++++++++++++-- .../v1beta4/applicationMonitoring.yaml | 64 ++--- .../dynakube/v1beta4/classicFullStack.yaml | 21 +- .../v1beta4/cloudNativeFullStack.yaml | 6 +- .../dynakube/v1beta4/hostMonitoring.yaml | 5 +- .../v1beta4/kubernetesObservability.yaml | 4 +- .../kubernetesSecurityPostureManagement.yaml | 6 +- .../dynakube/v1beta4/logMonitoring.yaml | 9 +- 14 files changed, 1405 insertions(+), 87 deletions(-) diff --git a/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml b/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml index 38251f3aa6..15a2783173 100644 --- a/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml +++ b/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml @@ -4,15 +4,174 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + metadataEnrichment: + enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for OneAgent + # oneAgent: + # Optional: Set a host group for OneAgent + # + # hostGroup: "" + applicationMonitoring: {} + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Optional: The OneAgent version to be used. + # Example: ..., e.g. 1.200.0.20240101-000000 + # + # version: "" + + # Optional: Define resources requests and limits for the initContainer. + # + # initResources: + # requests: + # cpu: 30m + # memory: 30Mi + # limits: + # cpu: 100m + # memory: 60Mi + # Optional: The OneAgent image that is used to inject into pods + # + # codeModulesImage: "" + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - routing - kubernetes-monitoring - dynatrace-api + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta3/classicFullStack.yaml b/assets/samples/dynakube/v1beta3/classicFullStack.yaml index 050ca5ad47..e8766afac1 100644 --- a/assets/samples/dynakube/v1beta3/classicFullStack.yaml +++ b/assets/samples/dynakube/v1beta3/classicFullStack.yaml @@ -4,15 +4,229 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for Log monitoring. + # + # logMonitoring: {} + + # Optional: Specifies the rules and conditions for matching ingest attributes. + # + # ingestRuleMatchers: + # - attribute: "k8s.namespace.name" + # values: + # - "kube-system" + # - "dynatrace" + # - "default" + # - attribute: "k8s.pod.annotation", + # values: + # - "logs.dynatrace.com/ingest=true" + # - "category=security" + + # Configuration for OneAgent + # oneAgent: - classicFullStack: {} + # Optional: Set a host group for OneAgent + # + # hostGroup: "" + + classicFullStack: + # Optional: Specify the node selector that controls on which nodes OneAgent will be deployed. + # + # nodeSelector: {} + + # Optional: Assign a priority class to the OneAgent pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the OneAgent DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for OneAgent container. + # + # oneAgentResources: + # requests: + # cpu: 100m + # memory: 512Mi + # limits: + # cpu: 300m + # memory: 1.5Gi + + # Optional: Set additional arguments to the OneAgent installer. + # + # args: [] + + # Optional: Set additional environment variables for the OneAgent pods. + # + # env: [] + + # Optional: Disable automatic restarts of OneAgent pods in case a new version is available + # + # autoUpdate: true + # Optional: Set the DNS Policy for OneAgent pods. + # + # dnsPolicy: "ClusterFirstWithHostNet" + + # Optional: Add custom OneAgent annotations. + # + # annotations: + # custom: annotation + + # Optional: Add custom labels to OneAgent pods + # + # labels: + # custom: label + + # Optional: Use a custom OneAgent image. + # + # image: "" + + # Optional: The OneAgent version to be used. + # Example: ..., e.g. 1.200.0.20240101-000000 + # + # version: "" + + # Optional: The SecComp Profile that will be configured in order to run in secure computing mode. + # + # secCompProfile: "" + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - routing - kubernetes-monitoring - dynatrace-api + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml b/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml index 2bb9bb5db4..730f5e6ab6 100644 --- a/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml +++ b/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml @@ -4,15 +4,254 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters - + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + metadataEnrichment: + enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for Log monitoring. + # + # logMonitoring: {} + + # Optional: Specifies the rules and conditions for matching ingest attributes. + # + # ingestRuleMatchers: + # - attribute: "k8s.namespace.name" + # values: + # - "kube-system" + # - "dynatrace" + # - "default" + # - attribute: "k8s.pod.annotation", + # values: + # - "logs.dynatrace.com/ingest=true" + # - "category=security" + + # Configuration for OneAgent + # oneAgent: - cloudNativeFullStack: {} + # Optional: Set a host group for OneAgent + # + # hostGroup: "" + + cloudNativeFullStack: + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Optional: Specify the node selector that controls on which nodes OneAgent will be deployed. + # + # nodeSelector: {} + + # Optional: Assign a priority class to the OneAgent pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the OneAgent DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for OneAgent container. + # + # oneAgentResources: + # requests: + # cpu: 100m + # memory: 512Mi + # limits: + # cpu: 300m + # memory: 1.5Gi + + # Optional: Set additional arguments to the OneAgent installer. + # + # args: [] + + # Optional: Set additional environment variables for the OneAgent pods. + # + # env: [] + + # Optional: Disable automatic restarts of OneAgent pods in case a new version is available + # + # autoUpdate: true + # Optional: Set the DNS Policy for OneAgent pods. + # + # dnsPolicy: "ClusterFirstWithHostNet" + + # Optional: Add custom OneAgent annotations. + # + # annotations: + # custom: annotation + + # Optional: Add custom labels to OneAgent pods + # + # labels: + # custom: label + + # Optional: Use a custom OneAgent image. + # + # image: "" + + # Optional: The OneAgent version to be used. + # Example: ..., e.g. 1.200.0.20240101-000000 + # + # version: "" + + # Optional: Define resources requests and limits for the initContainer. + # + # initResources: + # requests: + # cpu: 30m + # memory: 30Mi + # limits: + # cpu: 100m + # memory: 60Mi + + # Optional: The OneAgent image that is used to inject into pods + # + # codeModulesImage: "" + + # Optional: The SecComp Profile that will be configured in order to run in secure computing mode. + # + # secCompProfile: "" + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - routing - kubernetes-monitoring - dynatrace-api + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta3/hostMonitoring.yaml b/assets/samples/dynakube/v1beta3/hostMonitoring.yaml index 42103677d4..8b215f6f33 100644 --- a/assets/samples/dynakube/v1beta3/hostMonitoring.yaml +++ b/assets/samples/dynakube/v1beta3/hostMonitoring.yaml @@ -4,15 +4,229 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for Log monitoring. + # + # logMonitoring: {} + + # Optional: Specifies the rules and conditions for matching ingest attributes. + # + # ingestRuleMatchers: + # - attribute: "k8s.namespace.name" + # values: + # - "kube-system" + # - "dynatrace" + # - "default" + # - attribute: "k8s.pod.annotation", + # values: + # - "logs.dynatrace.com/ingest=true" + # - "category=security" + + # Configuration for OneAgent + # oneAgent: - hostMonitoring: {} + # Optional: Set a host group for OneAgent + # + # hostGroup: "" + + hostMonitoring: + # Optional: Specify the node selector that controls on which nodes OneAgent will be deployed. + # + # nodeSelector: {} + + # Optional: Assign a priority class to the OneAgent pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the OneAgent DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for OneAgent container. + # + # oneAgentResources: + # requests: + # cpu: 100m + # memory: 512Mi + # limits: + # cpu: 300m + # memory: 1.5Gi + + # Optional: Set additional arguments to the OneAgent installer. + # + # args: [] + + # Optional: Set additional environment variables for the OneAgent pods. + # + # env: [] + + # Optional: Disable automatic restarts of OneAgent pods in case a new version is available + # + # autoUpdate: true + # Optional: Set the DNS Policy for OneAgent pods. + # + # dnsPolicy: "ClusterFirstWithHostNet" + + # Optional: Add custom OneAgent annotations. + # + # annotations: + # custom: annotation + + # Optional: Add custom labels to OneAgent pods + # + # labels: + # custom: label + + # Optional: Use a custom OneAgent image. + # + # image: "" + + # Optional: The OneAgent version to be used. + # Example: ..., e.g. 1.200.0.20240101-000000 + # + # version: "" + + # Optional: The SecComp Profile that will be configured in order to run in secure computing mode. + # + # secCompProfile: "" + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - routing - kubernetes-monitoring - dynatrace-api + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml b/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml index 84230e0392..0b2792fd91 100644 --- a/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml +++ b/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml @@ -4,12 +4,137 @@ metadata: name: dynakube namespace: dynatrace # annotations: - # feature.dynatrace.com/k8s-app-enabled: "true" + # feature.dynatrace.com/k8s-app-enabled: "true" spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - kubernetes-monitoring + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [connectivity] + # networkZone= + # valueFrom: myCustomPropertiesSecret + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] diff --git a/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml b/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml index c4719e087e..7c9fb4d1e0 100644 --- a/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml +++ b/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml @@ -4,29 +4,192 @@ metadata: name: dynakube namespace: dynatrace spec: + # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + + # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + # metadataEnrichment: + # enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] kspm: {} + # Configuration for ActiveGate instances. + # activeGate: - tlsSecretName: - + # Defines the ActiveGate capabilities + # capabilities: - kubernetes-monitoring - customProperties: - value: | - [kubernetes_monitoring] - kubernetes_configuration_dataset_pipeline_enabled = true - kubernetes_configuration_dataset_pipeline_include_node_config = true + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [kubernetes_monitoring] + # kubernetes_configuration_dataset_pipeline_enabled = true + # kubernetes_configuration_dataset_pipeline_include_node_config = true + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} - templates: {} - # Required in combination with kspm enabled. - # As there is no image available in public registry yet, this field is required if you want to run kspm. + # Optional: Set tolerations for the ActiveGate pods. # - # kspmNodeConfigurationCollector: - # imageRef: - # repository: - # tag: + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] + + templates: + kspmNodeConfigurationCollector: + # Required: Configure the image for the Node Configuration Collector. + imageRef: + repository: public.ecr.aws/dynatrace/dynatrace-k8s-node-config-collector + tag: + + # Optional: Define the update strategy for the Node Configuration Collector daemonSet + # + # updateStrategy: {} + + # Optional: Add custom labels to NNode Configuration Collector pods + # + # labels: + # custom: label + + # Optional: Add custom annotations to Node Configuration Collector pods. + # + # annotations: + # custom: annotation + + # Optional: Specify the node selector that controls on which nodes OneAgent will be deployed. + # + # nodeSelector: {} + + # Optional: Define the nodeAffinity for the DaemonSet of the Node Configuration Collector + # + # nodeAffinity: {} + + # Optional: Assign a priority class to the Node Configuration Collector pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the Node Configuration Collector DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for Node Configuration Collector container. + # + # resources: {} + + # Optional: Set additional arguments to the Node Configuration Collector. + # + # args: [] + + # Optional: Set additional environment variables for the Node Configuration Collector pods. + # + # env: [] diff --git a/assets/samples/dynakube/v1beta3/logMonitoring.yaml b/assets/samples/dynakube/v1beta3/logMonitoring.yaml index bb505e36b5..f55ad58e2e 100644 --- a/assets/samples/dynakube/v1beta3/logMonitoring.yaml +++ b/assets/samples/dynakube/v1beta3/logMonitoring.yaml @@ -3,26 +3,209 @@ kind: DynaKube metadata: name: dynakube namespace: dynatrace +# annotations: +# feature.dynatrace.com/oneagent-privileged: "true" # Required on Openshift spec: - apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters - # The `logMonitoring` section is used to configure log collection via the OneAgent Log module. - # it can be used with any other DynaKube mode, e.g. applicationMonitoring. - # Available with Dynatrace version 1.306+ and OneAgent 1.305+ + # Required: Dynatrace apiUrl including the `/api` path at the end. + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" + + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false + + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret + + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap + + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone + + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true + + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 + + # Configuration for Metadata Enrichment. + # + metadataEnrichment: + enabled: true + + # Optional: The namespaces where you want Dynatrace Operator to inject + # + # namespaceSelector: + # matchLabels: + # app: my-app + # matchExpressions: + # - key: app + # operator: In + # values: [my-frontend, my-backend, my-database] + # Configuration for Log monitoring. + # logMonitoring: {} - + + # Optional: Specifies the rules and conditions for matching ingest attributes. + # + # ingestRuleMatchers: + # - attribute: "k8s.namespace.name" + # values: + # - "kube-system" + # - "dynatrace" + # - "default" + # - attribute: "k8s.pod.annotation", + # values: + # - "logs.dynatrace.com/ingest=true" + # - "category=security" + + # Configuration for ActiveGate instances. + # activeGate: + # Defines the ActiveGate capabilities + # capabilities: - kubernetes-monitoring - - templates: {} - # Required in combination with logMonitoring enabled. - # As there is no image available in public registry yet, this field is required if you want to run logMonitoring. - # - # logMonitoring: - # imageRef: - # repository: - # tag: + + # Optional: Amount of replicas of ActiveGate pods. + # + # replicas: 1 + + # Optional: Use a custom ActiveGate image + # + # image: "" + + # Optional: Set the ActiveGate group + # + # group: "" + + # Optional: Add a custom properties file by providing it as a value or by referencing it from a secret. + # + # customProperties: + # value: | + # [kubernetes_monitoring] + # kubernetes_configuration_dataset_pipeline_enabled = true + # kubernetes_configuration_dataset_pipeline_include_node_config = true + + # Optional: Resource settings for ActiveGate container. + # + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 1.5Gi + + # Optional: Specify the node selector that controls on which nodes ActiveGate will be deployed. + # + # nodeSelector: {} + + # Optional: Set tolerations for the ActiveGate pods. + # + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # operator: Exists + + # Optional: Add custom labels to ActiveGate pods + # + # labels: + # custom: label + + # Optional: Add custom environment variables to ActiveGate pods + # + # env: [] + + # Optional: Name of a secret containing ActiveGate TLS certificate, key, and password. + # + # tlsSecretName: "my-tls-secret" + + # Optional: Set the DNS policy for ActiveGate pods. + # + # dnsPolicy: "Default" + + # Optional: Assign a priority class to the ActiveGate pods. + # + # priorityClassName: priority-class + + # Optional: Add custom annotations to ActiveGate pods + # + # annotations: + # custom: annotation + + # Optional: Add TopologySpreadConstraints to the ActiveGate pods + # + # topologySpreadConstraints: [] + + templates: + logMonitoring: + imageRef: + repository: public.ecr.aws/dynatrace/dynatrace-logmodule + tag: + + # Optional: Define the update strategy for the Log monitoring daemonSet + # + # updateStrategy: {} + + # Optional: Add custom labels to Log monitoring pods + # + # labels: + # custom: label + + # Optional: Add custom annotations to Log monitoring pods. + # + # annotations: + # custom: annotation + + # Optional: Specify the node selector that controls on which nodes Log monitoring will be deployed. + # + # nodeSelector: {} + + # Optional: Define the nodeAffinity for the Log monitoring DaemonSet + # + # nodeAffinity: {} + + # Optional: Assign a priority class to the Log monitoring pods. + # + # priorityClassName: priority-class + + # Optional: Tolerations to include with the Log monitoring DaemonSet. + # + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + + # Optional: Resource settings for Log monitoring container. + # + # resources: {} + + # Optional: Set additional arguments to Log monitoring + # + # args: [] + + # Optional: Set additional environment variables for the Log monitoring pods. + # + # env: [] \ No newline at end of file diff --git a/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml b/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml index a17d25df43..29dfee6b15 100644 --- a/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml @@ -9,44 +9,44 @@ spec: # Required: Dynatrace apiUrl including the `/api` path at the end. apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. - # - # tokens: "" + # Optional: Name of the secret holding the tokens used for connecting to Dynatrace. + # + # tokens: "" - # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment - # - # customPullSecret: "custom-pull-secret" + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # + # customPullSecret: "custom-pull-secret" - # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. - # - # skipCertCheck: false + # Optional: Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + # + # skipCertCheck: false - # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' - # - # proxy: - # value: my-proxy-url.com - # valueFrom: name-of-my-proxy-secret + # Optional: Set custom proxy settings either directly or from a secret with the field 'proxy' + # + # proxy: + # value: my-proxy-url.com + # valueFrom: name-of-my-proxy-secret - # Optional: Add custom RootCAs from a configmap. - # - # trustedCAs: name-of-my-ca-configmap + # Optional: Add custom RootCAs from a configmap. + # + # trustedCAs: name-of-my-ca-configmap - # Optional: Set a network zone for the OneAgent and ActiveGate pods. - # - # networkZone: name-of-my-network-zone + # Optional: Set a network zone for the OneAgent and ActiveGate pods. + # + # networkZone: name-of-my-network-zone - # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. - # - # enableIstio: true + # Optional: Configure istio to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate pods. + # + # enableIstio: true - # Optional: Minimum minutes between Dynatrace API requests. - # - # dynatraceApiRequestThreshold: 15 + # Optional: Minimum minutes between Dynatrace API requests. + # + # dynatraceApiRequestThreshold: 15 - # Configuration for Metadata Enrichment. - # - # metadataEnrichment: - # enabled: true + # Configuration for Metadata Enrichment. + # + metadataEnrichment: + enabled: true # Optional: The namespaces where you want Dynatrace Operator to inject # @@ -56,12 +56,12 @@ spec: # matchExpressions: # - key: app # operator: In - # values: [my-frontend, my-backend, my-database] + # values: [my-frontend, my-backend, my-database] # Configuration for OneAgent # oneAgent: - # Optional: Set a host group for OneAgent. + # Optional: Set a host group for OneAgent # # hostGroup: "" diff --git a/assets/samples/dynakube/v1beta4/classicFullStack.yaml b/assets/samples/dynakube/v1beta4/classicFullStack.yaml index 160e61201e..ac3e4ac790 100644 --- a/assets/samples/dynakube/v1beta4/classicFullStack.yaml +++ b/assets/samples/dynakube/v1beta4/classicFullStack.yaml @@ -46,7 +46,7 @@ spec: # Configuration for Metadata Enrichment. # # metadataEnrichment: - # enabled: true + # enabled: true # Optional: The namespaces where you want Dynatrace Operator to inject # @@ -58,10 +58,27 @@ spec: # operator: In # values: [my-frontend, my-backend, my-database] + # Configuration for Log monitoring. + # + # logMonitoring: {} + + # Optional: Specifies the rules and conditions for matching ingest attributes. + # + # ingestRuleMatchers: + # - attribute: "k8s.namespace.name" + # values: + # - "kube-system" + # - "dynatrace" + # - "default" + # - attribute: "k8s.pod.annotation", + # values: + # - "logs.dynatrace.com/ingest=true" + # - "category=security" + # Configuration for OneAgent # oneAgent: - # Optional: Set a host group for OneAgent. + # Optional: Set a host group for OneAgent # # hostGroup: "" diff --git a/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml b/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml index 58ee638c71..294d5efa6d 100644 --- a/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml +++ b/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml @@ -45,8 +45,8 @@ spec: # Configuration for Metadata Enrichment. # - # metadataEnrichment: - # enabled: true + metadataEnrichment: + enabled: true # Optional: The namespaces where you want Dynatrace Operator to inject # @@ -61,6 +61,7 @@ spec: # Configuration for Log monitoring. # # logMonitoring: {} + # Optional: Specifies the rules and conditions for matching ingest attributes. # # ingestRuleMatchers: @@ -82,6 +83,7 @@ spec: # hostGroup: "" cloudNativeFullStack: + # Optional: The namespaces where you want Dynatrace Operator to inject # # namespaceSelector: diff --git a/assets/samples/dynakube/v1beta4/hostMonitoring.yaml b/assets/samples/dynakube/v1beta4/hostMonitoring.yaml index 9ae817f2ae..934a42626f 100644 --- a/assets/samples/dynakube/v1beta4/hostMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/hostMonitoring.yaml @@ -46,7 +46,7 @@ spec: # Configuration for Metadata Enrichment. # # metadataEnrichment: - # enabled: true + # enabled: true # Optional: The namespaces where you want Dynatrace Operator to inject # @@ -61,6 +61,7 @@ spec: # Configuration for Log monitoring. # # logMonitoring: {} + # Optional: Specifies the rules and conditions for matching ingest attributes. # # ingestRuleMatchers: @@ -77,7 +78,7 @@ spec: # Configuration for OneAgent # oneAgent: - # Optional: Set a host group for OneAgent. + # Optional: Set a host group for OneAgent # # hostGroup: "" diff --git a/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml b/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml index 23a465f65e..268800ae94 100644 --- a/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml +++ b/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml @@ -4,7 +4,7 @@ metadata: name: dynakube namespace: dynatrace # annotations: - # feature.dynatrace.com/k8s-app-enabled: "true" + # feature.dynatrace.com/k8s-app-enabled: "true" spec: # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters @@ -48,7 +48,7 @@ spec: # Configuration for Metadata Enrichment. # # metadataEnrichment: - # enabled: true + # enabled: true # Optional: The namespaces where you want Dynatrace Operator to inject # diff --git a/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml index 83d1b5da2d..d59644888e 100644 --- a/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml +++ b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml @@ -3,8 +3,8 @@ kind: DynaKube metadata: name: dynakube namespace: dynatrace - # annotations: - # feature.dynatrace.com/k8s-app-enabled: "true" + # annotations: + # feature.dynatrace.com/k8s-app-enabled: "true" spec: # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters @@ -48,7 +48,7 @@ spec: # Configuration for Metadata Enrichment. # # metadataEnrichment: - # enabled: true + # enabled: true # Optional: The namespaces where you want Dynatrace Operator to inject # diff --git a/assets/samples/dynakube/v1beta4/logMonitoring.yaml b/assets/samples/dynakube/v1beta4/logMonitoring.yaml index b849b23c78..9b9cfde350 100644 --- a/assets/samples/dynakube/v1beta4/logMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/logMonitoring.yaml @@ -3,8 +3,8 @@ kind: DynaKube metadata: name: dynakube namespace: dynatrace -# annotations: -# feature.dynatrace.com/oneagent-privileged: "true" # Required on Openshift + # annotations: + # feature.dynatrace.com/oneagent-privileged: "true" # Required on Openshift spec: # Link to api reference for further information: https://docs.dynatrace.com/docs/ingest-from/setup-on-k8s/reference/dynakube-parameters @@ -47,8 +47,8 @@ spec: # Configuration for Metadata Enrichment. # - # metadataEnrichment: - # enabled: true + metadataEnrichment: + enabled: true # Optional: The namespaces where you want Dynatrace Operator to inject # @@ -63,6 +63,7 @@ spec: # Configuration for Log monitoring. # logMonitoring: {} + # Optional: Specifies the rules and conditions for matching ingest attributes. # # ingestRuleMatchers: From 594e934717e1f5636565a5d6e92fc977874a40bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Werner=20Putsch=C3=B6gl?= <132911917+wepudt@users.noreply.github.com> Date: Thu, 3 Apr 2025 10:42:43 +0200 Subject: [PATCH 389/426] Revert "Migrate CI to build and distribute images using buildah... (#4684) Co-authored-by: Marcell Sevcsik Co-authored-by: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 22 ++++++++--------- .github/actions/upload-image/action.yaml | 2 +- .github/workflows/ci.yaml | 8 +++---- .github/workflows/release.yaml | 12 +++++----- hack/build/build_image.sh | 10 ++++---- hack/build/ci/upload-docker-image.sh | 30 ++++++++++++++++++++++++ hack/build/ci/upload-podman-image.sh | 22 ----------------- 7 files changed, 55 insertions(+), 51 deletions(-) create mode 100755 hack/build/ci/upload-docker-image.sh delete mode 100755 hack/build/ci/upload-podman-image.sh diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 2808a2f123..58fe781ce2 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -1,4 +1,4 @@ -name: Build Image +name: Build Docker Image description: Builds the operator docker image inputs: platform: @@ -15,6 +15,8 @@ runs: steps: - name: Set up QEMU uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - name: Set up Golang uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: @@ -33,27 +35,23 @@ runs: run: | touch dynatrace-operator-bin-sbom.cdx.json - name: Build target - uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2.13 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 with: + builder: ${{ steps.buildx.outputs.name }} build-args: | GO_LINKER_ARGS=${{ steps.prep.outputs.go_linker_args }} GO_BUILD_TAGS=${{ steps.prep.outputs.go_build_tags }} context: . - containerfiles: | - ./Dockerfile + file: ./Dockerfile platforms: linux/${{ inputs.platform }} - tags: ${{ inputs.image-tag }} - image: operator-${{ inputs.platform }} + push: false + tags: operator-${{ inputs.platform }}:${{ inputs.image-tag }} labels: ${{ inputs.labels }} - oci: true - - name: Export image to file - shell: bash - run: | - set -x - podman save --format oci-archive -o /tmp/operator-${{ inputs.platform }}.tar operator-${{ inputs.platform }}:${{ inputs.image-tag }} + outputs: type=oci,dest=/tmp/operator-${{ inputs.platform }}.tar - name: Upload artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: operator-${{ inputs.platform }} path: /tmp/operator-${{ inputs.platform }}.tar retention-days: 1 + diff --git a/.github/actions/upload-image/action.yaml b/.github/actions/upload-image/action.yaml index 79476ba6e8..fe75fc2283 100644 --- a/.github/actions/upload-image/action.yaml +++ b/.github/actions/upload-image/action.yaml @@ -39,4 +39,4 @@ runs: env: IMAGE: "${{ inputs.registry }}/${{ inputs.repository }}:${{ inputs.version }}" run: | - hack/build/ci/upload-podman-image.sh "${{ inputs.platform }}" "${{ env.IMAGE }}" "${{ inputs.skip-platform-suffix }}" + hack/build/ci/upload-docker-image.sh "${{ inputs.platform }}" "${{ env.IMAGE }}" "${{ inputs.skip-platform-suffix }}" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ca7399c525..868f51aa5f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -217,7 +217,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry - uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} @@ -234,16 +234,14 @@ jobs: manifest: name: Create manifest - needs: [ prepare, push ] + needs: [prepare, push] runs-on: ubuntu-latest - env: - COMBINED: ${{ github.ref_protected }} if: ${{ !github.event.pull_request.head.repo.fork }} steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry - uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c82f66da02..36f6a5b277 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -106,7 +106,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry if: ${{ matrix.registry != 'amazon-ecr' }} - uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ${{ matrix.url }} username: ${{ secrets[matrix.username] }} @@ -139,7 +139,7 @@ jobs: signing-password: ${{ secrets.COSIGN_PASSWORD }} manifest: - name: Create manifests + name: Create Docker manifests environment: Release needs: [prepare, push] runs-on: ubuntu-latest @@ -174,7 +174,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry if: ${{ matrix.registry != 'amazon-ecr' }} - uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ${{ matrix.url }} username: ${{ secrets[matrix.username] }} @@ -235,7 +235,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry if: ${{ matrix.registry != 'amazon-ecr' }} - uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ${{ matrix.url }} username: ${{ secrets[matrix.username] }} @@ -315,7 +315,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Login to Registry - uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ${{ env.SCAN_REGISTRY }} username: ${{ secrets.RHCC_USERNAME }} @@ -378,7 +378,7 @@ jobs: run: | helm registry login -u "${{ secrets.DOCKERHUB_USERNAME }}" -p "${{ secrets.DOCKERHUB_PASSWORD }}" "registry.hub.docker.com" - name: Login Docker to dockerhub - uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: docker.io username: ${{ secrets.DOCKERHUB_USERNAME }} diff --git a/hack/build/build_image.sh b/hack/build/build_image.sh index 76d9203f8b..fdfe2091d4 100755 --- a/hack/build/build_image.sh +++ b/hack/build/build_image.sh @@ -23,9 +23,10 @@ out_image="${image}:${tag}" mkdir -p third_party_licenses touch dynatrace-operator-bin-sbom.cdx.json -if ! command -v podman 2>/dev/null; then - echo "Only podman is supported to build images" - exit 1 +if ! command -v docker 2>/dev/null; then + CONTAINER_CMD=podman +else + CONTAINER_CMD=docker fi OPERATOR_BUILD_PLATFORM="--platform=linux/amd64" @@ -34,8 +35,7 @@ if [ -n "${OPERATOR_DEV_BUILD_PLATFORM}" ]; then OPERATOR_BUILD_PLATFORM="--platform=${OPERATOR_DEV_BUILD_PLATFORM}" fi -podman build "${OPERATOR_BUILD_PLATFORM}" . -f ./Dockerfile -t "${out_image}" \ - --format oci \ +${CONTAINER_CMD} build "${OPERATOR_BUILD_PLATFORM}" . -f ./Dockerfile -t "${out_image}" \ --build-arg "GO_LINKER_ARGS=${go_linker_args}" \ --build-arg "GO_BUILD_TAGS=${go_build_tags}" \ --build-arg "DEBUG_TOOLS=${debug}" \ diff --git a/hack/build/ci/upload-docker-image.sh b/hack/build/ci/upload-docker-image.sh new file mode 100755 index 0000000000..5e20764c50 --- /dev/null +++ b/hack/build/ci/upload-docker-image.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -x + +readonly platform="${1}" +targetImage="${2}" +readonly skip_platform_suffix="${3}" + +readonly imageTarPath="/tmp/operator-${platform}.tar" + +if [ -z "${skip_platform_suffix}" ] +then + targetImage=${targetImage}-${platform} +fi + +docker load -i "${imageTarPath}" + +# $docker load -i /tmp/alpine.tar +# Loaded image: alpine:latest +# +# we're interested in "alpine:latest", that's field=3 +srcImage=$(docker load -i "${imageTarPath}" | cut -d' ' -f3) + +docker load --input "${imageTarPath}" +docker tag "${srcImage}" "${targetImage}" +pushinfo=$(docker push "${targetImage}") + +# filtering by image-tag directly does not work currently see: https://github.com/moby/moby/issues/29901 +digest=$(echo "$pushinfo" | tail -n 1 | cut -d " " -f 3) +echo "digest=${digest}">> "$GITHUB_OUTPUT" diff --git a/hack/build/ci/upload-podman-image.sh b/hack/build/ci/upload-podman-image.sh deleted file mode 100755 index e8b302a1e4..0000000000 --- a/hack/build/ci/upload-podman-image.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -x - -readonly platform="${1}" -target_image="${2}" -readonly skip_platform_suffix="${3}" - -readonly image_tar_path="/tmp/operator-${platform}.tar" - -if [ -z "${skip_platform_suffix}" ] -then - target_image=${target_image}-${platform} -fi - -src_image=$(podman load -i "${image_tar_path}" | cut -d' ' -f3) - -# we need retag it because we load it as localhost -podman tag "${src_image}" "${target_image}" - -# --format is manifest type (oci, v2s2, or v2s1) to use when pushing an image. -podman push --format oci "${target_image}" From d506b3a0fe339797d67a865d3cc69f7d494d96a6 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:04:52 +0200 Subject: [PATCH 390/426] Fully remove podman from CI (#4699) (#4701) --- .github/actions/build-image/action.yaml | 17 ++- .github/actions/create-manifests/action.yaml | 4 +- .github/actions/upload-image/action.yaml | 42 ------- .github/workflows/ci.yaml | 39 +----- .github/workflows/release.yaml | 124 ++++++++----------- hack/build/ci/create-manifest.sh | 25 +--- 6 files changed, 69 insertions(+), 182 deletions(-) delete mode 100644 .github/actions/upload-image/action.yaml diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 58fe781ce2..1cf12add72 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -7,9 +7,11 @@ inputs: labels: description: The labels for the built image required: true - image-tag: + image: description: The tag of the built image required: true + annotation: + description: The annotation added to the built image runs: using: "composite" steps: @@ -43,15 +45,10 @@ runs: GO_BUILD_TAGS=${{ steps.prep.outputs.go_build_tags }} context: . file: ./Dockerfile + provenance: false platforms: linux/${{ inputs.platform }} - push: false - tags: operator-${{ inputs.platform }}:${{ inputs.image-tag }} + push: true + tags: ${{ inputs.image }} labels: ${{ inputs.labels }} - outputs: type=oci,dest=/tmp/operator-${{ inputs.platform }}.tar - - name: Upload artifact - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: operator-${{ inputs.platform }} - path: /tmp/operator-${{ inputs.platform }}.tar - retention-days: 1 + annotations: ${{ inputs.annotation }} diff --git a/.github/actions/create-manifests/action.yaml b/.github/actions/create-manifests/action.yaml index 0f9ea7cebd..5f8cd3e5fd 100644 --- a/.github/actions/create-manifests/action.yaml +++ b/.github/actions/create-manifests/action.yaml @@ -13,8 +13,6 @@ inputs: platforms: description: List of platforms required: true - annotation: - description: Annotation information about an entry in a manifest list outputs: digest: description: The digest of the created manifest @@ -28,4 +26,4 @@ runs: IMAGE: ${{ inputs.registry }}/${{ inputs.repository }} shell: bash run: | - hack/build/ci/create-manifest.sh "${IMAGE}" "${{ inputs.version }}" "${{ inputs.platforms }}" "${{ inputs.annotation }}" + hack/build/ci/create-manifest.sh "${IMAGE}" "${{ inputs.version }}" "${{ inputs.platforms }}" diff --git a/.github/actions/upload-image/action.yaml b/.github/actions/upload-image/action.yaml deleted file mode 100644 index fe75fc2283..0000000000 --- a/.github/actions/upload-image/action.yaml +++ /dev/null @@ -1,42 +0,0 @@ -name: Upload Docker Image -description: Uploads the operator docker image to a registry -inputs: - platform: - description: The platform of the uploaded image - required: true - labels: - description: The labels for the uploaded image - required: true - version: - description: The version the image is for - required: true - registry: - description: The registry where the image is uploaded - required: true - repository: - description: The repository in the registry where the image is uploaded - required: true - skip-platform-suffix: - description: Set if platform suffix should be skipped for image - required: false - default: "" -outputs: - digest: - description: The digest of the pushed image - value: ${{ steps.push-image.outputs.digest }} - -runs: - using: "composite" - steps: - - name: Download artifact - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 - with: - name: operator-${{ inputs.platform }} - path: /tmp - - name: Upload image to Registry - id: push-image - shell: bash - env: - IMAGE: "${{ inputs.registry }}/${{ inputs.repository }}:${{ inputs.version }}" - run: | - hack/build/ci/upload-docker-image.sh "${{ inputs.platform }}" "${{ env.IMAGE }}" "${{ inputs.skip-platform-suffix }}" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 868f51aa5f..39321dfd15 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,8 +25,6 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Helm uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - name: Run Unit tests id: helm-unittest run: | @@ -40,8 +38,6 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Helm uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - name: Run Linting id: helm-linting run: | @@ -107,8 +103,6 @@ jobs: go-version-file: "${{ github.workspace }}/go.mod" - name: Set up Helm uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 - name: Check deepcopy files are up-to-date id: deepcopy @@ -194,25 +188,6 @@ jobs: strategy: matrix: platform: [amd64, arm64, ppc64le, s390x] - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Build image - if: matrix.platform == 'amd64' || matrix.platform == 'arm64' || github.ref_protected - uses: ./.github/actions/build-image - with: - platform: ${{ matrix.platform }} - labels: ${{ needs.prepare.outputs.labels }} - image-tag: ${{ needs.prepare.outputs.version }} - - push: - name: Push images - runs-on: ubuntu-latest - needs: [prepare, build] - strategy: - matrix: - platform: [amd64, arm64, ppc64le, s390x] - if: ${{ !github.event.pull_request.head.repo.fork }} steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -222,19 +197,18 @@ jobs: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_PASSWORD }} - - name: Upload Image + - name: Build image if: matrix.platform == 'amd64' || matrix.platform == 'arm64' || github.ref_protected - uses: ./.github/actions/upload-image + uses: ./.github/actions/build-image with: platform: ${{ matrix.platform }} labels: ${{ needs.prepare.outputs.labels }} - version: ${{ needs.prepare.outputs.version }} - registry: ${{ needs.prepare.outputs.registry }} - repository: ${{ needs.prepare.outputs.repository }} + image: ${{ needs.prepare.outputs.registry }}/${{ needs.prepare.outputs.repository }}:${{ needs.prepare.outputs.version }}-${{ matrix.platform }} + annotation: "version=${{ needs.prepare.outputs.version }}" manifest: name: Create manifest - needs: [prepare, push] + needs: [prepare, build] runs-on: ubuntu-latest if: ${{ !github.event.pull_request.head.repo.fork }} steps: @@ -249,8 +223,7 @@ jobs: - name: Create Manifests uses: ./.github/actions/create-manifests with: + platforms: ${{github.ref_protected && 'amd64, arm64, ppc64le, s390x' || 'amd64, arm64'}} version: ${{ needs.prepare.outputs.version }} registry: ${{ needs.prepare.outputs.registry }} repository: ${{ needs.prepare.outputs.repository }} - platforms: "amd64, arm64" - annotation: "version=${{ needs.prepare.outputs.version }}" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 36f6a5b277..3dfc18b840 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -5,6 +5,8 @@ on: - v[0-9]+.[0-9]+.[0-9]+ - v[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+ # include prerelease tags too +env: + GOOGLE_MARKETPLACE_ANNOTATION: com.googleapis.cloudmarketplace.product.service.name=services/dynatrace-operator-dynatrace-marketplace-prod.cloudpartnerservices.goog jobs: prepare: @@ -20,7 +22,6 @@ jobs: id: prep run: | hack/build/ci/prepare-build-variables.sh - - name: Docker metadata uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 id: meta @@ -49,35 +50,9 @@ jobs: build: name: Build images runs-on: ubuntu-latest - needs: [prepare] - strategy: - matrix: - platform: [amd64, arm64, ppc64le, s390x] - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Setup Golang - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 - with: - go-version-file: "${{ github.workspace }}/go.mod" - - name: Prepare SBOM # Needs setup-go, uses a binary installed via `go install` - id: sbom - run: | - make release/gen-sbom - - name: Build image - uses: ./.github/actions/build-image - with: - platform: ${{ matrix.platform }} - labels: ${{ needs.prepare.outputs.labels }} - image-tag: ${{ needs.prepare.outputs.version }} - - push: - name: Push images - environment: Release - needs: [prepare, build] - runs-on: ubuntu-latest permissions: id-token: write + needs: [prepare] strategy: matrix: platform: [amd64, arm64, ppc64le, s390x] @@ -104,13 +79,21 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Login to Registry - if: ${{ matrix.registry != 'amazon-ecr' }} - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + - name: Setup Golang + uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 with: - registry: ${{ matrix.url }} - username: ${{ secrets[matrix.username] }} - password: ${{ secrets[matrix.password] }} + go-version-file: "${{ github.workspace }}/go.mod" + - name: Prepare SBOM # Needs setup-go, uses a binary installed via `go install` + id: sbom + run: | + make release/gen-sbom + - name: Login to Registry + if: ${{ matrix.registry != 'amazon-ecr' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ${{ matrix.url }} + username: ${{ secrets[matrix.username] }} + password: ${{ secrets[matrix.password] }} - name: Configure aws credentials if: ${{ matrix.registry == 'amazon-ecr' }} uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 @@ -122,26 +105,25 @@ jobs: uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 with: registry-type: public - - name: Push ${{matrix.platform}} to ${{matrix.registry}} - id: push-image - uses: ./.github/actions/upload-image + - name: Build image + id: build-image + uses: ./.github/actions/build-image with: platform: ${{ matrix.platform }} labels: ${{ needs.prepare.outputs.labels }} - version: ${{ needs.prepare.outputs.version }} - registry: ${{ matrix.url }} - repository: ${{ secrets[matrix.repository] }} + image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}-${{ matrix.platform }} + annotation: ${{ env.GOOGLE_MARKETPLACE_ANNOTATION }} - name: Sign image for ${{matrix.registry}} uses: ./.github/actions/sign-image with: - image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}-${{ matrix.platform }}@${{steps.push-image.outputs.digest}} + image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}-${{ matrix.platform }}@${{steps.build-image.outputs.digest}} signing-key: ${{ secrets.COSIGN_PRIVATE_KEY }} signing-password: ${{ secrets.COSIGN_PASSWORD }} manifest: name: Create Docker manifests environment: Release - needs: [prepare, push] + needs: [prepare, build] runs-on: ubuntu-latest permissions: id-token: write @@ -198,7 +180,6 @@ jobs: registry: ${{ matrix.url }} repository: ${{ secrets[matrix.repository] }} platforms: "amd64, arm64, ppc64le, s390x" - annotation: "com.googleapis.cloudmarketplace.product.service.name=services/dynatrace-operator-dynatrace-marketplace-prod.cloudpartnerservices.goog" - name: Sign images for ${{matrix.registry}} uses: ./.github/actions/sign-image with: @@ -209,7 +190,7 @@ jobs: attach-sbom: name: Attach sbom environment: Release - needs: [ prepare, push, manifest ] + needs: [ prepare, build, manifest ] runs-on: ubuntu-latest permissions: id-token: write @@ -273,41 +254,36 @@ jobs: environment: Release runs-on: ubuntu-latest needs: [ prepare ] + env: + IMAGE: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version_with_major_minor }} + IMAGE_NO_PREFIX: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version_without_prefix }} steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Login to GCR - uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7 - with: - registry: gcr.io - username: ${{ secrets.GCR_USERNAME }} - password: ${{ secrets.GCR_JSON_KEY }} - - name: Build target - id: build-image - uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2.13 - with: - oci: true - context: ./config/helm/ - containerfiles: | - ./config/helm/Dockerfile - tags: ${{ needs.prepare.outputs.version_with_major_minor }} ${{ needs.prepare.outputs.version_without_prefix }} - image: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }} - extra-args: | - --annotation=com.googleapis.cloudmarketplace.product.service.name=services/dynatrace-operator-dynatrace-marketplace-prod.cloudpartnerservices.goog - - name: Push To gcr - id: push-to-gcr - uses: redhat-actions/push-to-registry@5ed88d269cf581ea9ef6dd6806d01562096bee9c # v2.8 - with: - image: ${{ secrets.GCR_REPOSITORY_DEPLOYER }} - registry: gcr.io - tags: ${{ needs.prepare.outputs.version_with_major_minor }} ${{ needs.prepare.outputs.version_without_prefix }} - username: ${{ secrets.GCR_USERNAME }} - password: ${{ secrets.GCR_JSON_KEY }} + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Login to Docker Hub + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: gcr.io + username: ${{ secrets.GCR_USERNAME }} + password: ${{ secrets.GCR_JSON_KEY }} + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # 3.10.0 + - name: Build and push + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # 6.15.0 + with: + platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x + provenance: false + file: ./config/helm/Dockerfile + push: true + tags: ${{ env.IMAGE }},${{ env.IMAGE_NO_PREFIX }} + annotations: ${{ env.GOOGLE_MARKETPLACE_ANNOTATION }} run-preflight-rhcc: name: Run preflight for rhcc environment: Release - needs: [ prepare, push, manifest] + needs: [ prepare, build, manifest] runs-on: ubuntu-latest env: SCAN_REGISTRY: "quay.io" diff --git a/hack/build/ci/create-manifest.sh b/hack/build/ci/create-manifest.sh index a680f9f6c2..dfb2422fa8 100755 --- a/hack/build/ci/create-manifest.sh +++ b/hack/build/ci/create-manifest.sh @@ -2,20 +2,16 @@ if [ -z "$3" ] then - echo "Usage: $0 " + echo "Usage: $0 " exit 1 fi image_name=$1 image_tag=$2 raw_platforms=$3 -annotation=$4 image="${image_name}:${image_tag}" -echo "This script is based on podman version 4.9.3" -echo "current version of podman is $(podman --version)" - platforms=($(echo "${raw_platforms}" | tr "," "\n")) echo "Creating manifest for ${platforms[*]}" @@ -24,23 +20,12 @@ images=() for platfrom in "${platforms[@]}" do - podman pull "${image}-${platfrom}" + docker pull "${image}-${platfrom}" images+=("${image}-${platfrom}") done -podman manifest create "${image}" - -if [ -z "${annotation}" ] -then - podman manifest add "${image}" "${images[@]}" -else - podman manifest add --annotation "${annotation}" "${image}" "${images[@]}" -fi - -podman manifest inspect "${image}" - -podman manifest push --format oci --digestfile=digestfile.sha256 "${image}" - -sha256=$(cat digestfile.sha256) +docker manifest create "${image}" "${images[@]}" +docker manifest inspect "${image}" +sha256=$(docker manifest push "${image}") echo "digest=${sha256}">> $GITHUB_OUTPUT From 413c558306c49c9c562ff4c7c2f8a573961f7353 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Thu, 3 Apr 2025 16:01:40 +0200 Subject: [PATCH 391/426] Fix formatting. (#4706) --- .github/workflows/release.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3dfc18b840..a852935251 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -87,13 +87,13 @@ jobs: id: sbom run: | make release/gen-sbom - - name: Login to Registry - if: ${{ matrix.registry != 'amazon-ecr' }} - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 - with: - registry: ${{ matrix.url }} - username: ${{ secrets[matrix.username] }} - password: ${{ secrets[matrix.password] }} + - name: Login to Registry + if: ${{ matrix.registry != 'amazon-ecr' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ${{ matrix.url }} + username: ${{ secrets[matrix.username] }} + password: ${{ secrets[matrix.password] }} - name: Configure aws credentials if: ${{ matrix.registry == 'amazon-ecr' }} uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 From c65c949d3529dc781132ef6bebadc9d3fad030fb Mon Sep 17 00:00:00 2001 From: Stefan Hauth Date: Thu, 3 Apr 2025 16:13:37 +0200 Subject: [PATCH 392/426] Set environment on build step. --- .github/workflows/release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a852935251..9e5ea3955e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -49,6 +49,7 @@ jobs: build: name: Build images + environment: Release runs-on: ubuntu-latest permissions: id-token: write From 819db074299f88a0ca2b1bad6c7cb715f5e8bc59 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 3 Apr 2025 16:39:14 +0200 Subject: [PATCH 393/426] Expose the output of the docker build (#4708) --- .github/actions/build-image/action.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 1cf12add72..01000c215f 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -12,6 +12,10 @@ inputs: required: true annotation: description: The annotation added to the built image +outputs: + digest: + description: "The digest of the built image" + value: ${{ steps.build-target.outputs.digest }} runs: using: "composite" steps: @@ -37,6 +41,7 @@ runs: run: | touch dynatrace-operator-bin-sbom.cdx.json - name: Build target + id: build-target uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 with: builder: ${{ steps.buildx.outputs.name }} From 455dbb20fb5f2698c507daaa5c0922efc577af72 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Thu, 3 Apr 2025 21:07:22 +0200 Subject: [PATCH 394/426] Combine the manifest and sbom step (#4710) Co-authored-by: Marcell Sevcsik --- .github/workflows/release.yaml | 63 +++------------------------------- 1 file changed, 4 insertions(+), 59 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9e5ea3955e..a7033a54d4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -33,16 +33,7 @@ jobs: labels: | ${{ steps.prep.outputs.docker_image_labels }} vcs-ref=${{ github.sha }} - - name: Prepare major_minor tag - shell: bash - id: prepare-major-minor-tag - run: | - set -x - tag="${{ join(fromJSON(steps.meta.outputs.json).tags[0]) }}" - version_with_major_minor=${tag##*:} - echo "version_with_major_minor=$version_with_major_minor" >> $GITHUB_OUTPUT outputs: - version_with_major_minor: ${{ steps.prepare-major-minor-tag.outputs.version_with_major_minor }} labels: ${{ steps.meta.outputs.labels }} version: ${{ steps.prep.outputs.docker_image_tag }} version_without_prefix: ${{ steps.prep.outputs.docker_image_tag_without_prefix }} @@ -187,57 +178,11 @@ jobs: image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ steps.create-manifests.outputs.digest }} signing-key: ${{ secrets.COSIGN_PRIVATE_KEY }} signing-password: ${{ secrets.COSIGN_PASSWORD }} - - attach-sbom: - name: Attach sbom - environment: Release - needs: [ prepare, build, manifest ] - runs-on: ubuntu-latest - permissions: - id-token: write - strategy: - matrix: - registry: [gcr, dockerhub, amazon-ecr] - include: - - registry: gcr - url: gcr.io - repository: GCR_REPOSITORY - username: GCR_USERNAME - password: GCR_JSON_KEY - - registry: dockerhub - url: docker.io - repository: DOCKERHUB_REPOSITORY - username: DOCKERHUB_USERNAME - password: DOCKERHUB_PASSWORD - - registry: amazon-ecr - url: public.ecr.aws - repository: ECR_REPOSITORY - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Login to Registry - if: ${{ matrix.registry != 'amazon-ecr' }} - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 - with: - registry: ${{ matrix.url }} - username: ${{ secrets[matrix.username] }} - password: ${{ secrets[matrix.password] }} - - name: Configure aws credentials - if: ${{ matrix.registry == 'amazon-ecr' }} - uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 - with: - role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} - aws-region: us-east-1 - - name: Login to Amazon ECR - if: ${{ matrix.registry == 'amazon-ecr' }} - uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 - with: - registry-type: public - name: Create sbom for ${{matrix.registry}} id: sbom uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0 with: - image-ref: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ needs.manifest.outputs.digest }} + image-ref: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ steps.create-manifests.outputs.digest }} format: 'cyclonedx' output: 'result.json' skip-dirs: '/usr/share/dynatrace-operator/third_party_licenses' @@ -245,7 +190,7 @@ jobs: - name: Upload sbom to ${{matrix.registry}} uses: ./.github/actions/upload-sbom with: - image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ needs.manifest.outputs.digest }} + image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ steps.create-manifests.outputs.digest }} sbom: 'result.json' signing-key: ${{ secrets.COSIGN_PRIVATE_KEY }} signing-password: ${{ secrets.COSIGN_PASSWORD }} @@ -256,7 +201,7 @@ jobs: runs-on: ubuntu-latest needs: [ prepare ] env: - IMAGE: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version_with_major_minor }} + IMAGE: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version_without_prefix }} IMAGE_NO_PREFIX: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version_without_prefix }} steps: - name: Checkout @@ -309,7 +254,7 @@ jobs: release: name: Create release - needs: [prepare, build, attach-sbom, manifest, run-preflight-rhcc] + needs: [prepare, build, manifest, run-preflight-rhcc] environment: Release permissions: contents: write From e61c719ccb2ac3839793312c0d560f8016a4bd2c Mon Sep 17 00:00:00 2001 From: Stefan Hauth Date: Thu, 3 Apr 2025 22:05:03 +0200 Subject: [PATCH 395/426] Strip complete descriptions from CRD for rc.0 to avoid size limitation. --- hack/make/manifests/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/manifests/config.mk b/hack/make/manifests/config.mk index c45721f4bd..5c6f636a7c 100644 --- a/hack/make/manifests/config.mk +++ b/hack/make/manifests/config.mk @@ -1,4 +1,4 @@ -CRD_OPTIONS ?= "crd:crdVersions=v1,maxDescLen=350,ignoreUnexportedFields=true" +CRD_OPTIONS ?= "crd:crdVersions=v1,maxDescLen=0,ignoreUnexportedFields=true" OLM ?= false From 0522ec79efb29ac844b71d744a8dccfa98227541 Mon Sep 17 00:00:00 2001 From: Stefan Hauth Date: Fri, 4 Apr 2025 11:17:25 +0200 Subject: [PATCH 396/426] Adopt registry order. --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a7033a54d4..52864c414c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -48,7 +48,7 @@ jobs: strategy: matrix: platform: [amd64, arm64, ppc64le, s390x] - registry: [gcr, dockerhub, amazon-ecr, rhcc] + registry: [gcr, dockerhub, rhcc, amazon-ecr] include: - registry: gcr url: gcr.io @@ -123,7 +123,7 @@ jobs: digest: ${{ steps.create-manifests.outputs.digest }} strategy: matrix: - registry: [gcr, dockerhub, amazon-ecr, rhcc] + registry: [gcr, dockerhub, rhcc, amazon-ecr] include: - registry: gcr url: gcr.io From 6891c4bedbb518f2dd1722578b7b57064ea180f5 Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Fri, 4 Apr 2025 13:44:50 +0200 Subject: [PATCH 397/426] Store manifest digests separately per platform in GitHub actions (#4711) --- .github/workflows/release.yaml | 20 +- config/crd/bases/dynatrace.com_dynakubes.yaml | 5002 --------------- .../crd/bases/dynatrace.com_edgeconnects.yaml | 510 -- .../Common/crd/dynatrace-operator-crd.yaml | 5512 ----------------- doc/api/dynakube-api-ref.md | 296 +- doc/api/edgeconnect-api-ref.md | 52 +- 6 files changed, 189 insertions(+), 11203 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 52864c414c..af7aed49d0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -120,7 +120,10 @@ jobs: permissions: id-token: write outputs: - digest: ${{ steps.create-manifests.outputs.digest }} + digest-rhcc: ${{ steps.store-digest.outputs.digest-rhcc }} + digest-gcr: ${{ steps.store-digest.outputs.digest-gcr }} + digest-dockerhub: ${{ steps.store-digest.outputs.digest-dockerhub }} + digest-amazon-ecr: ${{ steps.store-digest.outputs.digest-amazon-ecr }} strategy: matrix: registry: [gcr, dockerhub, rhcc, amazon-ecr] @@ -172,6 +175,13 @@ jobs: registry: ${{ matrix.url }} repository: ${{ secrets[matrix.repository] }} platforms: "amd64, arm64, ppc64le, s390x" + - name: Store digest + id: store-digest + shell: bash + run: | + registry="${{ matrix.registry }}" + digest="${{ steps.create-manifests.outputs.digest }}" + echo "digest-${registry}=${digest}" >> "$GITHUB_OUTPUT" - name: Sign images for ${{matrix.registry}} uses: ./.github/actions/sign-image with: @@ -282,10 +292,10 @@ jobs: run: | make manifests/crd/release CHART_VERSION="${VERSION_WITHOUT_PREFIX}" - make manifests/kubernetes/olm IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest}}" - make manifests/kubernetes IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest}}" - make manifests/openshift/olm IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest}}" - make manifests/openshift IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest}}" + make manifests/kubernetes/olm IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-ecr}}" + make manifests/kubernetes IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-ecr}}" + make manifests/openshift/olm IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-rhcc}}" + make manifests/openshift IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-rhcc}}" cp config/deploy/kubernetes/kubernetes.yaml config/deploy/kubernetes/gke-autopilot.yaml - name: Build helm packages uses: ./.github/actions/build-helm diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index 70884149e1..032b5ab913 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -32,165 +32,92 @@ spec: name: v1beta1 schema: openAPIV3Schema: - description: DynaKube is the Schema for the DynaKube API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: - description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the ActiveGate pods type: object capabilities: - description: Activegate capabilities enabled (routing, kubernetes-monitoring, - metrics-ingest, dynatrace-api) items: type: string type: array customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Custom properties value. nullable: true type: string valueFrom: - description: Custom properties secret. nullable: true type: string type: object dnsPolicy: - description: Sets DNS Policy for the ActiveGate pods type: string env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -202,58 +129,30 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the StatefulSet. type: string replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -269,9 +168,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -280,94 +176,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: - description: |- - The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. - server.p12: certificate+key pair in pkcs12 format - password: passphrase to read server.p12 type: string tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -381,69 +222,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -453,148 +252,80 @@ spec: type: array type: object apiUrl: - description: |- - Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. type: string customPullSecret: - description: |- - Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. - To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret - (https://www.dynatrace. type: string enableIstio: - description: |- - When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding - VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. - Disabled by default. type: boolean kubernetesMonitoring: - description: Configuration for Kubernetes Monitoring properties: customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Custom properties value. nullable: true type: string valueFrom: - description: Custom properties secret. nullable: true type: string type: object enabled: - description: Enables Capability type: boolean env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -606,53 +337,28 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -668,9 +374,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -679,88 +382,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -774,69 +426,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -846,33 +456,15 @@ spec: type: array type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector applies - to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -886,59 +478,26 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic networkZone: - description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: - description: |- - General configuration about OneAgent instances. - You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). properties: applicationMonitoring: - description: |- - dynatrace-webhook injects into application pods based on labeled namespaces. - Has an optional CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: codeModulesImage: - description: The OneAgent image that is used to inject into - Pods. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -954,9 +513,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -965,158 +521,85 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object useCSIDriver: - description: Set if you want to use the CSIDriver. Don't enable - it if you do not have access to Kubernetes nodes or if you - lack privileges. type: boolean version: - description: The OneAgent version to be used. type: string type: object classicFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - Injection is performed via the same OneAgent DaemonSet. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -1128,49 +611,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -1186,9 +643,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -1197,203 +651,103 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used. type: string type: object cloudNativeFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - dynatrace-webhook injects into application pods based on labeled namespaces. - Has a CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean codeModulesImage: - description: The OneAgent image that is used to inject into - Pods. type: string dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -1405,37 +759,15 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -1451,9 +783,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -1462,53 +791,24 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -1524,9 +824,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -1535,201 +832,103 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used. type: string type: object hostGroup: - description: Sets a host group for OneAgent. type: string hostMonitoring: - description: |- - Has a single OneAgent per node via DaemonSet. - Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -1741,49 +940,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -1799,9 +972,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -1810,203 +980,108 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used. type: string type: object type: object proxy: - description: |- - Set custom proxy settings either directly or from a secret with the field proxy. - Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. properties: value: - description: Proxy URL. It has preference over ValueFrom. nullable: true type: string valueFrom: - description: Secret containing proxy URL. nullable: true type: string type: object routing: - description: Configuration for Routing properties: customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Custom properties value. nullable: true type: string valueFrom: - description: Custom properties secret. nullable: true type: string type: object enabled: - description: Enables Capability type: boolean env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -2018,53 +1093,28 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -2080,9 +1130,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -2091,88 +1138,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -2186,69 +1182,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -2258,139 +1212,85 @@ spec: type: array type: object skipCertCheck: - description: |- - Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. - Set to true if you want to skip certification validation checks. type: boolean tokens: - description: Name of the secret holding the tokens used for connecting - to Dynatrace. type: string trustedCAs: - description: |- - Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. - Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. type: string required: - apiUrl type: object status: - description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: - description: Observed state of ActiveGate properties: connectionInfoStatus: - description: Information about Active Gate's connections properties: endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string serviceIPs: - description: The ClusterIPs set by Kubernetes on the ActiveGate - Service created by the Operator items: type: string type: array source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object codeModules: - description: Observed state of Code Modules properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -2403,104 +1303,72 @@ spec: type: object type: array dynatraceApi: - description: Observed state of Dynatrace API properties: lastTokenScopeRequest: - description: Time of the last token request format: date-time type: string type: object kubeSystemUUID: - description: KubeSystemUUID contains the UUID of the current Kubernetes - cluster type: string lastTokenProbeTimestamp: - description: LastTokenProbeTimestamp tracks when the last request - for the API token validity was sent format: date-time type: string oneAgent: - description: Observed state of OneAgent properties: connectionInfoStatus: - description: Information about OneAgent's connections properties: communicationHosts: - description: List of communication hosts items: properties: host: - description: Host domain type: string port: - description: Connection port format: int32 type: integer protocol: - description: Connection protocol type: string type: object type: array endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object healthcheck: - description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: - description: Image ID type: string instances: additionalProperties: properties: ipAddress: - description: IP address of the pod type: string podName: - description: Name of the OneAgent pod type: string type: object - description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: - description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: UpdatedTimestamp indicates when the instance was last - updated format: date-time type: string type: object @@ -2522,169 +1390,92 @@ spec: name: v1beta2 schema: openAPIV3Schema: - description: DynaKube is the Schema for the DynaKube API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: - description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the ActiveGate pods type: object capabilities: - description: "Defines the ActiveGate pod capabilities\nPossible - values:\n\t- `routing` enables OneAgent routing.\n\t- `kubernetes-monitoring` - enables Kubernetes API monitoring.\n\t- `metrics-ingest` opens - the metrics ingest endpoint on the DynaKube ActiveGate and redirects - all pods to it.\n\t- `dynatrace-api` enables calling the Dynatrace - API via ActiveGate." items: type: string type: array customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called `customProperties` properties: value: - description: Custom properties value. nullable: true type: string valueFrom: - description: Custom properties secret. nullable: true type: string type: object dnsPolicy: - description: Sets DNS Policy for the ActiveGate pods type: string env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -2696,62 +1487,31 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: Use a custom ActiveGate image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Your defined labels for ActiveGate pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes ActiveGate will be deployed. type: object priorityClassName: - description: |- - Assign a priority class to the ActiveGate pods. By default, no class is set. - For details, see Pod Priority and Preemption. (https://dt-url.net/n8437bl) type: string replicas: default: 1 - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: |- - Resource settings for ActiveGate container. - Consumption of the ActiveGate heavily depends on the workload to monitor. Adjust values accordingly. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -2767,9 +1527,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -2778,94 +1535,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: - description: |- - The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. - `server.p12`: certificate+key pair in pkcs12 format - `password`: passphrase to read server.p12 type: string tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints to the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -2879,69 +1581,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -2951,61 +1611,29 @@ spec: type: array type: object apiUrl: - description: |- - Dynatrace `apiUrl`, including the `/api` path at the end. - - For SaaS, set `YOUR_ENVIRONMENT_ID` to your environment ID. - - For Managed, change the `apiUrl` address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. type: string customPullSecret: - description: |- - Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. - To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret - (https://www.dynatrace. type: string dynatraceApiRequestThreshold: default: 15 - description: Minimum minutes between Dynatrace API requests. type: integer enableIstio: - description: |- - When enabled, and if Istio is installed in the Kubernetes environment, Dynatrace Operator will create the corresponding VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. - Disabled by default. type: boolean metadataEnrichment: - description: Configuration for Metadata Enrichment. properties: enabled: default: false - description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: - description: The namespaces where you want Dynatrace Operator - to inject enrichment. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -3019,10 +1647,6 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic @@ -3030,51 +1654,22 @@ spec: - enabled type: object networkZone: - description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: - description: |- - General configuration about OneAgent instances. - You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). properties: applicationMonitoring: - description: |- - dynatrace-webhook injects into application pods based on labeled namespaces. - Has an optional CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: codeModulesImage: - description: The OneAgent image that is used to inject into - Pods. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -3090,9 +1685,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -3101,41 +1693,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -3149,160 +1718,88 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic useCSIDriver: default: false - description: Set if you want to use the CSIDriver. Don't enable - it if you do not have access to Kubernetes nodes or if you - lack privileges. type: boolean version: - description: The OneAgent version to be used. type: string type: object classicFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - Injection is performed via the same OneAgent DaemonSet. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -3314,50 +1811,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - - `resource.requests` shows the values needed to run - - `resource.limits` shows the maximum limits for the pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -3373,9 +1843,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -3384,210 +1851,106 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used for OneAgents - running in the dedicated pod. This setting doesn't affect - the OneAgent version used for application monitoring. type: string type: object cloudNativeFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - dynatrace-webhook injects into application pods based on labeled namespaces. - Has a CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean codeModulesImage: - description: The OneAgent image that is used to inject into - Pods. type: string dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -3599,37 +1962,15 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -3645,9 +1986,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -3656,47 +1994,22 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -3710,48 +2023,21 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - - `resource.requests` shows the values needed to run - - `resource.limits` shows the maximum limits for the pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -3767,9 +2053,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -3778,211 +2061,106 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used for OneAgents - running in the dedicated pod. This setting doesn't affect - the OneAgent version used for application monitoring. type: string type: object hostGroup: - description: |- - Specify the name of the group to which you want to assign the host. - This method is preferred over the now obsolete `--set-host-group` argument. - If both settings are used, this field takes precedence over the `--set-host-group` argument. type: string hostMonitoring: - description: |- - Has a single OneAgent per node via DaemonSet. - Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -3994,50 +2172,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - - `resource.requests` shows the values needed to run - - `resource.limits` shows the maximum limits for the pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -4053,9 +2204,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -4064,218 +2212,121 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used for OneAgents - running in the dedicated pod. This setting doesn't affect - the OneAgent version used for application monitoring. type: string type: object type: object proxy: - description: |- - Set custom proxy settings either directly or from a secret with the field `proxy`. - Applies to Dynatrace Operator, ActiveGate, and OneAgents. properties: value: - description: Proxy URL. It has preference over ValueFrom. nullable: true type: string valueFrom: - description: Secret containing proxy URL. nullable: true type: string type: object skipCertCheck: - description: |- - Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. - Set to `true` if you want to skip certification validation checks. type: boolean tokens: - description: Name of the secret holding the tokens used for connecting - to Dynatrace. type: string trustedCAs: - description: |- - Adds custom RootCAs from a configmap. - The key to the data must be `certs`. - This applies to both the Dynatrace Operator and the OneAgent. Doesn't apply to ActiveGate. type: string required: - apiUrl type: object status: - description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: - description: Observed state of ActiveGate properties: connectionInfoStatus: - description: Information about Active Gate's connections properties: endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string serviceIPs: - description: The ClusterIPs set by Kubernetes on the ActiveGate - Service created by the Operator items: type: string type: array source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object codeModules: - description: Observed state of Code Modules properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -4288,28 +2339,18 @@ spec: type: object type: array dynatraceApi: - description: Observed state of Dynatrace API properties: lastTokenScopeRequest: - description: Time of the last token request format: date-time type: string type: object kubeSystemUUID: - description: KubeSystemUUID contains the UUID of the current Kubernetes - cluster type: string kubernetesClusterMEID: - description: KubernetesClusterMEID contains the ID of the monitored - entity that points to the Kubernetes cluster type: string kubernetesClusterName: - description: KubernetesClusterName contains the display name (also - know as label) of the monitored entity that points to the Kubernetes - cluster type: string metadataEnrichment: - description: Observed state of Metadata-Enrichment properties: rules: items: @@ -4326,87 +2367,61 @@ spec: type: array type: object oneAgent: - description: Observed state of OneAgent properties: connectionInfoStatus: - description: Information about OneAgent's connections properties: communicationHosts: - description: List of communication hosts items: properties: host: - description: Host domain type: string port: - description: Connection port format: int32 type: integer protocol: - description: Connection protocol type: string type: object type: array endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object healthcheck: - description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: - description: Image ID type: string instances: additionalProperties: properties: ipAddress: - description: IP address of the pod type: string podName: - description: Name of the OneAgent pod type: string type: object - description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: - description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: UpdatedTimestamp indicates when the instance was last - updated format: date-time type: string type: object @@ -4428,165 +2443,92 @@ spec: name: v1beta3 schema: openAPIV3Schema: - description: DynaKube is the Schema for the DynaKube API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: - description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the ActiveGate pods type: object capabilities: - description: Activegate capabilities enabled (routing, kubernetes-monitoring, - metrics-ingest, dynatrace-api) items: type: string type: array customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Raw value for given property. nullable: true type: string valueFrom: - description: Name of the secret to get the property from. nullable: true type: string type: object dnsPolicy: - description: Sets DNS Policy for the ActiveGate pods type: string env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -4598,58 +2540,30 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the StatefulSet. type: string replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -4665,9 +2579,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -4676,94 +2587,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: - description: |- - The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. - server.p12: certificate+key pair in pkcs12 format - password: passphrase to read server.p12 type: string tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -4777,69 +2633,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -4849,36 +2663,19 @@ spec: type: array type: object apiUrl: - description: |- - Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. maxLength: 128 type: string customPullSecret: - description: |- - Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. - To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret - (https://www.dynatrace. type: string dynatraceApiRequestThreshold: - description: Configuration for thresholding Dynatrace API requests. type: integer enableIstio: - description: |- - When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding - VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. - Disabled by default. type: boolean extensions: - description: |- - When an (empty) ExtensionsSpec is provided, the extensions related components (extensions controller and extensions collector) - are deployed by the operator. type: object kspm: - description: General configuration about the KSPM feature. type: object logMonitoring: - description: General configuration about the LogMonitoring feature. properties: ingestRuleMatchers: items: @@ -4893,38 +2690,19 @@ spec: type: array type: object metadataEnrichment: - description: Configuration for Metadata Enrichment. properties: enabled: - description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: - description: The namespaces where you want Dynatrace Operator - to inject enrichment. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -4938,60 +2716,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic type: object networkZone: - description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: - description: |- - General configuration about OneAgent instances. - You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). properties: applicationMonitoring: - description: |- - dynatrace-webhook injects into application pods based on labeled namespaces. - Has an optional CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: codeModulesImage: - description: Use a custom OneAgent CodeModule image to download - binaries. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5007,9 +2752,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5018,41 +2760,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -5066,154 +2785,84 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic version: - description: Use a specific OneAgent CodeModule version. Defaults - to the latest version from the Dynatrace cluster. type: string type: object classicFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - Injection is performed via the same OneAgent DaemonSet. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -5225,49 +2874,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5283,9 +2906,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5294,208 +2914,105 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object cloudNativeFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - dynatrace-webhook injects into application pods based on labeled namespaces. - Has a CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean codeModulesImage: - description: Use a custom OneAgent CodeModule image to download - binaries. type: string dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -5507,37 +3024,15 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5553,9 +3048,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5564,47 +3056,22 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -5618,47 +3085,21 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5674,9 +3115,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5685,206 +3123,105 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object hostGroup: - description: Sets a host group for OneAgent. type: string hostMonitoring: - description: |- - Has a single OneAgent per node via DaemonSet. - Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -5896,49 +3233,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5954,9 +3265,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5965,86 +3273,42 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object type: object proxy: - description: |- - Set custom proxy settings either directly or from a secret with the field proxy. - Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. properties: value: - description: Raw value for given property. nullable: true type: string valueFrom: - description: Name of the secret to get the property from. nullable: true type: string type: object skipCertCheck: - description: |- - Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. - Set to true if you want to skip certification validation checks. type: boolean templates: properties: @@ -6053,64 +3317,37 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations to the ExtensionExecutionController - pods type: object customConfig: - description: Defines name of ConfigMap containing custom configuration - file type: string customExtensionCertificates: - description: Defines name of Secret containing certificates - for custom extensions signature validation type: string imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the ExtensionExecutionController - pods type: object persistentVolumeClaim: - description: Defines storage device properties: accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 items: type: string type: array x-kubernetes-list-type: atomic dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string required: - kind @@ -6118,39 +3355,20 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. type: string required: - kind - name type: object resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes. properties: limits: additionalProperties: @@ -6159,9 +3377,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -6170,40 +3385,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object selector: - description: selector is a label query over volumes to - consider for binding. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -6217,62 +3410,26 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. type: string volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. type: string volumeName: - description: volumeName is the binding reference to the - PersistentVolume backing this claim. type: string type: object resources: - description: Define resources' requests and limits for single - ExtensionExecutionController pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -6288,9 +3445,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -6299,91 +3453,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: type: string tolerations: - description: Set tolerations for the ExtensionExecutionController - pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ExtensionExecutionController - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the - selector applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -6397,69 +3499,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -6468,7 +3528,6 @@ spec: type: object type: array useEphemeralVolume: - description: Selects EmptyDir volume to be storage device type: boolean type: object kspmNodeConfigurationCollector: @@ -6476,122 +3535,67 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations for the NodeConfigurationCollector - pods type: object args: - description: Set additional arguments to the NodeConfigurationCollector - pods items: type: string type: array env: - description: Set additional environment variables for the - NodeConfigurationCollector pods items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -6603,65 +3607,32 @@ spec: type: object type: array imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the NodeConfigurationCollector - pods type: object nodeAffinity: - description: Define the nodeAffinity for the DaemonSet of - the NodeConfigurationCollector properties: preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: preference: - description: A node selector term, associated with - the corresponding weight. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -6673,29 +3644,13 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: - description: A list of node selector requirements - by node's fields. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -6709,8 +3664,6 @@ spec: type: object x-kubernetes-map-type: atomic weight: - description: Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: @@ -6720,46 +3673,18 @@ spec: type: array x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. properties: nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -6771,29 +3696,13 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: - description: A list of node selector requirements - by node's fields. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -6816,41 +3725,17 @@ spec: nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes NodeConfigurationCollector pods will be deployed. type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the DaemonSet. type: string resources: - description: Define resources' requests and limits for single - NodeConfigurationCollector pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -6866,9 +3751,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -6877,163 +3759,81 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: - description: Set tolerations for the NodeConfigurationCollector - pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array updateStrategy: - description: Define the NodeConfigurationCollector daemonSet - updateStrategy properties: rollingUpdate: - description: Rolling update config params. Present only - if type = "RollingUpdate". properties: maxSurge: anyOf: - type: integer - type: string - description: |- - The maximum number of nodes with an existing available DaemonSet pod that - can have an updated DaemonSet pod during during an update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up to a minimum of 1. x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string - description: |- - The maximum number of DaemonSet pods that can be unavailable during the - update. Value can be an absolute number (ex: 5) or a percentage of total - number of DaemonSet pods at the start of the update (ex: 10%). Absolute - number is calculated from percentage by rounding up. - This cannot be 0 if MaxSurge is 0 - Default value is 1. x-kubernetes-int-or-string: true type: object type: - description: Type of daemon set update. Can be "RollingUpdate" - or "OnDelete". Default is RollingUpdate. type: string type: object type: object logMonitoring: - description: Low-level configuration options for the LogMonitoring - feature. properties: annotations: additionalProperties: type: string - description: Add custom annotations to the LogMonitoring pods type: object args: - description: Set additional arguments to the LogMonitoring - main container items: type: string type: array dnsPolicy: - description: Sets DNS Policy for the LogMonitoring pods type: string imageRef: - description: Overrides the default image for the LogMonitoring - pods properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Add custom labels to the LogMonitoring pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes - for the LogMonitoring pods type: object priorityClassName: - description: Assign a priority class to the LogMonitoring - pods. By default, no class is set type: string resources: - description: Define resources' requests and limits for all - the LogMonitoring pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -7049,9 +3849,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -7060,54 +3857,23 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode for the LogMonitoring - pods type: string tolerations: - description: Set tolerations for the LogMonitoring pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array @@ -7117,57 +3883,30 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations to the OtelCollector - pods type: object imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the OtelCollector - pods type: object replicas: - description: Number of replicas for your OtelCollector format: int32 type: integer resources: - description: Define resources' requests and limits for single - OtelCollector pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -7183,9 +3922,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -7194,90 +3930,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: type: string tolerations: - description: Set tolerations for the OtelCollector pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the OtelCollector - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the - selector applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -7291,69 +3976,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -7364,134 +4007,83 @@ spec: type: object type: object tokens: - description: Name of the secret holding the tokens used for connecting - to Dynatrace. type: string trustedCAs: - description: |- - Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. - Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. type: string required: - apiUrl type: object status: - description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: - description: Observed state of ActiveGate properties: connectionInfoStatus: - description: Information about Active Gate's connections properties: endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string serviceIPs: - description: The ClusterIPs set by Kubernetes on the ActiveGate - Service created by the Operator items: type: string type: array source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object codeModules: - description: Observed state of Code Modules properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -7504,37 +4096,23 @@ spec: type: object type: array dynatraceApi: - description: Observed state of Dynatrace API properties: lastTokenScopeRequest: - description: Time of the last token request format: date-time type: string type: object kspm: - description: Observed state of Kspm properties: tokenSecretHash: - description: |- - TokenSecretHash contains the hash of the token that is passed to both the ActiveGate and Node-Configuration-Collector. - Meant to keep the two in sync. type: string type: object kubeSystemUUID: - description: KubeSystemUUID contains the UUID of the current Kubernetes - cluster type: string kubernetesClusterMEID: - description: KubernetesClusterMEID contains the ID of the monitored - entity that points to the Kubernetes cluster type: string kubernetesClusterName: - description: KubernetesClusterName contains the display name (also - know as label) of the monitored entity that points to the Kubernetes - cluster type: string metadataEnrichment: - description: Observed state of Metadata-Enrichment properties: rules: items: @@ -7551,87 +4129,61 @@ spec: type: array type: object oneAgent: - description: Observed state of OneAgent properties: connectionInfoStatus: - description: Information about OneAgent's connections properties: communicationHosts: - description: List of communication hosts items: properties: host: - description: Host domain type: string port: - description: Connection port format: int32 type: integer protocol: - description: Connection protocol type: string type: object type: array endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object healthcheck: - description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: - description: Image ID type: string instances: additionalProperties: properties: ipAddress: - description: IP address of the pod type: string podName: - description: Name of the OneAgent pod type: string type: object - description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: - description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: UpdatedTimestamp indicates when the instance was last - updated format: date-time type: string type: object @@ -7653,165 +4205,92 @@ spec: name: v1beta4 schema: openAPIV3Schema: - description: DynaKube is the Schema for the DynaKube API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: - description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the ActiveGate pods type: object capabilities: - description: Activegate capabilities enabled (routing, kubernetes-monitoring, - metrics-ingest, dynatrace-api) items: type: string type: array customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Raw value for given property. nullable: true type: string valueFrom: - description: Name of the secret to get the property from. nullable: true type: string type: object dnsPolicy: - description: Sets DNS Policy for the ActiveGate pods type: string env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -7823,52 +4302,31 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object persistentVolumeClaim: - description: Defines storage device properties: accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 items: type: string type: array x-kubernetes-list-type: atomic dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string required: - kind @@ -7876,39 +4334,20 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. type: string required: - kind - name type: object resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes. properties: limits: additionalProperties: @@ -7917,9 +4356,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -7928,40 +4364,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object selector: - description: selector is a label query over volumes to consider - for binding. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -7975,71 +4389,31 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. type: string volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. type: string volumeName: - description: volumeName is the binding reference to the PersistentVolume - backing this claim. type: string type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the StatefulSet. type: string replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -8055,9 +4429,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -8066,99 +4437,42 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object terminationGracePeriodSeconds: - description: Configures the terminationGracePeriodSeconds parameter - of the ActiveGate pod. Kubernetes defaults and rules apply. format: int64 type: integer tlsSecretName: - description: |- - The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. - server.p12: certificate+key pair in pkcs12 format - password: passphrase to read server.p12 type: string tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -8172,69 +4486,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -8243,40 +4515,22 @@ spec: type: object type: array useEphemeralVolume: - description: UseEphemeralVolume type: boolean type: object apiUrl: - description: |- - Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. maxLength: 128 type: string customPullSecret: - description: |- - Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. - To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret - (https://www.dynatrace. type: string dynatraceApiRequestThreshold: - description: Configuration for thresholding Dynatrace API requests. type: integer enableIstio: - description: |- - When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding - VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. - Disabled by default. type: boolean extensions: - description: |- - When an (empty) ExtensionsSpec is provided, the extensions related components (extensions controller and extensions collector) - are deployed by the operator. type: object kspm: - description: General configuration about the KSPM feature. type: object logMonitoring: - description: General configuration about the LogMonitoring feature. properties: ingestRuleMatchers: items: @@ -8291,38 +4545,19 @@ spec: type: array type: object metadataEnrichment: - description: Configuration for Metadata Enrichment. properties: enabled: - description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: - description: The namespaces where you want Dynatrace Operator - to inject enrichment. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -8336,60 +4571,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic type: object networkZone: - description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: - description: |- - General configuration about OneAgent instances. - You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). properties: applicationMonitoring: - description: |- - dynatrace-webhook injects into application pods based on labeled namespaces. - Has an optional CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: codeModulesImage: - description: Use a custom OneAgent CodeModule image to download - binaries. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -8405,9 +4607,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -8416,41 +4615,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -8464,154 +4640,84 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic version: - description: Use a specific OneAgent CodeModule version. Defaults - to the latest version from the Dynatrace cluster. type: string type: object classicFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - Injection is performed via the same OneAgent DaemonSet. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -8623,49 +4729,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -8681,9 +4761,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -8692,213 +4769,107 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string storageHostPath: - description: StorageHostPath is the writable directory on - the host filesystem where OneAgent configurations will be - stored. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object cloudNativeFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - dynatrace-webhook injects into application pods based on labeled namespaces. - Has a CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean codeModulesImage: - description: Use a custom OneAgent CodeModule image to download - binaries. type: string dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -8910,37 +4881,15 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -8956,9 +4905,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -8967,47 +4913,22 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -9021,47 +4942,21 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -9077,9 +4972,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -9088,211 +4980,107 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string storageHostPath: - description: StorageHostPath is the writable directory on - the host filesystem where OneAgent configurations will be - stored. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object hostGroup: - description: Sets a host group for OneAgent. type: string hostMonitoring: - description: |- - Has a single OneAgent per node via DaemonSet. - Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -9304,49 +5092,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -9362,9 +5124,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -9373,95 +5132,46 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string storageHostPath: - description: StorageHostPath is the writable directory on - the host filesystem where OneAgent configurations will be - stored. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object type: object proxy: - description: |- - Set custom proxy settings either directly or from a secret with the field proxy. - Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. properties: value: - description: Raw value for given property. nullable: true type: string valueFrom: - description: Name of the secret to get the property from. nullable: true type: string type: object skipCertCheck: - description: |- - Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. - Set to true if you want to skip certification validation checks. type: boolean telemetryIngest: - description: When a TelemetryIngestSpec is provided, the OTEL collector - is deployed by the operator. properties: protocols: items: @@ -9479,64 +5189,37 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations to the ExtensionExecutionController - pods type: object customConfig: - description: Defines name of ConfigMap containing custom configuration - file type: string customExtensionCertificates: - description: Defines name of Secret containing certificates - for custom extensions signature validation type: string imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the ExtensionExecutionController - pods type: object persistentVolumeClaim: - description: Defines storage device properties: accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 items: type: string type: array x-kubernetes-list-type: atomic dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string required: - kind @@ -9544,39 +5227,20 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. type: string required: - kind - name type: object resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes. properties: limits: additionalProperties: @@ -9585,9 +5249,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -9596,40 +5257,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object selector: - description: selector is a label query over volumes to - consider for binding. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -9643,62 +5282,26 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. type: string volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. type: string volumeName: - description: volumeName is the binding reference to the - PersistentVolume backing this claim. type: string type: object resources: - description: Define resources' requests and limits for single - ExtensionExecutionController pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -9714,9 +5317,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -9725,91 +5325,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: type: string tolerations: - description: Set tolerations for the ExtensionExecutionController - pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ExtensionExecutionController - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the - selector applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -9823,69 +5371,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -9894,7 +5400,6 @@ spec: type: object type: array useEphemeralVolume: - description: Selects EmptyDir volume to be storage device type: boolean type: object kspmNodeConfigurationCollector: @@ -9902,122 +5407,67 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations for the NodeConfigurationCollector - pods type: object args: - description: Set additional arguments to the NodeConfigurationCollector - pods items: type: string type: array env: - description: Set additional environment variables for the - NodeConfigurationCollector pods items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -10029,65 +5479,32 @@ spec: type: object type: array imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the NodeConfigurationCollector - pods type: object nodeAffinity: - description: Define the nodeAffinity for the DaemonSet of - the NodeConfigurationCollector properties: preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: preference: - description: A node selector term, associated with - the corresponding weight. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -10099,29 +5516,13 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: - description: A list of node selector requirements - by node's fields. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -10135,8 +5536,6 @@ spec: type: object x-kubernetes-map-type: atomic weight: - description: Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: @@ -10146,46 +5545,18 @@ spec: type: array x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. properties: nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -10197,29 +5568,13 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: - description: A list of node selector requirements - by node's fields. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -10242,41 +5597,17 @@ spec: nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes NodeConfigurationCollector pods will be deployed. type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the DaemonSet. type: string resources: - description: Define resources' requests and limits for single - NodeConfigurationCollector pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -10292,9 +5623,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -10303,163 +5631,81 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: - description: Set tolerations for the NodeConfigurationCollector - pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array updateStrategy: - description: Define the NodeConfigurationCollector daemonSet - updateStrategy properties: rollingUpdate: - description: Rolling update config params. Present only - if type = "RollingUpdate". properties: maxSurge: anyOf: - type: integer - type: string - description: |- - The maximum number of nodes with an existing available DaemonSet pod that - can have an updated DaemonSet pod during during an update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up to a minimum of 1. x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string - description: |- - The maximum number of DaemonSet pods that can be unavailable during the - update. Value can be an absolute number (ex: 5) or a percentage of total - number of DaemonSet pods at the start of the update (ex: 10%). Absolute - number is calculated from percentage by rounding up. - This cannot be 0 if MaxSurge is 0 - Default value is 1. x-kubernetes-int-or-string: true type: object type: - description: Type of daemon set update. Can be "RollingUpdate" - or "OnDelete". Default is RollingUpdate. type: string type: object type: object logMonitoring: - description: Low-level configuration options for the LogMonitoring - feature. properties: annotations: additionalProperties: type: string - description: Add custom annotations to the LogMonitoring pods type: object args: - description: Set additional arguments to the LogMonitoring - main container items: type: string type: array dnsPolicy: - description: Sets DNS Policy for the LogMonitoring pods type: string imageRef: - description: Overrides the default image for the LogMonitoring - pods properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Add custom labels to the LogMonitoring pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes - for the LogMonitoring pods type: object priorityClassName: - description: Assign a priority class to the LogMonitoring - pods. By default, no class is set type: string resources: - description: Define resources' requests and limits for all - the LogMonitoring pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -10475,9 +5721,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -10486,54 +5729,23 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode for the LogMonitoring - pods type: string tolerations: - description: Set tolerations for the LogMonitoring pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array @@ -10543,57 +5755,30 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations to the OtelCollector - pods type: object imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the OtelCollector - pods type: object replicas: - description: Number of replicas for your OtelCollector format: int32 type: integer resources: - description: Define resources' requests and limits for single - OtelCollector pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -10609,9 +5794,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -10620,90 +5802,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: type: string tolerations: - description: Set tolerations for the OtelCollector pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the OtelCollector - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the - selector applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -10717,69 +5848,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -10790,134 +5879,83 @@ spec: type: object type: object tokens: - description: Name of the secret holding the tokens used for connecting - to Dynatrace. type: string trustedCAs: - description: |- - Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. - Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. type: string required: - apiUrl type: object status: - description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: - description: Observed state of ActiveGate properties: connectionInfoStatus: - description: Information about Active Gate's connections properties: endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string serviceIPs: - description: The ClusterIPs set by Kubernetes on the ActiveGate - Service created by the Operator items: type: string type: array source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object codeModules: - description: Observed state of Code Modules properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -10930,37 +5968,23 @@ spec: type: object type: array dynatraceApi: - description: Observed state of Dynatrace API properties: lastTokenScopeRequest: - description: Time of the last token request format: date-time type: string type: object kspm: - description: Observed state of Kspm properties: tokenSecretHash: - description: |- - TokenSecretHash contains the hash of the token that is passed to both the ActiveGate and Node-Configuration-Collector. - Meant to keep the two in sync. type: string type: object kubeSystemUUID: - description: KubeSystemUUID contains the UUID of the current Kubernetes - cluster type: string kubernetesClusterMEID: - description: KubernetesClusterMEID contains the ID of the monitored - entity that points to the Kubernetes cluster type: string kubernetesClusterName: - description: KubernetesClusterName contains the display name (also - know as label) of the monitored entity that points to the Kubernetes - cluster type: string metadataEnrichment: - description: Observed state of Metadata-Enrichment properties: rules: items: @@ -10977,87 +6001,61 @@ spec: type: array type: object oneAgent: - description: Observed state of OneAgent properties: connectionInfoStatus: - description: Information about OneAgent's connections properties: communicationHosts: - description: List of communication hosts items: properties: host: - description: Host domain type: string port: - description: Connection port format: int32 type: integer protocol: - description: Connection protocol type: string type: object type: array endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object healthcheck: - description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: - description: Image ID type: string instances: additionalProperties: properties: ipAddress: - description: IP address of the pod type: string podName: - description: Name of the OneAgent pod type: string type: object - description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: - description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: UpdatedTimestamp indicates when the instance was last - updated format: date-time type: string type: object diff --git a/config/crd/bases/dynatrace.com_edgeconnects.yaml b/config/crd/bases/dynatrace.com_edgeconnects.yaml index 83ca131ace..06f0872a9b 100644 --- a/config/crd/bases/dynatrace.com_edgeconnects.yaml +++ b/config/crd/bases/dynatrace.com_edgeconnects.yaml @@ -32,154 +32,84 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: EdgeConnect is the Schema for the EdgeConnect API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: EdgeConnectSpec defines the desired state of EdgeConnect. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the EdgeConnect pods type: object apiServer: - description: Location of the Dynatrace API to connect to, including - your specific environment UUID type: string autoUpdate: default: true - description: 'Enables automatic restarts of EdgeConnect pods in case - a new version is available (the default value is: true)' type: boolean caCertsRef: - description: Adds custom root certificate from a configmap. Put the - certificate under certs within your configmap. type: string customPullSecret: - description: Pull secret for your private registry type: string env: - description: Adds additional environment variables to the EdgeConnect - pods items: - description: EnvVar represents an environment variable present in - a Container. properties: name: - description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. Cannot - be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its key - must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath is - written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the specified - API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the exposed - resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key must - be defined type: boolean required: - key @@ -191,64 +121,42 @@ spec: type: object type: array hostPatterns: - description: Host patterns to be set in the tenant, only considered - when provisioning is enabled. items: type: string type: array hostRestrictions: - description: Restrict outgoing HTTP requests to your internal resources - to specified hosts example: internal.example.org,*.dev.example.org type: string imageRef: - description: Overrides the default image properties: repository: - description: Custom EdgeConnect image repository example: docker.io/dynatrace/edgeconnect type: string tag: - description: Indicates version of the EdgeConnect image to use type: string type: object kubernetesAutomation: - description: KubernetesAutomation enables Kubernetes Automation for - Workflows properties: enabled: - description: Enables Kubernetes Automation for Workflows type: boolean type: object labels: additionalProperties: type: string - description: Adds additional labels to the EdgeConnect pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes for the - EdgeConnect pods type: object oauth: - description: EdgeConnect uses the OAuth client to authenticate itself - with the Dynatrace platform. properties: clientSecret: - description: Name of the secret that holds oauth clientId/secret type: string endpoint: - description: Token endpoint URL of Dynatrace SSO type: string provisioner: - description: Determines if the operator will create the EdgeConnect - and light OAuth client on the cluster using the credentials - provided. Requires more scopes than default behavior. type: boolean resource: - description: URN identifying your account. You get the URN when - creating the OAuth client type: string required: - clientSecret @@ -256,59 +164,29 @@ spec: - resource type: object proxy: - description: General configurations for proxy settings. properties: authRef: - description: |- - Secret name which contains the username and password used for authentication with the proxy, using the - "Basic" HTTP authentication scheme. type: string host: - description: Server address (hostname or IP address) of the proxy. type: string noProxy: - description: |- - NoProxy represents the NO_PROXY or no_proxy environment - variable. It specifies a string that contains comma-separated values - specifying hosts that should be excluded from proxying. type: string port: - description: Port of the proxy. format: int32 type: integer type: object replicas: default: 1 - description: 'Amount of replicas for your EdgeConnect (the default - value is: 1)' format: int32 type: integer resources: - description: Defines resources requests and limits for single pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -324,9 +202,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -335,93 +210,40 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object serviceAccountName: default: dynatrace-edgeconnect - description: ServiceAccountName that allows EdgeConnect to access - the Kubernetes API type: string tolerations: - description: Sets tolerations for the EdgeConnect pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Sets topology spread constraints for the EdgeConnect - pods items: - description: TopologySpreadConstraint specifies how to spread matching - pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -435,69 +257,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -510,55 +290,32 @@ spec: - oauth type: object status: - description: EdgeConnectStatus defines the observed state of EdgeConnect. properties: conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -571,36 +328,24 @@ spec: type: object type: array kubeSystemUID: - description: kube-system namespace uid type: string phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: Indicates when the resource was last updated format: date-time type: string version: - description: Version used for the Edgeconnect image properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object type: object @@ -622,153 +367,83 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: EdgeConnect is the Schema for the EdgeConnect API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: EdgeConnectSpec defines the desired state of EdgeConnect. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the EdgeConnect pods type: object apiServer: - description: Location of the Dynatrace API to connect to, including - your specific environment UUID type: string autoUpdate: - description: 'Enables automatic restarts of EdgeConnect pods in case - a new version is available (the default value is: true)' type: boolean caCertsRef: - description: Adds custom root certificate from a configmap. Put the - certificate under certs within your configmap. type: string customPullSecret: - description: Pull secret for your private registry type: string env: - description: Adds additional environment variables to the EdgeConnect - pods items: - description: EnvVar represents an environment variable present in - a Container. properties: name: - description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. Cannot - be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its key - must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath is - written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the specified - API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the exposed - resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key must - be defined type: boolean required: - key @@ -780,66 +455,44 @@ spec: type: object type: array hostPatterns: - description: Host patterns to be set in the tenant, only considered - when provisioning is enabled. items: type: string type: array hostRestrictions: - description: Restrict outgoing HTTP requests to your internal resources - to specified hosts example: internal.example.org,*.dev.example.org items: type: string type: array imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object kubernetesAutomation: - description: KubernetesAutomation enables Kubernetes Automation for - Workflows properties: enabled: - description: Enables Kubernetes Automation for Workflows type: boolean type: object labels: additionalProperties: type: string - description: Adds additional labels to the EdgeConnect pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes for the - EdgeConnect pods type: object oauth: - description: EdgeConnect uses the OAuth client to authenticate itself - with the Dynatrace platform. properties: clientSecret: - description: Name of the secret that holds oauth clientId/secret type: string endpoint: - description: Token endpoint URL of Dynatrace SSO type: string provisioner: - description: Determines if the operator will create the EdgeConnect - and light OAuth client on the cluster using the credentials - provided. Requires more scopes than default behavior. type: boolean resource: - description: URN identifying your account. You get the URN when - creating the OAuth client type: string required: - clientSecret @@ -847,58 +500,28 @@ spec: - resource type: object proxy: - description: General configurations for proxy settings. properties: authRef: - description: |- - Secret name which contains the username and password used for authentication with the proxy, using the - "Basic" HTTP authentication scheme. type: string host: - description: Server address (hostname or IP address) of the proxy. type: string noProxy: - description: |- - NoProxy represents the NO_PROXY or no_proxy environment - variable. It specifies a string that contains comma-separated values - specifying hosts that should be excluded from proxying. type: string port: - description: Port of the proxy. format: int32 type: integer type: object replicas: - description: 'Amount of replicas for your EdgeConnect (the default - value is: 1)' format: int32 type: integer resources: - description: Defines resources requests and limits for single pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -914,9 +537,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -925,92 +545,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object serviceAccountName: - description: ServiceAccountName that allows EdgeConnect to access - the Kubernetes API type: string tolerations: - description: Sets tolerations for the EdgeConnect pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Sets topology spread constraints for the EdgeConnect - pods items: - description: TopologySpreadConstraint specifies how to spread matching - pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -1024,69 +591,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -1099,55 +624,32 @@ spec: - oauth type: object status: - description: EdgeConnectStatus defines the observed state of EdgeConnect. properties: conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -1160,36 +662,24 @@ spec: type: object type: array kubeSystemUID: - description: kube-system namespace uid type: string phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: Indicates when the resource was last updated format: date-time type: string version: - description: Version used for the Edgeconnect image properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object type: object diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 4b0417758e..92013513d0 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -44,165 +44,92 @@ spec: name: v1beta1 schema: openAPIV3Schema: - description: DynaKube is the Schema for the DynaKube API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: - description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the ActiveGate pods type: object capabilities: - description: Activegate capabilities enabled (routing, kubernetes-monitoring, - metrics-ingest, dynatrace-api) items: type: string type: array customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Custom properties value. nullable: true type: string valueFrom: - description: Custom properties secret. nullable: true type: string type: object dnsPolicy: - description: Sets DNS Policy for the ActiveGate pods type: string env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -214,58 +141,30 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the StatefulSet. type: string replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -281,9 +180,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -292,94 +188,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: - description: |- - The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. - server.p12: certificate+key pair in pkcs12 format - password: passphrase to read server.p12 type: string tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -393,69 +234,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -465,148 +264,80 @@ spec: type: array type: object apiUrl: - description: |- - Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. type: string customPullSecret: - description: |- - Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. - To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret - (https://www.dynatrace. type: string enableIstio: - description: |- - When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding - VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. - Disabled by default. type: boolean kubernetesMonitoring: - description: Configuration for Kubernetes Monitoring properties: customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Custom properties value. nullable: true type: string valueFrom: - description: Custom properties secret. nullable: true type: string type: object enabled: - description: Enables Capability type: boolean env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -618,53 +349,28 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -680,9 +386,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -691,88 +394,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -786,69 +438,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -858,33 +468,15 @@ spec: type: array type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector applies - to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -898,59 +490,26 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic networkZone: - description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: - description: |- - General configuration about OneAgent instances. - You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). properties: applicationMonitoring: - description: |- - dynatrace-webhook injects into application pods based on labeled namespaces. - Has an optional CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: codeModulesImage: - description: The OneAgent image that is used to inject into - Pods. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -966,9 +525,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -977,158 +533,85 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object useCSIDriver: - description: Set if you want to use the CSIDriver. Don't enable - it if you do not have access to Kubernetes nodes or if you - lack privileges. type: boolean version: - description: The OneAgent version to be used. type: string type: object classicFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - Injection is performed via the same OneAgent DaemonSet. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -1140,49 +623,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -1198,9 +655,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -1209,203 +663,103 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used. type: string type: object cloudNativeFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - dynatrace-webhook injects into application pods based on labeled namespaces. - Has a CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean codeModulesImage: - description: The OneAgent image that is used to inject into - Pods. type: string dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -1417,37 +771,15 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -1463,9 +795,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -1474,53 +803,24 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -1536,9 +836,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -1547,201 +844,103 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used. type: string type: object hostGroup: - description: Sets a host group for OneAgent. type: string hostMonitoring: - description: |- - Has a single OneAgent per node via DaemonSet. - Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -1753,49 +952,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -1811,9 +984,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -1822,203 +992,108 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used. type: string type: object type: object proxy: - description: |- - Set custom proxy settings either directly or from a secret with the field proxy. - Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. properties: value: - description: Proxy URL. It has preference over ValueFrom. nullable: true type: string valueFrom: - description: Secret containing proxy URL. nullable: true type: string type: object routing: - description: Configuration for Routing properties: customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Custom properties value. nullable: true type: string valueFrom: - description: Custom properties secret. nullable: true type: string type: object enabled: - description: Enables Capability type: boolean env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -2030,53 +1105,28 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -2092,9 +1142,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -2103,88 +1150,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -2198,69 +1194,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -2270,139 +1224,85 @@ spec: type: array type: object skipCertCheck: - description: |- - Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. - Set to true if you want to skip certification validation checks. type: boolean tokens: - description: Name of the secret holding the tokens used for connecting - to Dynatrace. type: string trustedCAs: - description: |- - Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. - Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. type: string required: - apiUrl type: object status: - description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: - description: Observed state of ActiveGate properties: connectionInfoStatus: - description: Information about Active Gate's connections properties: endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string serviceIPs: - description: The ClusterIPs set by Kubernetes on the ActiveGate - Service created by the Operator items: type: string type: array source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object codeModules: - description: Observed state of Code Modules properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -2415,104 +1315,72 @@ spec: type: object type: array dynatraceApi: - description: Observed state of Dynatrace API properties: lastTokenScopeRequest: - description: Time of the last token request format: date-time type: string type: object kubeSystemUUID: - description: KubeSystemUUID contains the UUID of the current Kubernetes - cluster type: string lastTokenProbeTimestamp: - description: LastTokenProbeTimestamp tracks when the last request - for the API token validity was sent format: date-time type: string oneAgent: - description: Observed state of OneAgent properties: connectionInfoStatus: - description: Information about OneAgent's connections properties: communicationHosts: - description: List of communication hosts items: properties: host: - description: Host domain type: string port: - description: Connection port format: int32 type: integer protocol: - description: Connection protocol type: string type: object type: array endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object healthcheck: - description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: - description: Image ID type: string instances: additionalProperties: properties: ipAddress: - description: IP address of the pod type: string podName: - description: Name of the OneAgent pod type: string type: object - description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: - description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: UpdatedTimestamp indicates when the instance was last - updated format: date-time type: string type: object @@ -2534,169 +1402,92 @@ spec: name: v1beta2 schema: openAPIV3Schema: - description: DynaKube is the Schema for the DynaKube API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: - description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the ActiveGate pods type: object capabilities: - description: "Defines the ActiveGate pod capabilities\nPossible - values:\n\t- `routing` enables OneAgent routing.\n\t- `kubernetes-monitoring` - enables Kubernetes API monitoring.\n\t- `metrics-ingest` opens - the metrics ingest endpoint on the DynaKube ActiveGate and redirects - all pods to it.\n\t- `dynatrace-api` enables calling the Dynatrace - API via ActiveGate." items: type: string type: array customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called `customProperties` properties: value: - description: Custom properties value. nullable: true type: string valueFrom: - description: Custom properties secret. nullable: true type: string type: object dnsPolicy: - description: Sets DNS Policy for the ActiveGate pods type: string env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -2708,62 +1499,31 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: Use a custom ActiveGate image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Your defined labels for ActiveGate pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes ActiveGate will be deployed. type: object priorityClassName: - description: |- - Assign a priority class to the ActiveGate pods. By default, no class is set. - For details, see Pod Priority and Preemption. (https://dt-url.net/n8437bl) type: string replicas: default: 1 - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: |- - Resource settings for ActiveGate container. - Consumption of the ActiveGate heavily depends on the workload to monitor. Adjust values accordingly. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -2779,9 +1539,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -2790,94 +1547,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: - description: |- - The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. - `server.p12`: certificate+key pair in pkcs12 format - `password`: passphrase to read server.p12 type: string tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints to the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -2891,69 +1593,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -2963,61 +1623,29 @@ spec: type: array type: object apiUrl: - description: |- - Dynatrace `apiUrl`, including the `/api` path at the end. - - For SaaS, set `YOUR_ENVIRONMENT_ID` to your environment ID. - - For Managed, change the `apiUrl` address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. type: string customPullSecret: - description: |- - Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. - To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret - (https://www.dynatrace. type: string dynatraceApiRequestThreshold: default: 15 - description: Minimum minutes between Dynatrace API requests. type: integer enableIstio: - description: |- - When enabled, and if Istio is installed in the Kubernetes environment, Dynatrace Operator will create the corresponding VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. - Disabled by default. type: boolean metadataEnrichment: - description: Configuration for Metadata Enrichment. properties: enabled: default: false - description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: - description: The namespaces where you want Dynatrace Operator - to inject enrichment. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -3031,10 +1659,6 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic @@ -3042,51 +1666,22 @@ spec: - enabled type: object networkZone: - description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: - description: |- - General configuration about OneAgent instances. - You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). properties: applicationMonitoring: - description: |- - dynatrace-webhook injects into application pods based on labeled namespaces. - Has an optional CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: codeModulesImage: - description: The OneAgent image that is used to inject into - Pods. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -3102,9 +1697,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -3113,41 +1705,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -3161,160 +1730,88 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic useCSIDriver: default: false - description: Set if you want to use the CSIDriver. Don't enable - it if you do not have access to Kubernetes nodes or if you - lack privileges. type: boolean version: - description: The OneAgent version to be used. type: string type: object classicFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - Injection is performed via the same OneAgent DaemonSet. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -3326,50 +1823,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - - `resource.requests` shows the values needed to run - - `resource.limits` shows the maximum limits for the pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -3385,9 +1855,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -3396,210 +1863,106 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used for OneAgents - running in the dedicated pod. This setting doesn't affect - the OneAgent version used for application monitoring. type: string type: object cloudNativeFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - dynatrace-webhook injects into application pods based on labeled namespaces. - Has a CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean codeModulesImage: - description: The OneAgent image that is used to inject into - Pods. type: string dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -3611,37 +1974,15 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -3657,9 +1998,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -3668,47 +2006,22 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -3722,48 +2035,21 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - - `resource.requests` shows the values needed to run - - `resource.limits` shows the maximum limits for the pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -3779,9 +2065,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -3790,211 +2073,106 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used for OneAgents - running in the dedicated pod. This setting doesn't affect - the OneAgent version used for application monitoring. type: string type: object hostGroup: - description: |- - Specify the name of the group to which you want to assign the host. - This method is preferred over the now obsolete `--set-host-group` argument. - If both settings are used, this field takes precedence over the `--set-host-group` argument. type: string hostMonitoring: - description: |- - Has a single OneAgent per node via DaemonSet. - Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -4006,50 +2184,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent Docker image. Defaults - to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - - `resource.requests` shows the values needed to run - - `resource.limits` shows the maximum limits for the pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -4065,9 +2216,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -4076,218 +2224,121 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: The OneAgent version to be used for OneAgents - running in the dedicated pod. This setting doesn't affect - the OneAgent version used for application monitoring. type: string type: object type: object proxy: - description: |- - Set custom proxy settings either directly or from a secret with the field `proxy`. - Applies to Dynatrace Operator, ActiveGate, and OneAgents. properties: value: - description: Proxy URL. It has preference over ValueFrom. nullable: true type: string valueFrom: - description: Secret containing proxy URL. nullable: true type: string type: object skipCertCheck: - description: |- - Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. - Set to `true` if you want to skip certification validation checks. type: boolean tokens: - description: Name of the secret holding the tokens used for connecting - to Dynatrace. type: string trustedCAs: - description: |- - Adds custom RootCAs from a configmap. - The key to the data must be `certs`. - This applies to both the Dynatrace Operator and the OneAgent. Doesn't apply to ActiveGate. type: string required: - apiUrl type: object status: - description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: - description: Observed state of ActiveGate properties: connectionInfoStatus: - description: Information about Active Gate's connections properties: endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string serviceIPs: - description: The ClusterIPs set by Kubernetes on the ActiveGate - Service created by the Operator items: type: string type: array source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object codeModules: - description: Observed state of Code Modules properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -4300,28 +2351,18 @@ spec: type: object type: array dynatraceApi: - description: Observed state of Dynatrace API properties: lastTokenScopeRequest: - description: Time of the last token request format: date-time type: string type: object kubeSystemUUID: - description: KubeSystemUUID contains the UUID of the current Kubernetes - cluster type: string kubernetesClusterMEID: - description: KubernetesClusterMEID contains the ID of the monitored - entity that points to the Kubernetes cluster type: string kubernetesClusterName: - description: KubernetesClusterName contains the display name (also - know as label) of the monitored entity that points to the Kubernetes - cluster type: string metadataEnrichment: - description: Observed state of Metadata-Enrichment properties: rules: items: @@ -4338,87 +2379,61 @@ spec: type: array type: object oneAgent: - description: Observed state of OneAgent properties: connectionInfoStatus: - description: Information about OneAgent's connections properties: communicationHosts: - description: List of communication hosts items: properties: host: - description: Host domain type: string port: - description: Connection port format: int32 type: integer protocol: - description: Connection protocol type: string type: object type: array endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object healthcheck: - description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: - description: Image ID type: string instances: additionalProperties: properties: ipAddress: - description: IP address of the pod type: string podName: - description: Name of the OneAgent pod type: string type: object - description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: - description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: UpdatedTimestamp indicates when the instance was last - updated format: date-time type: string type: object @@ -4440,165 +2455,92 @@ spec: name: v1beta3 schema: openAPIV3Schema: - description: DynaKube is the Schema for the DynaKube API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: - description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the ActiveGate pods type: object capabilities: - description: Activegate capabilities enabled (routing, kubernetes-monitoring, - metrics-ingest, dynatrace-api) items: type: string type: array customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Raw value for given property. nullable: true type: string valueFrom: - description: Name of the secret to get the property from. nullable: true type: string type: object dnsPolicy: - description: Sets DNS Policy for the ActiveGate pods type: string env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -4610,58 +2552,30 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the StatefulSet. type: string replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -4677,9 +2591,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -4688,94 +2599,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsSecretName: - description: |- - The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. - server.p12: certificate+key pair in pkcs12 format - password: passphrase to read server.p12 type: string tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -4789,69 +2645,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -4861,36 +2675,19 @@ spec: type: array type: object apiUrl: - description: |- - Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. maxLength: 128 type: string customPullSecret: - description: |- - Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. - To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret - (https://www.dynatrace. type: string dynatraceApiRequestThreshold: - description: Configuration for thresholding Dynatrace API requests. type: integer enableIstio: - description: |- - When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding - VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. - Disabled by default. type: boolean extensions: - description: |- - When an (empty) ExtensionsSpec is provided, the extensions related components (extensions controller and extensions collector) - are deployed by the operator. type: object kspm: - description: General configuration about the KSPM feature. type: object logMonitoring: - description: General configuration about the LogMonitoring feature. properties: ingestRuleMatchers: items: @@ -4905,38 +2702,19 @@ spec: type: array type: object metadataEnrichment: - description: Configuration for Metadata Enrichment. properties: enabled: - description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: - description: The namespaces where you want Dynatrace Operator - to inject enrichment. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -4950,60 +2728,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic type: object networkZone: - description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: - description: |- - General configuration about OneAgent instances. - You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). properties: applicationMonitoring: - description: |- - dynatrace-webhook injects into application pods based on labeled namespaces. - Has an optional CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: codeModulesImage: - description: Use a custom OneAgent CodeModule image to download - binaries. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5019,9 +2764,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5030,41 +2772,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -5078,154 +2797,84 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic version: - description: Use a specific OneAgent CodeModule version. Defaults - to the latest version from the Dynatrace cluster. type: string type: object classicFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - Injection is performed via the same OneAgent DaemonSet. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -5237,49 +2886,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5295,9 +2918,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5306,208 +2926,105 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object cloudNativeFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - dynatrace-webhook injects into application pods based on labeled namespaces. - Has a CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean codeModulesImage: - description: Use a custom OneAgent CodeModule image to download - binaries. type: string dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -5519,37 +3036,15 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5565,9 +3060,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5576,47 +3068,22 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -5630,47 +3097,21 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5686,9 +3127,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5697,206 +3135,105 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object hostGroup: - description: Sets a host group for OneAgent. type: string hostMonitoring: - description: |- - Has a single OneAgent per node via DaemonSet. - Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -5908,49 +3245,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -5966,9 +3277,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -5977,86 +3285,42 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object type: object proxy: - description: |- - Set custom proxy settings either directly or from a secret with the field proxy. - Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. properties: value: - description: Raw value for given property. nullable: true type: string valueFrom: - description: Name of the secret to get the property from. nullable: true type: string type: object skipCertCheck: - description: |- - Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. - Set to true if you want to skip certification validation checks. type: boolean templates: properties: @@ -6065,64 +3329,37 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations to the ExtensionExecutionController - pods type: object customConfig: - description: Defines name of ConfigMap containing custom configuration - file type: string customExtensionCertificates: - description: Defines name of Secret containing certificates - for custom extensions signature validation type: string imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the ExtensionExecutionController - pods type: object persistentVolumeClaim: - description: Defines storage device properties: accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 items: type: string type: array x-kubernetes-list-type: atomic dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string required: - kind @@ -6130,39 +3367,20 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. type: string required: - kind - name type: object resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes. properties: limits: additionalProperties: @@ -6171,9 +3389,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -6182,40 +3397,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object selector: - description: selector is a label query over volumes to - consider for binding. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -6229,62 +3422,26 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. type: string volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. type: string volumeName: - description: volumeName is the binding reference to the - PersistentVolume backing this claim. type: string type: object resources: - description: Define resources' requests and limits for single - ExtensionExecutionController pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -6300,9 +3457,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -6311,91 +3465,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: type: string tolerations: - description: Set tolerations for the ExtensionExecutionController - pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ExtensionExecutionController - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the - selector applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -6409,69 +3511,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -6480,7 +3540,6 @@ spec: type: object type: array useEphemeralVolume: - description: Selects EmptyDir volume to be storage device type: boolean type: object kspmNodeConfigurationCollector: @@ -6488,122 +3547,67 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations for the NodeConfigurationCollector - pods type: object args: - description: Set additional arguments to the NodeConfigurationCollector - pods items: type: string type: array env: - description: Set additional environment variables for the - NodeConfigurationCollector pods items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -6615,65 +3619,32 @@ spec: type: object type: array imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the NodeConfigurationCollector - pods type: object nodeAffinity: - description: Define the nodeAffinity for the DaemonSet of - the NodeConfigurationCollector properties: preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: preference: - description: A node selector term, associated with - the corresponding weight. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -6685,29 +3656,13 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: - description: A list of node selector requirements - by node's fields. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -6721,8 +3676,6 @@ spec: type: object x-kubernetes-map-type: atomic weight: - description: Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: @@ -6732,46 +3685,18 @@ spec: type: array x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. properties: nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -6783,29 +3708,13 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: - description: A list of node selector requirements - by node's fields. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -6828,41 +3737,17 @@ spec: nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes NodeConfigurationCollector pods will be deployed. type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the DaemonSet. type: string resources: - description: Define resources' requests and limits for single - NodeConfigurationCollector pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -6878,9 +3763,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -6889,163 +3771,81 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: - description: Set tolerations for the NodeConfigurationCollector - pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array updateStrategy: - description: Define the NodeConfigurationCollector daemonSet - updateStrategy properties: rollingUpdate: - description: Rolling update config params. Present only - if type = "RollingUpdate". properties: maxSurge: anyOf: - type: integer - type: string - description: |- - The maximum number of nodes with an existing available DaemonSet pod that - can have an updated DaemonSet pod during during an update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up to a minimum of 1. x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string - description: |- - The maximum number of DaemonSet pods that can be unavailable during the - update. Value can be an absolute number (ex: 5) or a percentage of total - number of DaemonSet pods at the start of the update (ex: 10%). Absolute - number is calculated from percentage by rounding up. - This cannot be 0 if MaxSurge is 0 - Default value is 1. x-kubernetes-int-or-string: true type: object type: - description: Type of daemon set update. Can be "RollingUpdate" - or "OnDelete". Default is RollingUpdate. type: string type: object type: object logMonitoring: - description: Low-level configuration options for the LogMonitoring - feature. properties: annotations: additionalProperties: type: string - description: Add custom annotations to the LogMonitoring pods type: object args: - description: Set additional arguments to the LogMonitoring - main container items: type: string type: array dnsPolicy: - description: Sets DNS Policy for the LogMonitoring pods type: string imageRef: - description: Overrides the default image for the LogMonitoring - pods properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Add custom labels to the LogMonitoring pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes - for the LogMonitoring pods type: object priorityClassName: - description: Assign a priority class to the LogMonitoring - pods. By default, no class is set type: string resources: - description: Define resources' requests and limits for all - the LogMonitoring pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -7061,9 +3861,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -7072,54 +3869,23 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode for the LogMonitoring - pods type: string tolerations: - description: Set tolerations for the LogMonitoring pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array @@ -7129,57 +3895,30 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations to the OtelCollector - pods type: object imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the OtelCollector - pods type: object replicas: - description: Number of replicas for your OtelCollector format: int32 type: integer resources: - description: Define resources' requests and limits for single - OtelCollector pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -7195,9 +3934,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -7206,90 +3942,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: type: string tolerations: - description: Set tolerations for the OtelCollector pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the OtelCollector - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the - selector applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -7303,69 +3988,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -7376,134 +4019,83 @@ spec: type: object type: object tokens: - description: Name of the secret holding the tokens used for connecting - to Dynatrace. type: string trustedCAs: - description: |- - Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. - Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. type: string required: - apiUrl type: object status: - description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: - description: Observed state of ActiveGate properties: connectionInfoStatus: - description: Information about Active Gate's connections properties: endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string serviceIPs: - description: The ClusterIPs set by Kubernetes on the ActiveGate - Service created by the Operator items: type: string type: array source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object codeModules: - description: Observed state of Code Modules properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -7516,37 +4108,23 @@ spec: type: object type: array dynatraceApi: - description: Observed state of Dynatrace API properties: lastTokenScopeRequest: - description: Time of the last token request format: date-time type: string type: object kspm: - description: Observed state of Kspm properties: tokenSecretHash: - description: |- - TokenSecretHash contains the hash of the token that is passed to both the ActiveGate and Node-Configuration-Collector. - Meant to keep the two in sync. type: string type: object kubeSystemUUID: - description: KubeSystemUUID contains the UUID of the current Kubernetes - cluster type: string kubernetesClusterMEID: - description: KubernetesClusterMEID contains the ID of the monitored - entity that points to the Kubernetes cluster type: string kubernetesClusterName: - description: KubernetesClusterName contains the display name (also - know as label) of the monitored entity that points to the Kubernetes - cluster type: string metadataEnrichment: - description: Observed state of Metadata-Enrichment properties: rules: items: @@ -7563,87 +4141,61 @@ spec: type: array type: object oneAgent: - description: Observed state of OneAgent properties: connectionInfoStatus: - description: Information about OneAgent's connections properties: communicationHosts: - description: List of communication hosts items: properties: host: - description: Host domain type: string port: - description: Connection port format: int32 type: integer protocol: - description: Connection protocol type: string type: object type: array endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object healthcheck: - description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: - description: Image ID type: string instances: additionalProperties: properties: ipAddress: - description: IP address of the pod type: string podName: - description: Name of the OneAgent pod type: string type: object - description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: - description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: UpdatedTimestamp indicates when the instance was last - updated format: date-time type: string type: object @@ -7665,165 +4217,92 @@ spec: name: v1beta4 schema: openAPIV3Schema: - description: DynaKube is the Schema for the DynaKube API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: - description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the ActiveGate pods type: object capabilities: - description: Activegate capabilities enabled (routing, kubernetes-monitoring, - metrics-ingest, dynatrace-api) items: type: string type: array customProperties: - description: |- - Add a custom properties file by providing it as a value or reference it from a secret - If referenced from a secret, make sure the key is called 'customProperties' properties: value: - description: Raw value for given property. nullable: true type: string valueFrom: - description: Name of the secret to get the property from. nullable: true type: string type: object dnsPolicy: - description: Sets DNS Policy for the ActiveGate pods type: string env: - description: List of environment variables to set for the ActiveGate items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its - key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the - specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key - must be defined type: boolean required: - key @@ -7835,52 +4314,31 @@ spec: type: object type: array group: - description: Set activation group for ActiveGate type: string image: - description: The ActiveGate container image. Defaults to the latest - ActiveGate image provided by the registry on the tenant type: string labels: additionalProperties: type: string - description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes type: object persistentVolumeClaim: - description: Defines storage device properties: accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 items: type: string type: array x-kubernetes-list-type: atomic dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string required: - kind @@ -7888,39 +4346,20 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. type: string required: - kind - name type: object resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes. properties: limits: additionalProperties: @@ -7929,9 +4368,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -7940,40 +4376,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object selector: - description: selector is a label query over volumes to consider - for binding. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -7987,71 +4401,31 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. type: string volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. type: string volumeName: - description: volumeName is the binding reference to the PersistentVolume - backing this claim. type: string type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the StatefulSet. type: string replicas: - description: Amount of replicas for your ActiveGates format: int32 type: integer resources: - description: Define resources requests and limits for single ActiveGate - pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -8067,9 +4441,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -8078,99 +4449,42 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object terminationGracePeriodSeconds: - description: Configures the terminationGracePeriodSeconds parameter - of the ActiveGate pod. Kubernetes defaults and rules apply. format: int64 type: integer tlsSecretName: - description: |- - The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. - server.p12: certificate+key pair in pkcs12 format - password: passphrase to read server.p12 type: string tolerations: - description: Set tolerations for the ActiveGate pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ActiveGate - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -8184,69 +4498,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -8255,40 +4527,22 @@ spec: type: object type: array useEphemeralVolume: - description: UseEphemeralVolume type: boolean type: object apiUrl: - description: |- - Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. - For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace. maxLength: 128 type: string customPullSecret: - description: |- - Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. - To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret - (https://www.dynatrace. type: string dynatraceApiRequestThreshold: - description: Configuration for thresholding Dynatrace API requests. type: integer enableIstio: - description: |- - When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding - VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. - Disabled by default. type: boolean extensions: - description: |- - When an (empty) ExtensionsSpec is provided, the extensions related components (extensions controller and extensions collector) - are deployed by the operator. type: object kspm: - description: General configuration about the KSPM feature. type: object logMonitoring: - description: General configuration about the LogMonitoring feature. properties: ingestRuleMatchers: items: @@ -8303,38 +4557,19 @@ spec: type: array type: object metadataEnrichment: - description: Configuration for Metadata Enrichment. properties: enabled: - description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: - description: The namespaces where you want Dynatrace Operator - to inject enrichment. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -8348,60 +4583,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic type: object networkZone: - description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: - description: |- - General configuration about OneAgent instances. - You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). properties: applicationMonitoring: - description: |- - dynatrace-webhook injects into application pods based on labeled namespaces. - Has an optional CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: codeModulesImage: - description: Use a custom OneAgent CodeModule image to download - binaries. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -8417,9 +4619,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -8428,41 +4627,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -8476,154 +4652,84 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic version: - description: Use a specific OneAgent CodeModule version. Defaults - to the latest version from the Dynatrace cluster. type: string type: object classicFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - Injection is performed via the same OneAgent DaemonSet. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -8635,49 +4741,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -8693,9 +4773,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -8704,213 +4781,107 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string storageHostPath: - description: StorageHostPath is the writable directory on - the host filesystem where OneAgent configurations will be - stored. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object cloudNativeFullStack: - description: |- - Has a single OneAgent per node via DaemonSet. - dynatrace-webhook injects into application pods based on labeled namespaces. - Has a CSI driver per node via DaemonSet to provide binaries to pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean codeModulesImage: - description: Use a custom OneAgent CodeModule image to download - binaries. type: string dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -8922,37 +4893,15 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string initResources: - description: |- - Define resources requests and limits for the initContainer. For details, see Managing resources for containers - (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -8968,9 +4917,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -8979,47 +4925,22 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object namespaceSelector: - description: |- - Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. - For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -9033,47 +4954,21 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -9089,9 +4984,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -9100,211 +4992,107 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string storageHostPath: - description: StorageHostPath is the writable directory on - the host filesystem where OneAgent configurations will be - stored. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object hostGroup: - description: Sets a host group for OneAgent. type: string hostMonitoring: - description: |- - Has a single OneAgent per node via DaemonSet. - Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string - description: Add custom OneAgent annotations. type: object args: - description: |- - Set additional arguments to the OneAgent installer. - For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). - For the list of limitations, see Limitations (https://www.dynatrace. items: type: string type: array x-kubernetes-list-type: set autoUpdate: - description: |- - Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). - Enabled by default. type: boolean dnsPolicy: - description: Set the DNS Policy for OneAgent pods. For details, - see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). type: string env: - description: Set additional environment variables for the - OneAgent pods. items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -9316,49 +5104,23 @@ spec: type: object type: array image: - description: Use a custom OneAgent image. Defaults to the - latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string - description: Your defined labels for OneAgent pods in order - to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes OneAgent will be deployed. type: object oneAgentResources: - description: |- - Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. - Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -9374,9 +5136,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -9385,95 +5144,46 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object priorityClassName: - description: |- - Assign a priority class to the OneAgent pods. By default, no class is set. - For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). type: string secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode. type: string storageHostPath: - description: StorageHostPath is the writable directory on - the host filesystem where OneAgent configurations will be - stored. type: string tolerations: - description: Tolerations to include with the OneAgent DaemonSet. - For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array version: - description: Use a specific OneAgent version. Defaults to - the latest version from the Dynatrace cluster. type: string type: object type: object proxy: - description: |- - Set custom proxy settings either directly or from a secret with the field proxy. - Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. properties: value: - description: Raw value for given property. nullable: true type: string valueFrom: - description: Name of the secret to get the property from. nullable: true type: string type: object skipCertCheck: - description: |- - Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. - Set to true if you want to skip certification validation checks. type: boolean telemetryIngest: - description: When a TelemetryIngestSpec is provided, the OTEL collector - is deployed by the operator. properties: protocols: items: @@ -9491,64 +5201,37 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations to the ExtensionExecutionController - pods type: object customConfig: - description: Defines name of ConfigMap containing custom configuration - file type: string customExtensionCertificates: - description: Defines name of Secret containing certificates - for custom extensions signature validation type: string imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the ExtensionExecutionController - pods type: object persistentVolumeClaim: - description: Defines storage device properties: accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 items: type: string type: array x-kubernetes-list-type: atomic dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string required: - kind @@ -9556,39 +5239,20 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. properties: apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. type: string kind: - description: Kind is the type of resource being referenced type: string name: - description: Name is the name of resource being referenced type: string namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. type: string required: - kind - name type: object resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes. properties: limits: additionalProperties: @@ -9597,9 +5261,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -9608,40 +5269,18 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object selector: - description: selector is a label query over volumes to - consider for binding. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -9655,62 +5294,26 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. type: string volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. type: string volumeName: - description: volumeName is the binding reference to the - PersistentVolume backing this claim. type: string type: object resources: - description: Define resources' requests and limits for single - ExtensionExecutionController pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -9726,9 +5329,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -9737,91 +5337,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: type: string tolerations: - description: Set tolerations for the ExtensionExecutionController - pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the ExtensionExecutionController - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the - selector applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -9835,69 +5383,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -9906,7 +5412,6 @@ spec: type: object type: array useEphemeralVolume: - description: Selects EmptyDir volume to be storage device type: boolean type: object kspmNodeConfigurationCollector: @@ -9914,122 +5419,67 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations for the NodeConfigurationCollector - pods type: object args: - description: Set additional arguments to the NodeConfigurationCollector - pods items: type: string type: array env: - description: Set additional environment variables for the - NodeConfigurationCollector pods items: - description: EnvVar represents an environment variable present - in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or - its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in - the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's - namespace properties: key: - description: The key of the secret to select - from. Must be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its - key must be defined type: boolean required: - key @@ -10041,65 +5491,32 @@ spec: type: object type: array imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the NodeConfigurationCollector - pods type: object nodeAffinity: - description: Define the nodeAffinity for the DaemonSet of - the NodeConfigurationCollector properties: preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: preference: - description: A node selector term, associated with - the corresponding weight. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -10111,29 +5528,13 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: - description: A list of node selector requirements - by node's fields. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -10147,8 +5548,6 @@ spec: type: object x-kubernetes-map-type: atomic weight: - description: Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: @@ -10158,46 +5557,18 @@ spec: type: array x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. properties: nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -10209,29 +5580,13 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: - description: A list of node selector requirements - by node's fields. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. properties: key: - description: The label key that the selector - applies to. type: string operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. items: type: string type: array @@ -10254,41 +5609,17 @@ spec: nodeSelector: additionalProperties: type: string - description: Specify the node selector that controls on which - nodes NodeConfigurationCollector pods will be deployed. type: object priorityClassName: - description: |- - If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that - name. If not specified the setting will be removed from the DaemonSet. type: string resources: - description: Define resources' requests and limits for single - NodeConfigurationCollector pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -10304,9 +5635,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -10315,163 +5643,81 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tolerations: - description: Set tolerations for the NodeConfigurationCollector - pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array updateStrategy: - description: Define the NodeConfigurationCollector daemonSet - updateStrategy properties: rollingUpdate: - description: Rolling update config params. Present only - if type = "RollingUpdate". properties: maxSurge: anyOf: - type: integer - type: string - description: |- - The maximum number of nodes with an existing available DaemonSet pod that - can have an updated DaemonSet pod during during an update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up to a minimum of 1. x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string - description: |- - The maximum number of DaemonSet pods that can be unavailable during the - update. Value can be an absolute number (ex: 5) or a percentage of total - number of DaemonSet pods at the start of the update (ex: 10%). Absolute - number is calculated from percentage by rounding up. - This cannot be 0 if MaxSurge is 0 - Default value is 1. x-kubernetes-int-or-string: true type: object type: - description: Type of daemon set update. Can be "RollingUpdate" - or "OnDelete". Default is RollingUpdate. type: string type: object type: object logMonitoring: - description: Low-level configuration options for the LogMonitoring - feature. properties: annotations: additionalProperties: type: string - description: Add custom annotations to the LogMonitoring pods type: object args: - description: Set additional arguments to the LogMonitoring - main container items: type: string type: array dnsPolicy: - description: Sets DNS Policy for the LogMonitoring pods type: string imageRef: - description: Overrides the default image for the LogMonitoring - pods properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Add custom labels to the LogMonitoring pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes - for the LogMonitoring pods type: object priorityClassName: - description: Assign a priority class to the LogMonitoring - pods. By default, no class is set type: string resources: - description: Define resources' requests and limits for all - the LogMonitoring pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -10487,9 +5733,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -10498,54 +5741,23 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object secCompProfile: - description: The SecComp Profile that will be configured in - order to run in secure computing mode for the LogMonitoring - pods type: string tolerations: - description: Set tolerations for the LogMonitoring pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array @@ -10555,57 +5767,30 @@ spec: annotations: additionalProperties: type: string - description: Adds additional annotations to the OtelCollector - pods type: object imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string - description: Adds additional labels for the OtelCollector - pods type: object replicas: - description: Number of replicas for your OtelCollector format: int32 type: integer resources: - description: Define resources' requests and limits for single - OtelCollector pod properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -10621,9 +5806,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -10632,90 +5814,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object tlsRefName: type: string tolerations: - description: Set tolerations for the OtelCollector pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Adds TopologySpreadConstraints for the OtelCollector - pods items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the - selector applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -10729,69 +5860,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -10802,134 +5891,83 @@ spec: type: object type: object tokens: - description: Name of the secret holding the tokens used for connecting - to Dynatrace. type: string trustedCAs: - description: |- - Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. - Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. type: string required: - apiUrl type: object status: - description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: - description: Observed state of ActiveGate properties: connectionInfoStatus: - description: Information about Active Gate's connections properties: endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string serviceIPs: - description: The ClusterIPs set by Kubernetes on the ActiveGate - Service created by the Operator items: type: string type: array source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object codeModules: - description: Observed state of Code Modules properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -10942,37 +5980,23 @@ spec: type: object type: array dynatraceApi: - description: Observed state of Dynatrace API properties: lastTokenScopeRequest: - description: Time of the last token request format: date-time type: string type: object kspm: - description: Observed state of Kspm properties: tokenSecretHash: - description: |- - TokenSecretHash contains the hash of the token that is passed to both the ActiveGate and Node-Configuration-Collector. - Meant to keep the two in sync. type: string type: object kubeSystemUUID: - description: KubeSystemUUID contains the UUID of the current Kubernetes - cluster type: string kubernetesClusterMEID: - description: KubernetesClusterMEID contains the ID of the monitored - entity that points to the Kubernetes cluster type: string kubernetesClusterName: - description: KubernetesClusterName contains the display name (also - know as label) of the monitored entity that points to the Kubernetes - cluster type: string metadataEnrichment: - description: Observed state of Metadata-Enrichment properties: rules: items: @@ -10989,87 +6013,61 @@ spec: type: array type: object oneAgent: - description: Observed state of OneAgent properties: connectionInfoStatus: - description: Information about OneAgent's connections properties: communicationHosts: - description: List of communication hosts items: properties: host: - description: Host domain type: string port: - description: Connection port format: int32 type: integer protocol: - description: Connection protocol type: string type: object type: array endpoints: - description: Available connection endpoints type: string lastRequest: - description: Time of the last connection request format: date-time type: string tenantTokenHash: - description: Hash of the tenant token type: string tenantUUID: - description: UUID of the tenant, received from the tenant type: string type: object healthcheck: - description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: - description: Image ID type: string instances: additionalProperties: properties: ipAddress: - description: IP address of the pod type: string podName: - description: Name of the OneAgent pod type: string type: object - description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: - description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: UpdatedTimestamp indicates when the instance was last - updated format: date-time type: string type: object @@ -11124,154 +6122,84 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: EdgeConnect is the Schema for the EdgeConnect API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: EdgeConnectSpec defines the desired state of EdgeConnect. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the EdgeConnect pods type: object apiServer: - description: Location of the Dynatrace API to connect to, including - your specific environment UUID type: string autoUpdate: default: true - description: 'Enables automatic restarts of EdgeConnect pods in case - a new version is available (the default value is: true)' type: boolean caCertsRef: - description: Adds custom root certificate from a configmap. Put the - certificate under certs within your configmap. type: string customPullSecret: - description: Pull secret for your private registry type: string env: - description: Adds additional environment variables to the EdgeConnect - pods items: - description: EnvVar represents an environment variable present in - a Container. properties: name: - description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. Cannot - be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its key - must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath is - written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the specified - API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the exposed - resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key must - be defined type: boolean required: - key @@ -11283,64 +6211,42 @@ spec: type: object type: array hostPatterns: - description: Host patterns to be set in the tenant, only considered - when provisioning is enabled. items: type: string type: array hostRestrictions: - description: Restrict outgoing HTTP requests to your internal resources - to specified hosts example: internal.example.org,*.dev.example.org type: string imageRef: - description: Overrides the default image properties: repository: - description: Custom EdgeConnect image repository example: docker.io/dynatrace/edgeconnect type: string tag: - description: Indicates version of the EdgeConnect image to use type: string type: object kubernetesAutomation: - description: KubernetesAutomation enables Kubernetes Automation for - Workflows properties: enabled: - description: Enables Kubernetes Automation for Workflows type: boolean type: object labels: additionalProperties: type: string - description: Adds additional labels to the EdgeConnect pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes for the - EdgeConnect pods type: object oauth: - description: EdgeConnect uses the OAuth client to authenticate itself - with the Dynatrace platform. properties: clientSecret: - description: Name of the secret that holds oauth clientId/secret type: string endpoint: - description: Token endpoint URL of Dynatrace SSO type: string provisioner: - description: Determines if the operator will create the EdgeConnect - and light OAuth client on the cluster using the credentials - provided. Requires more scopes than default behavior. type: boolean resource: - description: URN identifying your account. You get the URN when - creating the OAuth client type: string required: - clientSecret @@ -11348,59 +6254,29 @@ spec: - resource type: object proxy: - description: General configurations for proxy settings. properties: authRef: - description: |- - Secret name which contains the username and password used for authentication with the proxy, using the - "Basic" HTTP authentication scheme. type: string host: - description: Server address (hostname or IP address) of the proxy. type: string noProxy: - description: |- - NoProxy represents the NO_PROXY or no_proxy environment - variable. It specifies a string that contains comma-separated values - specifying hosts that should be excluded from proxying. type: string port: - description: Port of the proxy. format: int32 type: integer type: object replicas: default: 1 - description: 'Amount of replicas for your EdgeConnect (the default - value is: 1)' format: int32 type: integer resources: - description: Defines resources requests and limits for single pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -11416,9 +6292,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -11427,93 +6300,40 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object serviceAccountName: default: dynatrace-edgeconnect - description: ServiceAccountName that allows EdgeConnect to access - the Kubernetes API type: string tolerations: - description: Sets tolerations for the EdgeConnect pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Sets topology spread constraints for the EdgeConnect - pods items: - description: TopologySpreadConstraint specifies how to spread matching - pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -11527,69 +6347,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -11602,55 +6380,32 @@ spec: - oauth type: object status: - description: EdgeConnectStatus defines the observed state of EdgeConnect. properties: conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -11663,36 +6418,24 @@ spec: type: object type: array kubeSystemUID: - description: kube-system namespace uid type: string phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: Indicates when the resource was last updated format: date-time type: string version: - description: Version used for the Edgeconnect image properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object type: object @@ -11714,153 +6457,83 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: EdgeConnect is the Schema for the EdgeConnect API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: EdgeConnectSpec defines the desired state of EdgeConnect. properties: annotations: additionalProperties: type: string - description: Adds additional annotations to the EdgeConnect pods type: object apiServer: - description: Location of the Dynatrace API to connect to, including - your specific environment UUID type: string autoUpdate: - description: 'Enables automatic restarts of EdgeConnect pods in case - a new version is available (the default value is: true)' type: boolean caCertsRef: - description: Adds custom root certificate from a configmap. Put the - certificate under certs within your configmap. type: string customPullSecret: - description: Pull secret for your private registry type: string env: - description: Adds additional environment variables to the EdgeConnect - pods items: - description: EnvVar represents an environment variable present in - a Container. properties: name: - description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. type: string valueFrom: - description: Source for the environment variable's value. Cannot - be used if value is not empty. properties: configMapKeyRef: - description: Selects a key of a ConfigMap. properties: key: - description: The key to select. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the ConfigMap or its key - must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: - description: Version of the schema the FieldPath is - written in terms of, defaults to "v1". type: string fieldPath: - description: Path of the field to select in the specified - API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: - description: 'Container name: required for volumes, - optional for env vars' type: string divisor: anyOf: - type: integer - type: string - description: Specifies the output format of the exposed - resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: - description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: - description: Selects a key of a secret in the pod's namespace properties: key: - description: The key of the secret to select from. Must - be a valid secret key. type: string name: default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: - description: Specify whether the Secret or its key must - be defined type: boolean required: - key @@ -11872,66 +6545,44 @@ spec: type: object type: array hostPatterns: - description: Host patterns to be set in the tenant, only considered - when provisioning is enabled. items: type: string type: array hostRestrictions: - description: Restrict outgoing HTTP requests to your internal resources - to specified hosts example: internal.example.org,*.dev.example.org items: type: string type: array imageRef: - description: Overrides the default image properties: repository: - description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: - description: Indicates a tag of the image to use type: string type: object kubernetesAutomation: - description: KubernetesAutomation enables Kubernetes Automation for - Workflows properties: enabled: - description: Enables Kubernetes Automation for Workflows type: boolean type: object labels: additionalProperties: type: string - description: Adds additional labels to the EdgeConnect pods type: object nodeSelector: additionalProperties: type: string - description: Node selector to control the selection of nodes for the - EdgeConnect pods type: object oauth: - description: EdgeConnect uses the OAuth client to authenticate itself - with the Dynatrace platform. properties: clientSecret: - description: Name of the secret that holds oauth clientId/secret type: string endpoint: - description: Token endpoint URL of Dynatrace SSO type: string provisioner: - description: Determines if the operator will create the EdgeConnect - and light OAuth client on the cluster using the credentials - provided. Requires more scopes than default behavior. type: boolean resource: - description: URN identifying your account. You get the URN when - creating the OAuth client type: string required: - clientSecret @@ -11939,58 +6590,28 @@ spec: - resource type: object proxy: - description: General configurations for proxy settings. properties: authRef: - description: |- - Secret name which contains the username and password used for authentication with the proxy, using the - "Basic" HTTP authentication scheme. type: string host: - description: Server address (hostname or IP address) of the proxy. type: string noProxy: - description: |- - NoProxy represents the NO_PROXY or no_proxy environment - variable. It specifies a string that contains comma-separated values - specifying hosts that should be excluded from proxying. type: string port: - description: Port of the proxy. format: int32 type: integer type: object replicas: - description: 'Amount of replicas for your EdgeConnect (the default - value is: 1)' format: int32 type: integer resources: - description: Defines resources requests and limits for single pods properties: claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. type: string request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. type: string required: - name @@ -12006,9 +6627,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: @@ -12017,92 +6635,39 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object serviceAccountName: - description: ServiceAccountName that allows EdgeConnect to access - the Kubernetes API type: string tolerations: - description: Sets tolerations for the EdgeConnect pods items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . properties: effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. type: string tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: - description: Sets topology spread constraints for the EdgeConnect - pods items: - description: TopologySpreadConstraint specifies how to spread matching - pods among the given topology. properties: labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. properties: matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: key: - description: key is the label key that the selector - applies to. type: string operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. items: type: string type: array @@ -12116,69 +6681,27 @@ spec: matchLabels: additionalProperties: type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. items: type: string type: array x-kubernetes-list-type: atomic maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. format: int32 type: integer minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. format: int32 type: integer nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. type: string nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. type: string topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. type: string whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. type: string required: - maxSkew @@ -12191,55 +6714,32 @@ spec: - oauth type: object status: - description: EdgeConnectStatus defines the observed state of EdgeConnect. properties: conditions: - description: Conditions includes status about the current state of - the instance items: - description: Condition contains details for one aspect of the current - state of this API Resource. properties: lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -12252,36 +6752,24 @@ spec: type: object type: array kubeSystemUID: - description: kube-system namespace uid type: string phase: - description: Defines the current state (Running, Updating, Error, - ...) type: string updatedTimestamp: - description: Indicates when the resource was last updated format: date-time type: string version: - description: Version used for the Edgeconnect image properties: imageID: - description: Image ID type: string lastProbeTimestamp: - description: Indicates when the last check for a new version was - performed format: date-time type: string source: - description: Source of the image (tenant-registry, public-registry, - ...) type: string type: - description: Image type type: string version: - description: Image version type: string type: object type: object diff --git a/doc/api/dynakube-api-ref.md b/doc/api/dynakube-api-ref.md index d85e4309e3..b176b0e065 100644 --- a/doc/api/dynakube-api-ref.md +++ b/doc/api/dynakube-api-ref.md @@ -4,45 +4,45 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`apiUrl`|Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address.
For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret
(VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate.
Disabled by default.|-|boolean| -|`extensions`|When an (empty) ExtensionsSpec is provided, the extensions related components (extensions controller and extensions collector)
are deployed by the operator.|-|object| -|`kspm`|General configuration about the KSPM feature.|-|object| -|`networkZone`|Sets a network zone for the OneAgent and ActiveGate pods.|-|string| -|`proxy`|Set custom proxy settings either directly or from a secret with the field proxy.
Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents.|-|object| -|`skipCertCheck`|Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster.
Set to true if you want to skip certification validation checks.|-|boolean| -|`tokens`|Name of the secret holding the tokens used for connecting to Dynatrace.|-|string| -|`trustedCAs`|Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap.
Note: Applies to Dynatrace Operator, OneAgent and ActiveGate.|-|string| +|`apiUrl`||-|string| +|`customPullSecret`||-|string| +|`dynatraceApiRequestThreshold`||-|integer| +|`enableIstio`||-|boolean| +|`extensions`||-|object| +|`kspm`||-|object| +|`networkZone`||-|string| +|`proxy`||-|object| +|`skipCertCheck`||-|boolean| +|`tokens`||-|string| +|`trustedCAs`||-|string| ### .spec.oneAgent |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`hostGroup`|Sets a host group for OneAgent.|-|string| +|`hostGroup`||-|string| ### .spec.activeGate |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Adds additional annotations to the ActiveGate pods|-|object| -|`capabilities`|Activegate capabilities enabled (routing, kubernetes-monitoring, metrics-ingest, dynatrace-api)|-|array| -|`customProperties`|Add a custom properties file by providing it as a value or reference it from a secret
If referenced from a secret, make sure the key is called 'customProperties'|-|object| -|`dnsPolicy`|Sets DNS Policy for the ActiveGate pods|-|string| -|`env`|List of environment variables to set for the ActiveGate|-|array| -|`group`|Set activation group for ActiveGate|-|string| -|`image`|The ActiveGate container image. Defaults to the latest ActiveGate image provided by the registry on the tenant|-|string| -|`labels`|Adds additional labels for the ActiveGate pods|-|object| -|`nodeSelector`|Node selector to control the selection of nodes|-|object| -|`priorityClassName`|If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that
name. If not specified the setting will be removed from the StatefulSet.|-|string| -|`replicas`|Amount of replicas for your ActiveGates|-|integer| -|`resources`|Define resources requests and limits for single ActiveGate pods|-|object| -|`terminationGracePeriodSeconds`|Configures the terminationGracePeriodSeconds parameter of the ActiveGate pod. Kubernetes defaults and rules apply.|-|integer| -|`tlsSecretName`|The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used.
server.p12: certificate+key pair in pkcs12 format
password: passphrase to read server.p12|-|string| -|`tolerations`|Set tolerations for the ActiveGate pods|-|array| -|`topologySpreadConstraints`|Adds TopologySpreadConstraints for the ActiveGate pods|-|array| -|`useEphemeralVolume`|UseEphemeralVolume|-|boolean| +|`annotations`||-|object| +|`capabilities`||-|array| +|`customProperties`||-|object| +|`dnsPolicy`||-|string| +|`env`||-|array| +|`group`||-|string| +|`image`||-|string| +|`labels`||-|object| +|`nodeSelector`||-|object| +|`priorityClassName`||-|string| +|`replicas`||-|integer| +|`resources`||-|object| +|`terminationGracePeriodSeconds`||-|integer| +|`tlsSecretName`||-|string| +|`tolerations`||-|array| +|`topologySpreadConstraints`||-|array| +|`useEphemeralVolume`||-|boolean| ### .spec.logMonitoring @@ -62,219 +62,219 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`enabled`|Enables MetadataEnrichment, `false` by default.|-|boolean| -|`namespaceSelector`|The namespaces where you want Dynatrace Operator to inject enrichment.|-|object| +|`enabled`||-|boolean| +|`namespaceSelector`||-|object| ### .spec.oneAgent.hostMonitoring |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Add custom OneAgent annotations.|-|object| -|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().
For the list of limitations, see Limitations ().
Enabled by default.|-|boolean| -|`dnsPolicy`|Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy ().|-|string| -|`env`|Set additional environment variables for the OneAgent pods.|-|array| -|`image`|Use a custom OneAgent image. Defaults to the latest image from the Dynatrace cluster.|-|string| -|`labels`|Your defined labels for OneAgent pods in order to structure workloads as desired.|-|object| -|`nodeSelector`|Specify the node selector that controls on which nodes OneAgent will be deployed.|-|object| -|`oneAgentResources`|Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR.
Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod.|-|object| -|`priorityClassName`|Assign a priority class to the OneAgent pods. By default, no class is set.
For details, see Pod Priority and Preemption ().|-|string| -|`secCompProfile`|The SecComp Profile that will be configured in order to run in secure computing mode.|-|string| -|`storageHostPath`|StorageHostPath is the writable directory on the host filesystem where OneAgent configurations will be stored.|-|string| -|`tolerations`|Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations ().|-|array| -|`version`|Use a specific OneAgent version. Defaults to the latest version from the Dynatrace cluster.|-|string| +|`annotations`||-|object| +|`args`||-|array| +|`autoUpdate`||-|boolean| +|`dnsPolicy`||-|string| +|`env`||-|array| +|`image`||-|string| +|`labels`||-|object| +|`nodeSelector`||-|object| +|`oneAgentResources`||-|object| +|`priorityClassName`||-|string| +|`secCompProfile`||-|string| +|`storageHostPath`||-|string| +|`tolerations`||-|array| +|`version`||-|string| ### .spec.templates.logMonitoring |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Add custom annotations to the LogMonitoring pods|-|object| -|`args`|Set additional arguments to the LogMonitoring main container|-|array| -|`dnsPolicy`|Sets DNS Policy for the LogMonitoring pods|-|string| -|`labels`|Add custom labels to the LogMonitoring pods|-|object| -|`nodeSelector`|Node selector to control the selection of nodes for the LogMonitoring pods|-|object| -|`priorityClassName`|Assign a priority class to the LogMonitoring pods. By default, no class is set|-|string| -|`resources`|Define resources' requests and limits for all the LogMonitoring pods|-|object| -|`secCompProfile`|The SecComp Profile that will be configured in order to run in secure computing mode for the LogMonitoring pods|-|string| -|`tolerations`|Set tolerations for the LogMonitoring pods|-|array| +|`annotations`||-|object| +|`args`||-|array| +|`dnsPolicy`||-|string| +|`labels`||-|object| +|`nodeSelector`||-|object| +|`priorityClassName`||-|string| +|`resources`||-|object| +|`secCompProfile`||-|string| +|`tolerations`||-|array| ### .spec.templates.otelCollector |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Adds additional annotations to the OtelCollector pods|-|object| -|`labels`|Adds additional labels for the OtelCollector pods|-|object| -|`replicas`|Number of replicas for your OtelCollector|-|integer| -|`resources`|Define resources' requests and limits for single OtelCollector pod|-|object| +|`annotations`||-|object| +|`labels`||-|object| +|`replicas`||-|integer| +|`resources`||-|object| |`tlsRefName`||-|string| -|`tolerations`|Set tolerations for the OtelCollector pods|-|array| -|`topologySpreadConstraints`|Adds TopologySpreadConstraints for the OtelCollector pods|-|array| +|`tolerations`||-|array| +|`topologySpreadConstraints`||-|array| ### .spec.oneAgent.classicFullStack |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Add custom OneAgent annotations.|-|object| -|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().
For the list of limitations, see Limitations ().
Enabled by default.|-|boolean| -|`dnsPolicy`|Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy ().|-|string| -|`env`|Set additional environment variables for the OneAgent pods.|-|array| -|`image`|Use a custom OneAgent image. Defaults to the latest image from the Dynatrace cluster.|-|string| -|`labels`|Your defined labels for OneAgent pods in order to structure workloads as desired.|-|object| -|`nodeSelector`|Specify the node selector that controls on which nodes OneAgent will be deployed.|-|object| -|`oneAgentResources`|Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR.
Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod.|-|object| -|`priorityClassName`|Assign a priority class to the OneAgent pods. By default, no class is set.
For details, see Pod Priority and Preemption ().|-|string| -|`secCompProfile`|The SecComp Profile that will be configured in order to run in secure computing mode.|-|string| -|`storageHostPath`|StorageHostPath is the writable directory on the host filesystem where OneAgent configurations will be stored.|-|string| -|`tolerations`|Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations ().|-|array| -|`version`|Use a specific OneAgent version. Defaults to the latest version from the Dynatrace cluster.|-|string| +|`annotations`||-|object| +|`args`||-|array| +|`autoUpdate`||-|boolean| +|`dnsPolicy`||-|string| +|`env`||-|array| +|`image`||-|string| +|`labels`||-|object| +|`nodeSelector`||-|object| +|`oneAgentResources`||-|object| +|`priorityClassName`||-|string| +|`secCompProfile`||-|string| +|`storageHostPath`||-|string| +|`tolerations`||-|array| +|`version`||-|string| ### .spec.oneAgent.cloudNativeFullStack |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Add custom OneAgent annotations.|-|object| -|`args`|Set additional arguments to the OneAgent installer.
For available options, see Linux custom installation ().
For the list of limitations, see Limitations ().
Enabled by default.|-|boolean| -|`codeModulesImage`|Use a custom OneAgent CodeModule image to download binaries.|-|string| -|`dnsPolicy`|Set the DNS Policy for OneAgent pods. For details, see Pods DNS Policy ().|-|string| -|`env`|Set additional environment variables for the OneAgent pods.|-|array| -|`image`|Use a custom OneAgent image. Defaults to the latest image from the Dynatrace cluster.|-|string| -|`initResources`|Define resources requests and limits for the initContainer. For details, see Managing resources for containers
().|-|object| -|`labels`|Your defined labels for OneAgent pods in order to structure workloads as desired.|-|object| -|`namespaceSelector`|Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject.
For more information, see Configure monitoring for namespaces and pods (Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod.|-|object| -|`priorityClassName`|Assign a priority class to the OneAgent pods. By default, no class is set.
For details, see Pod Priority and Preemption ().|-|string| -|`secCompProfile`|The SecComp Profile that will be configured in order to run in secure computing mode.|-|string| -|`storageHostPath`|StorageHostPath is the writable directory on the host filesystem where OneAgent configurations will be stored.|-|string| -|`tolerations`|Tolerations to include with the OneAgent DaemonSet. For details, see Taints and Tolerations ().|-|array| -|`version`|Use a specific OneAgent version. Defaults to the latest version from the Dynatrace cluster.|-|string| +|`annotations`||-|object| +|`args`||-|array| +|`autoUpdate`||-|boolean| +|`codeModulesImage`||-|string| +|`dnsPolicy`||-|string| +|`env`||-|array| +|`image`||-|string| +|`initResources`||-|object| +|`labels`||-|object| +|`namespaceSelector`||-|object| +|`nodeSelector`||-|object| +|`oneAgentResources`||-|object| +|`priorityClassName`||-|string| +|`secCompProfile`||-|string| +|`storageHostPath`||-|string| +|`tolerations`||-|array| +|`version`||-|string| ### .spec.oneAgent.applicationMonitoring |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`codeModulesImage`|Use a custom OneAgent CodeModule image to download binaries.|-|string| -|`initResources`|Define resources requests and limits for the initContainer. For details, see Managing resources for containers
().|-|object| -|`namespaceSelector`|Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject.
For more information, see Configure monitoring for namespaces and pods (More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1|-|array| -|`dataSource`|dataSource field can be used to specify either:
* An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)
* An existing PVC (PersistentVolumeClaim)
If the provisioner or an external controller can support the specified data source,
it will create a new volume based on the contents of the specified data source.|-|object| -|`resources`|resources represents the minimum resources the volume should have.
If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.|-|object| -|`selector`|selector is a label query over volumes to consider for binding.|-|object| -|`storageClassName`|storageClassName is the name of the StorageClass required by the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1|-|string| -|`volumeAttributesClassName`|volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
it can be changed after the claim is created.|-|string| -|`volumeMode`|volumeMode defines what type of volume is required by the claim.
Value of Filesystem is implied when not included in claim spec.|-|string| -|`volumeName`|volumeName is the binding reference to the PersistentVolume backing this claim.|-|string| +|`accessModes`||-|array| +|`dataSource`||-|object| +|`resources`||-|object| +|`selector`||-|object| +|`storageClassName`||-|string| +|`volumeAttributesClassName`||-|string| +|`volumeMode`||-|string| +|`volumeName`||-|string| ### .spec.templates.logMonitoring.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`|Custom image repository|-|string| -|`tag`|Indicates a tag of the image to use|-|string| +|`repository`||-|string| +|`tag`||-|string| ### .spec.templates.otelCollector.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`|Custom image repository|-|string| -|`tag`|Indicates a tag of the image to use|-|string| +|`repository`||-|string| +|`tag`||-|string| ### .spec.templates.extensionExecutionController |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Adds additional annotations to the ExtensionExecutionController pods|-|object| -|`customConfig`|Defines name of ConfigMap containing custom configuration file|-|string| -|`customExtensionCertificates`|Defines name of Secret containing certificates for custom extensions signature validation|-|string| -|`labels`|Adds additional labels for the ExtensionExecutionController pods|-|object| -|`resources`|Define resources' requests and limits for single ExtensionExecutionController pod|-|object| +|`annotations`||-|object| +|`customConfig`||-|string| +|`customExtensionCertificates`||-|string| +|`labels`||-|object| +|`resources`||-|object| |`tlsRefName`||-|string| -|`tolerations`|Set tolerations for the ExtensionExecutionController pods|-|array| -|`topologySpreadConstraints`|Adds TopologySpreadConstraints for the ExtensionExecutionController pods|-|array| -|`useEphemeralVolume`|Selects EmptyDir volume to be storage device|-|boolean| +|`tolerations`||-|array| +|`topologySpreadConstraints`||-|array| +|`useEphemeralVolume`||-|boolean| ### .spec.templates.kspmNodeConfigurationCollector |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Adds additional annotations for the NodeConfigurationCollector pods|-|object| -|`args`|Set additional arguments to the NodeConfigurationCollector pods|-|array| -|`env`|Set additional environment variables for the NodeConfigurationCollector pods|-|array| -|`labels`|Adds additional labels for the NodeConfigurationCollector pods|-|object| -|`nodeSelector`|Specify the node selector that controls on which nodes NodeConfigurationCollector pods will be deployed.|-|object| -|`priorityClassName`|If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that
name. If not specified the setting will be removed from the DaemonSet.|-|string| -|`resources`|Define resources' requests and limits for single NodeConfigurationCollector pod|-|object| -|`tolerations`|Set tolerations for the NodeConfigurationCollector pods|-|array| +|`annotations`||-|object| +|`args`||-|array| +|`env`||-|array| +|`labels`||-|object| +|`nodeSelector`||-|object| +|`priorityClassName`||-|string| +|`resources`||-|object| +|`tolerations`||-|array| ### .spec.activeGate.persistentVolumeClaim.dataSourceRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`apiGroup`|APIGroup is the group for the resource being referenced.
If APIGroup is not specified, the specified Kind must be in the core API group.
For any other third-party types, APIGroup is required.|-|string| -|`kind`|Kind is the type of resource being referenced|-|string| -|`name`|Name is the name of resource being referenced|-|string| -|`namespace`|Namespace is the namespace of resource being referenced
Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.|-|string| +|`apiGroup`||-|string| +|`kind`||-|string| +|`name`||-|string| +|`namespace`||-|string| ### .spec.templates.extensionExecutionController.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`|Custom image repository|-|string| -|`tag`|Indicates a tag of the image to use|-|string| +|`repository`||-|string| +|`tag`||-|string| ### .spec.templates.kspmNodeConfigurationCollector.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`|Custom image repository|-|string| -|`tag`|Indicates a tag of the image to use|-|string| +|`repository`||-|string| +|`tag`||-|string| ### .spec.templates.kspmNodeConfigurationCollector.nodeAffinity |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`preferredDuringSchedulingIgnoredDuringExecution`|The scheduler will prefer to schedule pods to nodes that satisfy
the affinity expressions specified by this field, but it may choose
a node that violates one or more of the expressions. The node that is
most preferred is the one with the greatest sum of weights, i.e.|-|array| -|`requiredDuringSchedulingIgnoredDuringExecution`|If the affinity requirements specified by this field are not met at
scheduling time, the pod will not be scheduled onto the node.
If the affinity requirements specified by this field cease to be met
at some point during pod execution (e.g. due to an update), the system
may or may not try to eventually evict the pod from its node.|-|object| +|`preferredDuringSchedulingIgnoredDuringExecution`||-|array| +|`requiredDuringSchedulingIgnoredDuringExecution`||-|object| ### .spec.templates.kspmNodeConfigurationCollector.updateStrategy |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`type`|Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is RollingUpdate.|-|string| +|`type`||-|string| ### .spec.templates.extensionExecutionController.persistentVolumeClaim |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`accessModes`|accessModes contains the desired access modes the volume should have.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1|-|array| -|`dataSource`|dataSource field can be used to specify either:
* An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)
* An existing PVC (PersistentVolumeClaim)
If the provisioner or an external controller can support the specified data source,
it will create a new volume based on the contents of the specified data source.|-|object| -|`resources`|resources represents the minimum resources the volume should have.
If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.|-|object| -|`selector`|selector is a label query over volumes to consider for binding.|-|object| -|`storageClassName`|storageClassName is the name of the StorageClass required by the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1|-|string| -|`volumeAttributesClassName`|volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
it can be changed after the claim is created.|-|string| -|`volumeMode`|volumeMode defines what type of volume is required by the claim.
Value of Filesystem is implied when not included in claim spec.|-|string| -|`volumeName`|volumeName is the binding reference to the PersistentVolume backing this claim.|-|string| +|`accessModes`||-|array| +|`dataSource`||-|object| +|`resources`||-|object| +|`selector`||-|object| +|`storageClassName`||-|string| +|`volumeAttributesClassName`||-|string| +|`volumeMode`||-|string| +|`volumeName`||-|string| ### .spec.templates.kspmNodeConfigurationCollector.updateStrategy.rollingUpdate |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`maxSurge`|The maximum number of nodes with an existing available DaemonSet pod that
can have an updated DaemonSet pod during during an update.
Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
This can not be 0 if MaxUnavailable is 0.
Absolute number is calculated from percentage by rounding up to a minimum of 1.|-|integer or string| -|`maxUnavailable`|The maximum number of DaemonSet pods that can be unavailable during the
update. Value can be an absolute number (ex: 5) or a percentage of total
number of DaemonSet pods at the start of the update (ex: 10%). Absolute
number is calculated from percentage by rounding up.
This cannot be 0 if MaxSurge is 0
Default value is 1.|-|integer or string| +|`maxSurge`||-|integer or string| +|`maxUnavailable`||-|integer or string| ### .spec.templates.extensionExecutionController.persistentVolumeClaim.dataSourceRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`apiGroup`|APIGroup is the group for the resource being referenced.
If APIGroup is not specified, the specified Kind must be in the core API group.
For any other third-party types, APIGroup is required.|-|string| -|`kind`|Kind is the type of resource being referenced|-|string| -|`name`|Name is the name of resource being referenced|-|string| -|`namespace`|Namespace is the namespace of resource being referenced
Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.|-|string| +|`apiGroup`||-|string| +|`kind`||-|string| +|`name`||-|string| +|`namespace`||-|string| diff --git a/doc/api/edgeconnect-api-ref.md b/doc/api/edgeconnect-api-ref.md index e476553807..e6336e9d35 100644 --- a/doc/api/edgeconnect-api-ref.md +++ b/doc/api/edgeconnect-api-ref.md @@ -4,49 +4,49 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`|Adds additional annotations to the EdgeConnect pods|-|object| -|`apiServer`|Location of the Dynatrace API to connect to, including your specific environment UUID|-|string| -|`autoUpdate`|Enables automatic restarts of EdgeConnect pods in case a new version is available (the default value is: true)|-|boolean| -|`caCertsRef`|Adds custom root certificate from a configmap. Put the certificate under certs within your configmap.|-|string| -|`customPullSecret`|Pull secret for your private registry|-|string| -|`env`|Adds additional environment variables to the EdgeConnect pods|-|array| -|`hostPatterns`|Host patterns to be set in the tenant, only considered when provisioning is enabled.|-|array| -|`hostRestrictions`|Restrict outgoing HTTP requests to your internal resources to specified hosts|-|array| -|`labels`|Adds additional labels to the EdgeConnect pods|-|object| -|`nodeSelector`|Node selector to control the selection of nodes for the EdgeConnect pods|-|object| -|`replicas`|Amount of replicas for your EdgeConnect (the default value is: 1)|-|integer| -|`resources`|Defines resources requests and limits for single pods|-|object| -|`serviceAccountName`|ServiceAccountName that allows EdgeConnect to access the Kubernetes API|-|string| -|`tolerations`|Sets tolerations for the EdgeConnect pods|-|array| -|`topologySpreadConstraints`|Sets topology spread constraints for the EdgeConnect pods|-|array| +|`annotations`||-|object| +|`apiServer`||-|string| +|`autoUpdate`||-|boolean| +|`caCertsRef`||-|string| +|`customPullSecret`||-|string| +|`env`||-|array| +|`hostPatterns`||-|array| +|`hostRestrictions`||-|array| +|`labels`||-|object| +|`nodeSelector`||-|object| +|`replicas`||-|integer| +|`resources`||-|object| +|`serviceAccountName`||-|string| +|`tolerations`||-|array| +|`topologySpreadConstraints`||-|array| ### .spec.oauth |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`clientSecret`|Name of the secret that holds oauth clientId/secret|-|string| -|`endpoint`|Token endpoint URL of Dynatrace SSO|-|string| -|`provisioner`|Determines if the operator will create the EdgeConnect and light OAuth client on the cluster using the credentials provided. Requires more scopes than default behavior.|-|boolean| -|`resource`|URN identifying your account. You get the URN when creating the OAuth client|-|string| +|`clientSecret`||-|string| +|`endpoint`||-|string| +|`provisioner`||-|boolean| +|`resource`||-|string| ### .spec.proxy |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`authRef`|Secret name which contains the username and password used for authentication with the proxy, using the
"Basic" HTTP authentication scheme.|-|string| -|`host`|Server address (hostname or IP address) of the proxy.|-|string| -|`noProxy`|NoProxy represents the NO_PROXY or no_proxy environment
variable. It specifies a string that contains comma-separated values
specifying hosts that should be excluded from proxying.|-|string| -|`port`|Port of the proxy.|-|integer| +|`authRef`||-|string| +|`host`||-|string| +|`noProxy`||-|string| +|`port`||-|integer| ### .spec.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`|Custom image repository|-|string| -|`tag`|Indicates a tag of the image to use|-|string| +|`repository`||-|string| +|`tag`||-|string| ### .spec.kubernetesAutomation |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`enabled`|Enables Kubernetes Automation for Workflows|-|boolean| +|`enabled`||-|boolean| From 0699e7e04ce940c8846c53636b9f8c86368d901e Mon Sep 17 00:00:00 2001 From: Gabriel Krenn Date: Fri, 4 Apr 2025 14:00:15 +0200 Subject: [PATCH 398/426] Fix typo in digest of release pipeline (#4713) --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index af7aed49d0..37e5a8bf34 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -292,8 +292,8 @@ jobs: run: | make manifests/crd/release CHART_VERSION="${VERSION_WITHOUT_PREFIX}" - make manifests/kubernetes/olm IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-ecr}}" - make manifests/kubernetes IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-ecr}}" + make manifests/kubernetes/olm IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-amazon-ecr}}" + make manifests/kubernetes IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-amazon-ecr}}" make manifests/openshift/olm IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-rhcc}}" make manifests/openshift IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-rhcc}}" cp config/deploy/kubernetes/kubernetes.yaml config/deploy/kubernetes/gke-autopilot.yaml From 3490f81185bdff9961cbfa9788ebe3842627ec4b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 5 Apr 2025 02:10:11 +0000 Subject: [PATCH 399/426] chore(deps): update module github.com/helm-unittest/helm-unittest to v0.8.1 (release-1.5) (#4715) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hack/make/prerequisites.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/prerequisites.mk b/hack/make/prerequisites.mk index 9c3b26a27e..14f24e5455 100644 --- a/hack/make/prerequisites.mk +++ b/hack/make/prerequisites.mk @@ -13,7 +13,7 @@ mockery_version=v2.53.3 # renovate depName=github.com/igorshubovych/markdownlint-cli markdownlint_cli_version=v0.44.0 # renovate depName=github.com/helm-unittest/helm-unittest -helmunittest_version=v0.8.0 +helmunittest_version=v0.8.1 # renovate depName=github.com/princjef/gomarkdoc gomarkdoc_version=v1.1.0 # renovate depName=github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod From e7f74aadc098349e5bcab85d4b7917489a48b353 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:04:03 +0000 Subject: [PATCH 400/426] chore(deps): update github/codeql-action action to v3.28.14 (release-1.5) (#4720) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 44267af5ed..21d2f406d4 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 + uses: github/codeql-action/init@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 + uses: github/codeql-action/autobuild@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 + uses: github/codeql-action/analyze@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 52ba2247a9..7cda197e44 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 + uses: github/codeql-action/upload-sarif@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14 with: sarif_file: results.sarif From f0eeb654a746f0328fb107da3266645226341c3e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 06:18:57 +0000 Subject: [PATCH 401/426] chore(deps): update github/codeql-action action to v3.28.15 (release-1.5) (#4725) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 21d2f406d4..06ee3751cd 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14 + uses: github/codeql-action/init@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14 + uses: github/codeql-action/autobuild@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14 + uses: github/codeql-action/analyze@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 7cda197e44..5ae8f3c09e 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14 + uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 with: sarif_file: results.sarif From 0d58758515308d6378f6b6f8ae511f0325f7530a Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Tue, 8 Apr 2025 14:43:26 +0200 Subject: [PATCH 402/426] Rework CI (#4729) --- .../action.yaml | 34 +++-- .github/actions/create-manifests/action.yaml | 29 ---- .github/actions/sign-image/action.yaml | 4 +- .github/workflows/ci.yaml | 71 ++-------- .github/workflows/release.yaml | 134 ++++++------------ hack/build/ci/prepare-build-variables.sh | 3 +- test/helpers/feature.go | 2 + test/helpers/kubeobjects/statefulset/get.go | 2 + test/helpers/platform/platform.go | 2 + test/helpers/registry/registry.go | 2 + test/scenarios/filter.go | 2 + 11 files changed, 92 insertions(+), 193 deletions(-) rename .github/actions/{build-image => build-push-image}/action.yaml (61%) delete mode 100644 .github/actions/create-manifests/action.yaml diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-push-image/action.yaml similarity index 61% rename from .github/actions/build-image/action.yaml rename to .github/actions/build-push-image/action.yaml index 01000c215f..f5b0f06c11 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-push-image/action.yaml @@ -1,20 +1,21 @@ -name: Build Docker Image -description: Builds the operator docker image +name: Build and Push Docker Image +description: Builds and pushes the operator docker image inputs: - platform: - description: The platform for which the image will be built + platforms: + description: The platforms for which the image will be built + defaults: linux/amd64,linux/arm64 required: true labels: description: The labels for the built image required: true - image: - description: The tag of the built image + tags: + description: The tags of the built image. Should be the whole image URIs, like docker.io/dynatrace/dynatrace-operator:snapshot,quay.io/dynatrace/dynatrace-operator:snapshot required: true annotation: description: The annotation added to the built image outputs: digest: - description: "The digest of the built image" + description: The digest of the built image value: ${{ steps.build-target.outputs.digest }} runs: using: "composite" @@ -40,6 +41,13 @@ runs: shell: bash run: | touch dynatrace-operator-bin-sbom.cdx.json + - name: Docker metadata + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + id: meta + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + with: + images: ${{ inputs.image }} - name: Build target id: build-target uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 @@ -51,9 +59,13 @@ runs: context: . file: ./Dockerfile provenance: false - platforms: linux/${{ inputs.platform }} + platforms: ${{ inputs.platforms }} push: true - tags: ${{ inputs.image }} - labels: ${{ inputs.labels }} - annotations: ${{ inputs.annotation }} + tags: ${{ inputs.tags }} + labels: | + ${{ inputs.labels }} + ${{ steps.meta.outputs.labels }} + annotations: | + ${{ inputs.annotation }} + ${{ steps.meta.outputs.annotations }} diff --git a/.github/actions/create-manifests/action.yaml b/.github/actions/create-manifests/action.yaml deleted file mode 100644 index 5f8cd3e5fd..0000000000 --- a/.github/actions/create-manifests/action.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Create Manifests -description: Creates the manifests for the images -inputs: - version: - description: The version the manifests are for - required: true - registry: - description: The registry where the manifests are pushed - required: true - repository: - description: The repository in the registry where the manifests are pushed - required: true - platforms: - description: List of platforms - required: true -outputs: - digest: - description: The digest of the created manifest - value: ${{ steps.create-manifest.outputs.digest }} -runs: - using: "composite" - steps: - - name: Create manifest - id: create-manifest - env: - IMAGE: ${{ inputs.registry }}/${{ inputs.repository }} - shell: bash - run: | - hack/build/ci/create-manifest.sh "${IMAGE}" "${{ inputs.version }}" "${{ inputs.platforms }}" diff --git a/.github/actions/sign-image/action.yaml b/.github/actions/sign-image/action.yaml index 31215bc6a4..8fbae189b8 100644 --- a/.github/actions/sign-image/action.yaml +++ b/.github/actions/sign-image/action.yaml @@ -18,13 +18,13 @@ runs: - name: Sign image with a key shell: bash run: | - cosign sign -y --key env://COSIGN_PRIVATE_KEY ${IMAGE} + cosign sign -y --key env://COSIGN_PRIVATE_KEY --recursive ${IMAGE} env: IMAGE: ${{ inputs.image }} COSIGN_PRIVATE_KEY: ${{ inputs.signing-key }} COSIGN_PASSWORD: ${{ inputs.signing-password }} - name: Sign the images with GitHub OIDC Token shell: bash - run: cosign sign -y ${IMAGE} + run: cosign sign -y --recursive ${IMAGE} env: IMAGE: ${{ inputs.image }} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 39321dfd15..ccae198dcf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -13,8 +13,10 @@ permissions: contents: read env: - DOCKER_REGISTRY: "quay.io" - DOCKER_REPOSITORY: "dynatrace/dynatrace-operator" + DOCKER_REGISTRY: quay.io + DOCKER_REPOSITORY: dynatrace/dynatrace-operator + PLATFORMS: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x + PR_PLATFORMS: linux/amd64,linux/arm64 jobs: helm-test: @@ -62,15 +64,6 @@ jobs: id: check-code-coverage run: | make go/check-coverage - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 - with: - fail_ci_if_error: true - verbose: true - files: ./coverage.txt - flags: unittests # optional - name: codecov-umbrella # optional - token: ${{ secrets.CODECOV_TOKEN }} linting: name: Run linting @@ -157,37 +150,14 @@ jobs: id: prep run: | hack/build/ci/prepare-build-variables.sh - - name: Docker metadata - uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 - id: meta - with: - images: dynatrace/dynatrace-operator - tags: ${{ steps.prep.outputs.docker_image_tag }} - labels: | - ${{ steps.prep.outputs.docker_image_labels }} - vcs-ref=${{ github.sha }} - - name: Prepare build parameters - id: prepenv - run: | - # Set output parameters. - # Reason: global envs do not work in workflow calls - # More info: https://github.com/actions/runner/issues/480#issuecomment-1021278915 - - echo "registry=${{ env.DOCKER_REGISTRY }}" >> "$GITHUB_OUTPUT" - echo "repository=${{ env.DOCKER_REPOSITORY }}" >> "$GITHUB_OUTPUT" outputs: - labels: ${{ steps.meta.outputs.labels }} + labels: ${{ steps.prep.outputs.docker_image_labels }} version: ${{ steps.prep.outputs.docker_image_tag }} - registry: ${{ steps.prepenv.outputs.registry }} - repository: ${{ steps.prepenv.outputs.repository }} - build: + build-push: name: Build images runs-on: ubuntu-latest needs: [prepare, tests, linting, generated-files] - strategy: - matrix: - platform: [amd64, arm64, ppc64le, s390x] steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -198,32 +168,9 @@ jobs: username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_PASSWORD }} - name: Build image - if: matrix.platform == 'amd64' || matrix.platform == 'arm64' || github.ref_protected - uses: ./.github/actions/build-image + uses: ./.github/actions/build-push-image with: - platform: ${{ matrix.platform }} + platforms: ${{github.ref_protected && env.PLATFORMS || env.PR_PLATFORMS }} labels: ${{ needs.prepare.outputs.labels }} - image: ${{ needs.prepare.outputs.registry }}/${{ needs.prepare.outputs.repository }}:${{ needs.prepare.outputs.version }}-${{ matrix.platform }} + tags: ${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_REPOSITORY }}:${{ needs.prepare.outputs.version }} annotation: "version=${{ needs.prepare.outputs.version }}" - - manifest: - name: Create manifest - needs: [prepare, build] - runs-on: ubuntu-latest - if: ${{ !github.event.pull_request.head.repo.fork }} - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Login to Registry - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 - with: - registry: quay.io - username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.QUAY_PASSWORD }} - - name: Create Manifests - uses: ./.github/actions/create-manifests - with: - platforms: ${{github.ref_protected && 'amd64, arm64, ppc64le, s390x' || 'amd64, arm64'}} - version: ${{ needs.prepare.outputs.version }} - registry: ${{ needs.prepare.outputs.registry }} - repository: ${{ needs.prepare.outputs.repository }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 37e5a8bf34..3c911eeb7a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -7,6 +7,8 @@ on: env: GOOGLE_MARKETPLACE_ANNOTATION: com.googleapis.cloudmarketplace.product.service.name=services/dynatrace-operator-dynatrace-marketplace-prod.cloudpartnerservices.goog + PLATFORMS: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x + DEPLOYER_PLATFORMS: linux/amd64 jobs: prepare: @@ -22,52 +24,23 @@ jobs: id: prep run: | hack/build/ci/prepare-build-variables.sh - - name: Docker metadata - uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 - id: meta - with: - images: dynatrace/dynatrace-operator - tags: | - type=semver,pattern={{major}}.{{minor}} - ${{ steps.prep.outputs.docker_image_tag }} - labels: | - ${{ steps.prep.outputs.docker_image_labels }} - vcs-ref=${{ github.sha }} outputs: - labels: ${{ steps.meta.outputs.labels }} + labels: ${{ steps.prep.outputs.docker_image_labels }} version: ${{ steps.prep.outputs.docker_image_tag }} version_without_prefix: ${{ steps.prep.outputs.docker_image_tag_without_prefix }} - build: + build-push: name: Build images environment: Release runs-on: ubuntu-latest permissions: id-token: write needs: [prepare] - strategy: - matrix: - platform: [amd64, arm64, ppc64le, s390x] - registry: [gcr, dockerhub, rhcc, amazon-ecr] - include: - - registry: gcr - url: gcr.io - repository: GCR_REPOSITORY - username: GCR_USERNAME - password: GCR_JSON_KEY - - registry: dockerhub - url: docker.io - repository: DOCKERHUB_REPOSITORY - username: DOCKERHUB_USERNAME - password: DOCKERHUB_PASSWORD - - registry: amazon-ecr - url: public.ecr.aws - repository: ECR_REPOSITORY - - registry: rhcc - url: quay.io - username: RHCC_USERNAME - password: RHCC_PASSWORD - repository: RHCC_REPOSITORY + env: + GCR_IMAGE: gcr.io/${{ secrets.GCR_REPOSITORY }}:${{ needs.prepare.outputs.version }} + ECR_IMAGE: public.ecr.aws.io/${{ secrets.ECR_REPOSITORY }}:${{ needs.prepare.outputs.version }} + RHCC_IMAGE: quay.io/${{ secrets.RHCC_REPOSITORY }}:${{ needs.prepare.outputs.version }} + DOCKER_IMAGE: docker.io/${{ secrets.DOCKERHUB_REPOSITORY }}:${{ needs.prepare.outputs.version }} steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -79,51 +52,51 @@ jobs: id: sbom run: | make release/gen-sbom - - name: Login to Registry - if: ${{ matrix.registry != 'amazon-ecr' }} + - name: Login to GCR uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: - registry: ${{ matrix.url }} - username: ${{ secrets[matrix.username] }} - password: ${{ secrets[matrix.password] }} + registry: gcr.io + username: ${{ secrets.GCR_USERNAME }} + password: ${{ secrets.GCR_JSON_KEY }} + - name: Login to RHCC + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: quay.io + username: ${{ secrets.RHCC_USERNAME }} + password: ${{ secrets.RHCC_PASSWORD }} + - name: Login to Docker + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: docker.io + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Configure aws credentials - if: ${{ matrix.registry == 'amazon-ecr' }} uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 with: role-to-assume: ${{ secrets.ECR_IMAGEPUSH_ROLE }} aws-region: us-east-1 - name: Login to Amazon ECR - if: ${{ matrix.registry == 'amazon-ecr' }} uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 with: registry-type: public - name: Build image id: build-image - uses: ./.github/actions/build-image + uses: ./.github/actions/build-push-image with: - platform: ${{ matrix.platform }} + platforms: ${{ env.PLATFORMS }} labels: ${{ needs.prepare.outputs.labels }} - image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}-${{ matrix.platform }} + tags: ${{ env.RHCC_IMAGE }},${{ env.GCR_IMAGE }},${{ env.ECR_IMAGE }},${{ env.DOCKER_IMAGE }} annotation: ${{ env.GOOGLE_MARKETPLACE_ANNOTATION }} - - name: Sign image for ${{matrix.registry}} - uses: ./.github/actions/sign-image - with: - image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}-${{ matrix.platform }}@${{steps.build-image.outputs.digest}} - signing-key: ${{ secrets.COSIGN_PRIVATE_KEY }} - signing-password: ${{ secrets.COSIGN_PASSWORD }} + outputs: + digest: ${{steps.build-image.outputs.digest}} - manifest: - name: Create Docker manifests + signing: + name: Sign the image index/manifests + Add SBOM environment: Release - needs: [prepare, build] + needs: [prepare, build-push] runs-on: ubuntu-latest permissions: id-token: write - outputs: - digest-rhcc: ${{ steps.store-digest.outputs.digest-rhcc }} - digest-gcr: ${{ steps.store-digest.outputs.digest-gcr }} - digest-dockerhub: ${{ steps.store-digest.outputs.digest-dockerhub }} - digest-amazon-ecr: ${{ steps.store-digest.outputs.digest-amazon-ecr }} strategy: matrix: registry: [gcr, dockerhub, rhcc, amazon-ecr] @@ -167,32 +140,17 @@ jobs: uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 with: registry-type: public - - name: Create manifests for ${{matrix.registry}} - uses: ./.github/actions/create-manifests - id: create-manifests - with: - version: ${{ needs.prepare.outputs.version }} - registry: ${{ matrix.url }} - repository: ${{ secrets[matrix.repository] }} - platforms: "amd64, arm64, ppc64le, s390x" - - name: Store digest - id: store-digest - shell: bash - run: | - registry="${{ matrix.registry }}" - digest="${{ steps.create-manifests.outputs.digest }}" - echo "digest-${registry}=${digest}" >> "$GITHUB_OUTPUT" - name: Sign images for ${{matrix.registry}} uses: ./.github/actions/sign-image with: - image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ steps.create-manifests.outputs.digest }} + image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ needs.build-push.outputs.digest }} signing-key: ${{ secrets.COSIGN_PRIVATE_KEY }} signing-password: ${{ secrets.COSIGN_PASSWORD }} - name: Create sbom for ${{matrix.registry}} id: sbom uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0 with: - image-ref: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ steps.create-manifests.outputs.digest }} + image-ref: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ needs.build-push.outputs.digest }} format: 'cyclonedx' output: 'result.json' skip-dirs: '/usr/share/dynatrace-operator/third_party_licenses' @@ -200,7 +158,7 @@ jobs: - name: Upload sbom to ${{matrix.registry}} uses: ./.github/actions/upload-sbom with: - image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ steps.create-manifests.outputs.digest }} + image: ${{ matrix.url }}/${{ secrets[matrix.repository] }}:${{ needs.prepare.outputs.version }}@${{ needs.build-push.outputs.digest }} sbom: 'result.json' signing-key: ${{ secrets.COSIGN_PRIVATE_KEY }} signing-password: ${{ secrets.COSIGN_PASSWORD }} @@ -211,7 +169,7 @@ jobs: runs-on: ubuntu-latest needs: [ prepare ] env: - IMAGE: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version_without_prefix }} + IMAGE: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version }} IMAGE_NO_PREFIX: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version_without_prefix }} steps: - name: Checkout @@ -229,17 +187,19 @@ jobs: - name: Build and push uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # 6.15.0 with: - platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x + platforms: ${{ env.DEPLOYER_PLATFORMS }} provenance: false + context: ./config/helm file: ./config/helm/Dockerfile push: true tags: ${{ env.IMAGE }},${{ env.IMAGE_NO_PREFIX }} - annotations: ${{ env.GOOGLE_MARKETPLACE_ANNOTATION }} + annotations: | + ${{ env.GOOGLE_MARKETPLACE_ANNOTATION }} run-preflight-rhcc: name: Run preflight for rhcc environment: Release - needs: [ prepare, build, manifest] + needs: [ prepare, build-push] runs-on: ubuntu-latest env: SCAN_REGISTRY: "quay.io" @@ -264,7 +224,7 @@ jobs: release: name: Create release - needs: [prepare, build, manifest, run-preflight-rhcc] + needs: [prepare, build-push, signing, run-preflight-rhcc] environment: Release permissions: contents: write @@ -292,10 +252,10 @@ jobs: run: | make manifests/crd/release CHART_VERSION="${VERSION_WITHOUT_PREFIX}" - make manifests/kubernetes/olm IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-amazon-ecr}}" - make manifests/kubernetes IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-amazon-ecr}}" - make manifests/openshift/olm IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-rhcc}}" - make manifests/openshift IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.manifest.outputs.digest-rhcc}}" + make manifests/kubernetes/olm IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.build-push.outputs.digest}}" + make manifests/kubernetes IMAGE="public.ecr.aws/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.build-push.outputs.digest}}" + make manifests/openshift/olm IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.build-push.outputs.digest}}" + make manifests/openshift IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator" TAG="${VERSION}@${{needs.build-push.outputs.digest}}" cp config/deploy/kubernetes/kubernetes.yaml config/deploy/kubernetes/gke-autopilot.yaml - name: Build helm packages uses: ./.github/actions/build-helm diff --git a/hack/build/ci/prepare-build-variables.sh b/hack/build/ci/prepare-build-variables.sh index 335f985976..283ee77ca8 100755 --- a/hack/build/ci/prepare-build-variables.sh +++ b/hack/build/ci/prepare-build-variables.sh @@ -20,11 +20,11 @@ createDockerImageLabels() { fi echo "build-date=$(date --iso-8601)" + echo "vcs-ref=${GITHUB_SHA}" } printBuildRelatedVariables() { echo "go_linker_args=${go_linker_args}" - echo "go_build_tags=${go_build_tags}" echo "docker_image_labels=${docker_image_labels}" echo "docker_image_tag=${docker_image_tag}" echo "docker_image_tag_without_prefix=${docker_image_tag#v}" @@ -34,5 +34,4 @@ printBuildRelatedVariables() { docker_image_tag=$(createDockerImageTag) docker_image_labels=$(createDockerImageLabels) go_linker_args=$(hack/build/create_go_linker_args.sh "${docker_image_tag}" "${GITHUB_SHA}") -go_build_tags=$(hack/build/create_go_build_tags.sh false) printBuildRelatedVariables >> "$GITHUB_OUTPUT" diff --git a/test/helpers/feature.go b/test/helpers/feature.go index eceba634ed..8bbe9f0421 100644 --- a/test/helpers/feature.go +++ b/test/helpers/feature.go @@ -1,3 +1,5 @@ +//go:build e2e + package helpers import ( diff --git a/test/helpers/kubeobjects/statefulset/get.go b/test/helpers/kubeobjects/statefulset/get.go index b955763097..4691491fb3 100644 --- a/test/helpers/kubeobjects/statefulset/get.go +++ b/test/helpers/kubeobjects/statefulset/get.go @@ -1,3 +1,5 @@ +//go:build e2e + package statefulset import ( diff --git a/test/helpers/platform/platform.go b/test/helpers/platform/platform.go index 9f3a96c2f2..5a4fab7a58 100644 --- a/test/helpers/platform/platform.go +++ b/test/helpers/platform/platform.go @@ -1,3 +1,5 @@ +//go:build e2e + package platform import ( diff --git a/test/helpers/registry/registry.go b/test/helpers/registry/registry.go index 659f4f954d..18ac5c51c0 100644 --- a/test/helpers/registry/registry.go +++ b/test/helpers/registry/registry.go @@ -1,3 +1,5 @@ +//go:build e2e + package registry import ( diff --git a/test/scenarios/filter.go b/test/scenarios/filter.go index e1955a49e1..2e342a63aa 100644 --- a/test/scenarios/filter.go +++ b/test/scenarios/filter.go @@ -1,3 +1,5 @@ +//go:build e2e + package scenarios import ( From 9060065c6bc54996401af8695181a1529ea467c7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 19:09:43 +0000 Subject: [PATCH 403/426] chore(deps): update registry.access.redhat.com/ubi9 docker tag to v9.5-1744101466 (release-1.5) (#4734) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index eaab6cbfc4..6e1b32883b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1742939100@sha256:414cfa255ea10eaef4528a26d5618eb67cf487b635ee20f8f14b9317bfd6a4be AS base -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1742918310@sha256:a1804302f6f53e04cc1c6b20bc2204d5c9ae6e5a664174b38fbeeb30f7983d4e AS dependency +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1744101466@sha256:ea57285741f007e83f2ee20423c20b0cbcce0b59cc3da027c671692cc7efe4dd AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency RUN dnf install --installroot /tmp/rootfs-dependency \ From 1b747742e9f586997891f9f2641cf7468f52e385 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 05:19:58 +0000 Subject: [PATCH 404/426] chore(deps): update registry.access.redhat.com/ubi9-micro docker tag to v9.5-1744118077 (release-1.5) (#4737) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6e1b32883b..e01d0b34ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -o ./build/_output/bin/dynatrace-operator ./cmd/ # platform is required, otherwise the copy command will copy the wrong architecture files, don't trust GitHub Actions linting warnings -FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1742939100@sha256:414cfa255ea10eaef4528a26d5618eb67cf487b635ee20f8f14b9317bfd6a4be AS base +FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-micro:9.5-1744118077@sha256:dca8bc186bb579f36414c6ad28f1dbeda33e5cf0bd5fc1c51430cc578e25f819 AS base FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9:9.5-1744101466@sha256:ea57285741f007e83f2ee20423c20b0cbcce0b59cc3da027c671692cc7efe4dd AS dependency RUN mkdir -p /tmp/rootfs-dependency COPY --from=base / /tmp/rootfs-dependency From f5a8640883005873ef7ca694208b0228956a5753 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Wed, 9 Apr 2025 14:20:09 +0200 Subject: [PATCH 405/426] Switch to UPD ports for StatsD & Jaeger thrift/compact (#4727) --- pkg/controllers/dynakube/otelc/service/reconciler.go | 6 +++--- pkg/controllers/dynakube/otelc/service/reconciler_test.go | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pkg/controllers/dynakube/otelc/service/reconciler.go b/pkg/controllers/dynakube/otelc/service/reconciler.go index 5b51c6ac10..7ee81e22cd 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler.go @@ -173,13 +173,13 @@ func buildServicePortList(protocols []otelcgen.Protocol) []corev1.ServicePort { corev1.ServicePort{ Name: jaegerThriftBinaryPortName, Port: jaegerThriftBinaryPort, - Protocol: corev1.ProtocolTCP, + Protocol: corev1.ProtocolUDP, TargetPort: intstr.FromInt32(jaegerThriftBinaryPort), }, corev1.ServicePort{ Name: jaegerThriftCompactPortName, Port: jaegerThriftCompactPort, - Protocol: corev1.ProtocolTCP, + Protocol: corev1.ProtocolUDP, TargetPort: intstr.FromInt32(jaegerThriftCompactPort), }, corev1.ServicePort{ @@ -193,7 +193,7 @@ func buildServicePortList(protocols []otelcgen.Protocol) []corev1.ServicePort { corev1.ServicePort{ Name: statsdPortName, Port: statsdPort, - Protocol: corev1.ProtocolTCP, + Protocol: corev1.ProtocolUDP, TargetPort: intstr.FromInt32(statsdPort), }) default: diff --git a/pkg/controllers/dynakube/otelc/service/reconciler_test.go b/pkg/controllers/dynakube/otelc/service/reconciler_test.go index f5c5826548..615e0cafb1 100644 --- a/pkg/controllers/dynakube/otelc/service/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/service/reconciler_test.go @@ -52,34 +52,42 @@ func TestService(t *testing.T) { assert.Equal(t, otlpGrpcPortName, service.Spec.Ports[0].Name) assert.Equal(t, int32(4317), service.Spec.Ports[0].Port) assert.Equal(t, int32(4317), service.Spec.Ports[0].TargetPort.IntVal) + assert.Equal(t, corev1.ProtocolTCP, service.Spec.Ports[0].Protocol) assert.Equal(t, otlpHttpPortName, service.Spec.Ports[1].Name) assert.Equal(t, int32(4318), service.Spec.Ports[1].Port) assert.Equal(t, int32(4318), service.Spec.Ports[1].TargetPort.IntVal) + assert.Equal(t, corev1.ProtocolTCP, service.Spec.Ports[1].Protocol) assert.Equal(t, jaegerGrpcPortName, service.Spec.Ports[2].Name) assert.Equal(t, int32(14250), service.Spec.Ports[2].Port) assert.Equal(t, int32(14250), service.Spec.Ports[2].TargetPort.IntVal) + assert.Equal(t, corev1.ProtocolTCP, service.Spec.Ports[2].Protocol) assert.Equal(t, jaegerThriftBinaryPortName, service.Spec.Ports[3].Name) assert.Equal(t, int32(6832), service.Spec.Ports[3].Port) assert.Equal(t, int32(6832), service.Spec.Ports[3].TargetPort.IntVal) + assert.Equal(t, corev1.ProtocolUDP, service.Spec.Ports[3].Protocol) assert.Equal(t, jaegerThriftCompactPortName, service.Spec.Ports[4].Name) assert.Equal(t, int32(6831), service.Spec.Ports[4].Port) assert.Equal(t, int32(6831), service.Spec.Ports[4].TargetPort.IntVal) + assert.Equal(t, corev1.ProtocolUDP, service.Spec.Ports[4].Protocol) assert.Equal(t, jaegerThriftHttpPortName, service.Spec.Ports[5].Name) assert.Equal(t, int32(14268), service.Spec.Ports[5].Port) assert.Equal(t, int32(14268), service.Spec.Ports[5].TargetPort.IntVal) + assert.Equal(t, corev1.ProtocolTCP, service.Spec.Ports[5].Protocol) assert.Equal(t, statsdPortName, service.Spec.Ports[6].Name) assert.Equal(t, int32(8125), service.Spec.Ports[6].Port) assert.Equal(t, int32(8125), service.Spec.Ports[6].TargetPort.IntVal) + assert.Equal(t, corev1.ProtocolUDP, service.Spec.Ports[6].Protocol) assert.Equal(t, zipkinPortName, service.Spec.Ports[7].Name) assert.Equal(t, int32(9411), service.Spec.Ports[7].Port) assert.Equal(t, int32(9411), service.Spec.Ports[7].TargetPort.IntVal) + assert.Equal(t, corev1.ProtocolTCP, service.Spec.Ports[7].Protocol) require.Len(t, dk.Status.Conditions, 1) assert.Equal(t, serviceConditionType, dk.Status.Conditions[0].Type) From 0bc830965c5886126dbdc28d55e305bc00c876f8 Mon Sep 17 00:00:00 2001 From: Andrii Soldatenko Date: Thu, 10 Apr 2025 12:47:51 +0200 Subject: [PATCH 406/426] Preserver sorting of keys inside pmc properties (#4744) --- pkg/clients/dynatrace/processmoduleconfig.go | 7 ++ .../dynatrace/processmoduleconfig_test.go | 72 +++++++++++++++++++ .../namespace/bootstrapperconfig/pmc.go | 2 + 3 files changed, 81 insertions(+) diff --git a/pkg/clients/dynatrace/processmoduleconfig.go b/pkg/clients/dynatrace/processmoduleconfig.go index c9d716dd42..f06f65bccf 100644 --- a/pkg/clients/dynatrace/processmoduleconfig.go +++ b/pkg/clients/dynatrace/processmoduleconfig.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "net/http" + "sort" "strconv" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube/oneagent" @@ -145,6 +146,12 @@ func (pmc ProcessModuleConfig) ToMap() ConfMap { return sections } +func (pmc *ProcessModuleConfig) SortPropertiesByKey() { + sort.Slice(pmc.Properties, func(i, j int) bool { + return pmc.Properties[i].Key < pmc.Properties[j].Key + }) +} + func (pmc ProcessModuleConfig) IsEmpty() bool { return len(pmc.Properties) == 0 } diff --git a/pkg/clients/dynatrace/processmoduleconfig_test.go b/pkg/clients/dynatrace/processmoduleconfig_test.go index 45080622fb..71794925c7 100644 --- a/pkg/clients/dynatrace/processmoduleconfig_test.go +++ b/pkg/clients/dynatrace/processmoduleconfig_test.go @@ -2,6 +2,7 @@ package dynatrace import ( "context" + "encoding/json" "fmt" "net/http" "testing" @@ -411,3 +412,74 @@ func TestProcessModuleConfig_AddNoProxy(t *testing.T) { }) } } + +func TestProcessModuleConfig_SortPropertiesByKey(t *testing.T) { + processModuleConfig := &ProcessModuleConfig{ + Revision: 0, + Properties: []ProcessModuleProperty{ + { + Section: "general", + Key: "baa", + Value: "random", + }, + { + Section: "general", + Key: "aaa", + Value: "random", + }, + { + Section: "general", + Key: "aba", + Value: "random", + }, + { + Section: "general", + Key: "bbb", + Value: "random", + }, + { + Section: "general", + Key: "aab", + Value: "random", + }, + }, + } + processModuleConfig.SortPropertiesByKey() + + expected := []ProcessModuleProperty{ + { + Section: "general", + Key: "aaa", + Value: "random", + }, + { + Section: "general", + Key: "aab", + Value: "random", + }, + { + Section: "general", + Key: "aba", + Value: "random", + }, + { + Section: "general", + Key: "baa", + Value: "random", + }, + { + Section: "general", + Key: "bbb", + Value: "random", + }, + } + assert.Equal(t, expected, processModuleConfig.Properties) + + expectedByteds, err := json.Marshal(expected) + require.NoError(t, err) + + actualBytes, err := json.Marshal(processModuleConfig.Properties) + require.NoError(t, err) + + assert.Equal(t, expectedByteds, actualBytes) +} diff --git a/pkg/injection/namespace/bootstrapperconfig/pmc.go b/pkg/injection/namespace/bootstrapperconfig/pmc.go index 31cca645de..2c8c81982b 100644 --- a/pkg/injection/namespace/bootstrapperconfig/pmc.go +++ b/pkg/injection/namespace/bootstrapperconfig/pmc.go @@ -57,6 +57,8 @@ func (s *SecretGenerator) preparePMC(ctx context.Context, dk dynakube.DynaKube) pmc.AddNoProxy(dnsEntry) } + pmc.SortPropertiesByKey() + marshaled, err := json.Marshal(pmc) if err != nil { log.Info("could not marshal process module config") From 3c713aa0618e7bb0099dc17adcbe18a21885d2de Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Thu, 10 Apr 2025 13:02:56 +0200 Subject: [PATCH 407/426] Use conditions properly in bootstrapper config reconciler (#4745) (#4746) --- .../dynakube/injection/reconciler.go | 2 +- .../processmoduleconfigsecret/conditions.go | 2 +- .../processmoduleconfigsecret/reconciler.go | 22 +++++----- .../reconciler_test.go | 12 +++--- .../bootstrapperconfig/bootstrapperconfig.go | 42 +++++++++++++------ .../bootstrapperconfig_test.go | 32 ++++++++++++-- .../bootstrapperconfig/conditions.go | 5 +++ .../namespace/bootstrapperconfig/endpoints.go | 7 ++++ .../namespace/bootstrapperconfig/pmc.go | 36 ++++++++++++---- .../namespace/bootstrapperconfig/replicate.go | 5 +++ 10 files changed, 123 insertions(+), 42 deletions(-) create mode 100644 pkg/injection/namespace/bootstrapperconfig/conditions.go diff --git a/pkg/controllers/dynakube/injection/reconciler.go b/pkg/controllers/dynakube/injection/reconciler.go index 02d8d27fb6..d908c7c32f 100644 --- a/pkg/controllers/dynakube/injection/reconciler.go +++ b/pkg/controllers/dynakube/injection/reconciler.go @@ -206,7 +206,7 @@ func (r *reconciler) cleanupOneAgentInjection(ctx context.Context) { return } - err = bootstrapperconfig.Cleanup(ctx, r.client, r.apiReader, namespaces, *r.dk) + err = bootstrapperconfig.Cleanup(ctx, r.client, r.apiReader, namespaces, r.dk) if err != nil { log.Error(err, "failed to clean-up bootstrapper code module injection init-secrets") } diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/conditions.go b/pkg/controllers/dynakube/processmoduleconfigsecret/conditions.go index 7ee97769ca..69babff381 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/conditions.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/conditions.go @@ -1,5 +1,5 @@ package processmoduleconfigsecret const ( - PMCConditionType = "ProcessModuleConfig" + ConditionType = "ProcessModuleConfig" ) diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go index 34c33d226e..200d6cf2f7 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler.go @@ -54,11 +54,11 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { r.dk.OneAgent().IsApplicationMonitoringMode()) if !(isNeeded) { - if meta.FindStatusCondition(*r.dk.Conditions(), PMCConditionType) == nil { + if meta.FindStatusCondition(*r.dk.Conditions(), ConditionType) == nil { return nil } - defer meta.RemoveStatusCondition(r.dk.Conditions(), PMCConditionType) + defer meta.RemoveStatusCondition(r.dk.Conditions(), ConditionType) err := r.deleteSecret(ctx, &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -83,12 +83,12 @@ func (r *Reconciler) Reconcile(ctx context.Context) error { } func (r *Reconciler) reconcileSecret(ctx context.Context) error { - if !conditions.IsOutdated(r.timeProvider, r.dk, PMCConditionType) { + if !conditions.IsOutdated(r.timeProvider, r.dk, ConditionType) { return nil } log.Info("processModuleConfig is outdated, updating") - conditions.SetSecretOutdated(r.dk.Conditions(), PMCConditionType, "secret is outdated, update in progress") + conditions.SetSecretOutdated(r.dk.Conditions(), ConditionType, "secret is outdated, update in progress") secret, err := r.prepareSecret(ctx) if err != nil { @@ -101,19 +101,19 @@ func (r *Reconciler) reconcileSecret(ctx context.Context) error { func (r *Reconciler) createOrUpdateSecret(ctx context.Context, secret *corev1.Secret) error { _, err := k8ssecret.Query(r.client, r.apiReader, log).WithOwner(r.dk).CreateOrUpdate(ctx, secret) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), ConditionType, err) return errors.Errorf("failed to create or update secret '%s': %v", secret.Name, err) } - conditions.SetSecretCreatedOrUpdated(r.dk.Conditions(), PMCConditionType, secret.Name) + conditions.SetSecretCreatedOrUpdated(r.dk.Conditions(), ConditionType, secret.Name) return nil } func (r *Reconciler) deleteSecret(ctx context.Context, secret *corev1.Secret) error { if err := k8ssecret.Query(r.client, r.apiReader, log).Delete(ctx, secret); err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), ConditionType, err) return err } @@ -124,7 +124,7 @@ func (r *Reconciler) deleteSecret(ctx context.Context, secret *corev1.Secret) er func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) { pmc, err := r.dtClient.GetProcessModuleConfig(ctx, 0) if err != nil { - conditions.SetDynatraceApiError(r.dk.Conditions(), PMCConditionType, err) + conditions.SetDynatraceApiError(r.dk.Conditions(), ConditionType, err) return nil, err } @@ -134,7 +134,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) Namespace: r.dk.Namespace, }, connectioninfo.TenantTokenKey, log) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), ConditionType, err) return nil, err } @@ -148,7 +148,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) if r.dk.NeedsOneAgentProxy() { proxy, err := r.dk.Proxy(ctx, r.apiReader) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), ConditionType, err) return nil, err } @@ -179,7 +179,7 @@ func (r *Reconciler) prepareSecret(ctx context.Context) (*corev1.Secret, error) k8ssecret.SetType(corev1.SecretTypeOpaque) if err != nil { - conditions.SetKubeApiError(r.dk.Conditions(), PMCConditionType, err) + conditions.SetKubeApiError(r.dk.Conditions(), ConditionType, err) return nil, err } diff --git a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go index 1aecd8c014..4e11f398de 100644 --- a/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go +++ b/pkg/controllers/dynakube/processmoduleconfigsecret/reconciler_test.go @@ -49,7 +49,7 @@ func TestReconcile(t *testing.T) { checkSecretForValue(t, mockK8sClient, "\"revision\":0") - condition := meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), ConditionType) oldTransitionTime := condition.LastTransitionTime require.NotNil(t, condition) require.NotEmpty(t, oldTransitionTime) @@ -63,7 +63,7 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) checkSecretForValue(t, mockK8sClient, "\"revision\":0") - condition = meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) + condition = meta.FindStatusCondition(*dk.Conditions(), ConditionType) require.NotNil(t, condition) require.Equal(t, condition.LastTransitionTime, oldTransitionTime) @@ -74,7 +74,7 @@ func TestReconcile(t *testing.T) { require.NoError(t, err) checkSecretForValue(t, mockK8sClient, "\"revision\":1") - condition = meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) + condition = meta.FindStatusCondition(*dk.Conditions(), ConditionType) require.NotNil(t, condition) require.Greater(t, condition.LastTransitionTime.Time, oldTransitionTime.Time) assert.Equal(t, conditions.SecretCreatedOrUpdatedReason, condition.Reason) @@ -83,7 +83,7 @@ func TestReconcile(t *testing.T) { t.Run("Only runs when required, and cleans up condition and pmc secret", func(t *testing.T) { dk := createDynakube(oneagent.Spec{ ClassicFullStack: &oneagent.HostInjectSpec{}}) - conditions.SetSecretCreated(dk.Conditions(), PMCConditionType, "this is a test") + conditions.SetSecretCreated(dk.Conditions(), ConditionType, "this is a test") secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -134,7 +134,7 @@ func TestReconcile(t *testing.T) { require.Error(t, err) require.Len(t, *dk.Conditions(), 1) - condition := meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), ConditionType) assert.Equal(t, conditions.KubeApiErrorReason, condition.Reason) assert.Equal(t, metav1.ConditionFalse, condition.Status) }) @@ -155,7 +155,7 @@ func TestReconcile(t *testing.T) { require.Error(t, err) require.Len(t, *dk.Conditions(), 1) - condition := meta.FindStatusCondition(*dk.Conditions(), PMCConditionType) + condition := meta.FindStatusCondition(*dk.Conditions(), ConditionType) assert.Equal(t, conditions.DynatraceApiErrorReason, condition.Reason) assert.Equal(t, metav1.ConditionFalse, condition.Status) }) diff --git a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go index c82f48a7d9..07451134fa 100644 --- a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go +++ b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig.go @@ -12,25 +12,30 @@ import ( dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + "github.com/Dynatrace/dynatrace-operator/pkg/util/timeprovider" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" "sigs.k8s.io/controller-runtime/pkg/client" ) // SecretGenerator manages the bootstrapper init secret generation for the user namespaces. type SecretGenerator struct { - client client.Client - dtClient dtclient.Client - apiReader client.Reader + client client.Client + dtClient dtclient.Client + apiReader client.Reader + timeProvider *timeprovider.Provider } func NewSecretGenerator(client client.Client, apiReader client.Reader, dtClient dtclient.Client) *SecretGenerator { return &SecretGenerator{ - client: client, - dtClient: dtClient, - apiReader: apiReader, + client: client, + dtClient: dtClient, + apiReader: apiReader, + timeProvider: timeprovider.New(), } } @@ -44,8 +49,15 @@ func (s *SecretGenerator) GenerateForDynakube(ctx context.Context, dk *dynakube. return errors.WithStack(err) } + err = s.createSourceForWebhook(ctx, dk, data) + if err != nil { + return err + } + nsList, err := mapper.GetNamespacesForDynakube(ctx, s.apiReader, dk.Name) if err != nil { + conditions.SetKubeApiError(dk.Conditions(), ConditionType, err) + return errors.WithStack(err) } @@ -53,25 +65,27 @@ func (s *SecretGenerator) GenerateForDynakube(ctx context.Context, dk *dynakube. secret, err := k8ssecret.BuildForNamespace(consts.BootstrapperInitSecretName, "", data, k8ssecret.SetLabels(coreLabels.BuildLabels())) if err != nil { + conditions.SetSecretGenFailed(dk.Conditions(), ConditionType, err) + return err } err = k8ssecret.Query(s.client, s.apiReader, log).CreateOrUpdateForNamespaces(ctx, secret, nsList) if err != nil { - return err - } + conditions.SetKubeApiError(dk.Conditions(), ConditionType, err) - err = s.createSourceForWebhook(ctx, dk, data) - if err != nil { return err } log.Info("done updating init secrets") + conditions.SetSecretCreatedOrUpdated(dk.Conditions(), ConditionType, GetSourceSecretName(dk.Name)) return nil } -func Cleanup(ctx context.Context, client client.Client, apiReader client.Reader, namespaces []corev1.Namespace, dk dynakube.DynaKube) error { +func Cleanup(ctx context.Context, client client.Client, apiReader client.Reader, namespaces []corev1.Namespace, dk *dynakube.DynaKube) error { + defer meta.RemoveStatusCondition(dk.Conditions(), ConditionType) + nsList := make([]string, 0, len(namespaces)) for _, ns := range namespaces { nsList = append(nsList, ns.Name) @@ -89,15 +103,19 @@ func Cleanup(ctx context.Context, client client.Client, apiReader client.Reader, func (s *SecretGenerator) generate(ctx context.Context, dk *dynakube.DynaKube) (map[string][]byte, error) { agCerts, err := dk.ActiveGateTLSCert(ctx, s.apiReader) if err != nil { + conditions.SetKubeApiError(dk.Conditions(), ConditionType, err) + return nil, errors.WithStack(err) } trustedCAs, err := dk.TrustedCAs(ctx, s.apiReader) if err != nil { + conditions.SetKubeApiError(dk.Conditions(), ConditionType, err) + return nil, errors.WithStack(err) } - pmcSecret, err := s.preparePMC(ctx, *dk) + pmcSecret, err := s.preparePMC(ctx, dk) if err != nil { return nil, errors.WithStack(err) } diff --git a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go index 438d9b6ce0..f9117d7c0f 100644 --- a/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go +++ b/pkg/injection/namespace/bootstrapperconfig/bootstrapperconfig_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -104,6 +105,10 @@ func TestGenerateForDynakube(t *testing.T) { require.Equal(t, GetSourceSecretName(dk.Name), sourceSecret.Name) assert.Equal(t, secret.Data, sourceSecret.Data) + + c := meta.FindStatusCondition(*dk.Conditions(), ConditionType) + require.NotNil(t, c) + assert.Equal(t, metav1.ConditionTrue, c.Status) }) t.Run("succcessfully generate secret with fields for dynakube", func(t *testing.T) { dk := &dynakube.DynaKube{ @@ -189,6 +194,10 @@ func TestGenerateForDynakube(t *testing.T) { require.Equal(t, GetSourceSecretName(dk.Name), sourceSecret.Name) assert.Equal(t, secret.Data, sourceSecret.Data) + + c := meta.FindStatusCondition(*dk.Conditions(), ConditionType) + require.NotNil(t, c) + assert.Equal(t, metav1.ConditionTrue, c.Status) }) t.Run("update secret with preexisting secret + fields", func(t *testing.T) { dk := &dynakube.DynaKube{ @@ -278,9 +287,13 @@ func TestGenerateForDynakube(t *testing.T) { require.Equal(t, GetSourceSecretName(dk.Name), sourceSecret.Name) assert.Equal(t, secret.Data, sourceSecret.Data) + + c := meta.FindStatusCondition(*dk.Conditions(), ConditionType) + require.NotNil(t, c) + assert.Equal(t, metav1.ConditionTrue, c.Status) }) t.Run("fail while generating secret for dynakube", func(t *testing.T) { - dynakube := &dynakube.DynaKube{ + dk := &dynakube.DynaKube{ ObjectMeta: metav1.ObjectMeta{ Name: testDynakube, Namespace: testNamespaceDynatrace, @@ -291,7 +304,7 @@ func TestGenerateForDynakube(t *testing.T) { } clt := fake.NewClientWithIndex( - dynakube, + dk, clientInjectedNamespace(testNamespace, testDynakube), clientSecret(testDynakube, testNamespaceDynatrace, map[string][]byte{ dtclient.ApiToken: []byte(testAPIToken), @@ -304,8 +317,12 @@ func TestGenerateForDynakube(t *testing.T) { mockDTClient.On("GetProcessModuleConfig", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("uint")).Return(&dtclient.ProcessModuleConfig{}, nil) secretGenerator := NewSecretGenerator(clt, clt, mockDTClient) - err := secretGenerator.GenerateForDynakube(context.Background(), dynakube) + err := secretGenerator.GenerateForDynakube(context.Background(), dk) require.Error(t, err) + + c := meta.FindStatusCondition(*dk.Conditions(), ConditionType) + require.NotNil(t, c) + assert.Equal(t, metav1.ConditionFalse, c.Status) }) } @@ -318,6 +335,12 @@ func TestCleanup(t *testing.T) { Spec: dynakube.DynaKubeSpec{ APIURL: testApiUrl, }, + Status: dynakube.DynaKubeStatus{ + Conditions: []metav1.Condition{ + {Type: ConditionType}, + {Type: "other"}, + }, + }, } clt := fake.NewClientWithIndex( @@ -353,7 +376,7 @@ func TestCleanup(t *testing.T) { require.NotEmpty(t, secretNS2) assert.Equal(t, consts.BootstrapperInitSecretName, secretNS2.Name) - err = Cleanup(context.Background(), clt, clt, namespaces, *dk) + err = Cleanup(context.Background(), clt, clt, namespaces, dk) require.NoError(t, err) var deleted corev1.Secret @@ -368,6 +391,7 @@ func TestCleanup(t *testing.T) { err = clt.Get(context.Background(), client.ObjectKey{Name: GetSourceSecretName(dk.Name), Namespace: dk.Namespace}, &deleted) require.Error(t, err) assert.True(t, errors.IsNotFound(err)) + require.Nil(t, meta.FindStatusCondition(*dk.Conditions(), ConditionType)) } func clientSecret(secretName string, namespaceName string, data map[string][]byte) *corev1.Secret { diff --git a/pkg/injection/namespace/bootstrapperconfig/conditions.go b/pkg/injection/namespace/bootstrapperconfig/conditions.go new file mode 100644 index 0000000000..9d4d62f3cd --- /dev/null +++ b/pkg/injection/namespace/bootstrapperconfig/conditions.go @@ -0,0 +1,5 @@ +package bootstrapperconfig + +const ( + ConditionType = "BootstrapperConfig" +) diff --git a/pkg/injection/namespace/bootstrapperconfig/endpoints.go b/pkg/injection/namespace/bootstrapperconfig/endpoints.go index ae76fefbb2..266d7b623b 100644 --- a/pkg/injection/namespace/bootstrapperconfig/endpoints.go +++ b/pkg/injection/namespace/bootstrapperconfig/endpoints.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" dtclient "github.com/Dynatrace/dynatrace-operator/pkg/clients/dynatrace" dtingestendpoint "github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/ingestendpoint" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" "github.com/pkg/errors" "sigs.k8s.io/controller-runtime/pkg/client" @@ -23,10 +24,14 @@ func (s *SecretGenerator) prepareEndpoints(ctx context.Context, dk *dynakube.Dyn if dk.MetadataEnrichmentEnabled() { if _, err := endpointPropertiesBuilder.WriteString(fmt.Sprintf("%s=%s\n", dtingestendpoint.MetricsUrlSecretField, fields[dtingestendpoint.MetricsUrlSecretField])); err != nil { + conditions.SetSecretGenFailed(dk.Conditions(), ConditionType, err) + return "", errors.WithStack(err) } if _, err := endpointPropertiesBuilder.WriteString(fmt.Sprintf("%s=%s\n", dtingestendpoint.MetricsTokenSecretField, fields[dtingestendpoint.MetricsTokenSecretField])); err != nil { + conditions.SetSecretGenFailed(dk.Conditions(), ConditionType, err) + return "", errors.WithStack(err) } } @@ -39,6 +44,8 @@ func (s *SecretGenerator) prepareFieldsForEndpoints(ctx context.Context, dk *dyn tokens, err := k8ssecret.Query(s.client, s.apiReader, log).Get(ctx, client.ObjectKey{Name: dk.Tokens(), Namespace: dk.Namespace}) if err != nil { + conditions.SetKubeApiError(dk.Conditions(), ConditionType, err) + return nil, errors.WithMessage(err, "failed to query tokens") } diff --git a/pkg/injection/namespace/bootstrapperconfig/pmc.go b/pkg/injection/namespace/bootstrapperconfig/pmc.go index 2c8c81982b..a9fadf28ca 100644 --- a/pkg/injection/namespace/bootstrapperconfig/pmc.go +++ b/pkg/injection/namespace/bootstrapperconfig/pmc.go @@ -4,19 +4,37 @@ import ( "context" "encoding/json" + "github.com/Dynatrace/dynatrace-bootstrapper/pkg/configure/oneagent/pmc" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/activegate/capability" "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/connectioninfo" - "github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/processmoduleconfigsecret" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" + k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" ) -func (s *SecretGenerator) preparePMC(ctx context.Context, dk dynakube.DynaKube) ([]byte, error) { +func (s *SecretGenerator) preparePMC(ctx context.Context, dk *dynakube.DynaKube) ([]byte, error) { + if !conditions.IsOutdated(s.timeProvider, dk, ConditionType) { + log.Info("skipping Dynatrace API call, trying to get ruxitagentproc content from source secret") + + source, err := getSecretFromSource(ctx, *dk, k8ssecret.Query(s.client, s.apiReader, log), dk.Namespace) + if err != nil && !k8serrors.IsNotFound(err) { + conditions.SetKubeApiError(dk.Conditions(), ConditionType, err) + + return nil, err + } else if err == nil && source.Data[pmc.InputFileName] != nil { + return source.Data[pmc.InputFileName], nil + } + } + + log.Debug("calling the Dynatrace API for ruxitagentproc content") + + conditions.SetSecretOutdated(dk.Conditions(), ConditionType, "secret is outdated, update in progress") + pmc, err := s.dtClient.GetProcessModuleConfig(ctx, 0) if err != nil { - conditions.SetDynatraceApiError(dk.Conditions(), processmoduleconfigsecret.PMCConditionType, err) + conditions.SetDynatraceApiError(dk.Conditions(), ConditionType, err) return nil, err } @@ -26,7 +44,7 @@ func (s *SecretGenerator) preparePMC(ctx context.Context, dk dynakube.DynaKube) Namespace: dk.Namespace, }, connectioninfo.TenantTokenKey, log) if err != nil { - conditions.SetKubeApiError(dk.Conditions(), processmoduleconfigsecret.PMCConditionType, err) + conditions.SetKubeApiError(dk.Conditions(), ConditionType, err) return nil, err } @@ -38,16 +56,18 @@ func (s *SecretGenerator) preparePMC(ctx context.Context, dk dynakube.DynaKube) AddProxy("") if dk.NeedsOneAgentProxy() { + log.Debug("proxy is needed") + proxy, err := dk.Proxy(ctx, s.apiReader) if err != nil { - conditions.SetKubeApiError(dk.Conditions(), processmoduleconfigsecret.PMCConditionType, err) + conditions.SetKubeApiError(dk.Conditions(), ConditionType, err) return nil, err } pmc.AddProxy(proxy) - multiCap := capability.NewMultiCapability(&dk) + multiCap := capability.NewMultiCapability(dk) dnsEntry := capability.BuildDNSEntryPointWithoutEnvVars(dk.Name, dk.Namespace, multiCap) if dk.FeatureNoProxy() != "" { @@ -61,10 +81,12 @@ func (s *SecretGenerator) preparePMC(ctx context.Context, dk dynakube.DynaKube) marshaled, err := json.Marshal(pmc) if err != nil { + conditions.SetSecretGenFailed(dk.Conditions(), ConditionType, err) + log.Info("could not marshal process module config") return nil, err } - return marshaled, err + return marshaled, nil } diff --git a/pkg/injection/namespace/bootstrapperconfig/replicate.go b/pkg/injection/namespace/bootstrapperconfig/replicate.go index 85f2ffa938..c226c855b9 100644 --- a/pkg/injection/namespace/bootstrapperconfig/replicate.go +++ b/pkg/injection/namespace/bootstrapperconfig/replicate.go @@ -6,6 +6,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta4/dynakube" "github.com/Dynatrace/dynatrace-operator/pkg/consts" + "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" k8slabels "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/labels" k8ssecret "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/secret" corev1 "k8s.io/api/core/v1" @@ -45,11 +46,15 @@ func (s *SecretGenerator) createSourceForWebhook(ctx context.Context, dk *dynaku secret, err := k8ssecret.BuildForNamespace(GetSourceSecretName(dk.Name), dk.Namespace, data, k8ssecret.SetLabels(coreLabels.BuildLabels())) if err != nil { + conditions.SetSecretGenFailed(dk.Conditions(), ConditionType, err) + return err } _, err = k8ssecret.Query(s.client, s.apiReader, log).WithOwner(dk).CreateOrUpdate(ctx, secret) if err != nil { + conditions.SetKubeApiError(dk.Conditions(), ConditionType, err) + return err } From 3a56910d0586b135f8cba97170ce71841ccb3ed2 Mon Sep 17 00:00:00 2001 From: Stefan Hauth Date: Thu, 10 Apr 2025 15:21:24 +0200 Subject: [PATCH 408/426] Fix ECR image URL --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3c911eeb7a..9fbe0eb3e4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -38,7 +38,7 @@ jobs: needs: [prepare] env: GCR_IMAGE: gcr.io/${{ secrets.GCR_REPOSITORY }}:${{ needs.prepare.outputs.version }} - ECR_IMAGE: public.ecr.aws.io/${{ secrets.ECR_REPOSITORY }}:${{ needs.prepare.outputs.version }} + ECR_IMAGE: public.ecr.aws/${{ secrets.ECR_REPOSITORY }}:${{ needs.prepare.outputs.version }} RHCC_IMAGE: quay.io/${{ secrets.RHCC_REPOSITORY }}:${{ needs.prepare.outputs.version }} DOCKER_IMAGE: docker.io/${{ secrets.DOCKERHUB_REPOSITORY }}:${{ needs.prepare.outputs.version }} steps: From be183d7052e13238b75229b89df56679a0790304 Mon Sep 17 00:00:00 2001 From: Michael Eibensteiner <68381547+meibensteiner@users.noreply.github.com> Date: Thu, 10 Apr 2025 16:25:16 +0200 Subject: [PATCH 409/426] Add built-in GKE Autopilot Allowlistsynchronizer (#4740) Cherrypick (#4748) --- .../operator/allowlistsynchronizer.yaml | 23 +++++++++++++++++++ .../chart/default/templates/_platform.tpl | 9 ++++++++ .../serviceaccount-activegate_test.yaml | 2 +- .../serviceaccount-edgeconnect_test.yaml | 2 +- ...lusterrole-extensions-prometheus_test.yaml | 2 +- .../role-extensions-controller_test.yaml | 2 +- ...iceaccount-extensions-controller_test.yaml | 2 +- ...lusterrole-kubernetes-monitoring_test.yaml | 2 +- ...iceaccount-node-config-collector_test.yaml | 2 +- .../clusterrole-logmonitoring_test.yaml | 2 +- .../serviceaccount-logmonitoring_test.yaml | 2 +- .../oneagent/clusterrole-oneagent_test.yaml | 2 +- .../serviceaccount-oneagent_test.yaml | 2 +- .../clusterrole-telemetry-endpoints_test.yaml | 2 +- ...eaccount-opentelemetry-collector_test.yaml | 2 +- .../operator/allowlistsynchronizer_test.yaml | 20 ++++++++++++++++ .../poddisruptionbudget-webhook_test.yaml | 2 +- 17 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 config/helm/chart/default/templates/Common/operator/allowlistsynchronizer.yaml create mode 100644 config/helm/chart/default/tests/Common/operator/allowlistsynchronizer_test.yaml diff --git a/config/helm/chart/default/templates/Common/operator/allowlistsynchronizer.yaml b/config/helm/chart/default/templates/Common/operator/allowlistsynchronizer.yaml new file mode 100644 index 0000000000..523cd7fb1b --- /dev/null +++ b/config/helm/chart/default/templates/Common/operator/allowlistsynchronizer.yaml @@ -0,0 +1,23 @@ +{{ if eq (include "dynatrace-operator.needAutopilotAllowlisting" .) "true" }} +# Copyright 2021 Dynatrace LLC + +# 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. +apiVersion: auto.gke.io/v1 +kind: AllowlistSynchronizer +metadata: + name: dynatrace-operator +spec: + allowlistPaths: + - Dynatrace/csidriver/{{ .Chart.AppVersion }}/* + - Dynatrace/logmonitoring/{{ .Chart.AppVersion }}/* +{{- end -}} diff --git a/config/helm/chart/default/templates/_platform.tpl b/config/helm/chart/default/templates/_platform.tpl index 2080d801e0..ef1130f92b 100644 --- a/config/helm/chart/default/templates/_platform.tpl +++ b/config/helm/chart/default/templates/_platform.tpl @@ -25,6 +25,15 @@ Auto-detect the platform (if not set), according to the available APIVersions {{- end -}} {{- end }} +{{/* +Auto-detect whether or not we need allowlisting for logagent and csi-driver +*/}} +{{- define "dynatrace-operator.needAutopilotAllowlisting" -}} + {{- if .Capabilities.APIVersions.Has "auto.gke.io/v1/AllowlistSynchronizer" }} + {{- printf "true" -}} + {{- end -}} +{{- end }} + {{/* Set install source how the Operator was installed */}} diff --git a/config/helm/chart/default/tests/Common/activegate/serviceaccount-activegate_test.yaml b/config/helm/chart/default/tests/Common/activegate/serviceaccount-activegate_test.yaml index 0d1b0d9dde..d926a9996b 100644 --- a/config/helm/chart/default/tests/Common/activegate/serviceaccount-activegate_test.yaml +++ b/config/helm/chart/default/tests/Common/activegate/serviceaccount-activegate_test.yaml @@ -18,4 +18,4 @@ tests: rbac.activeGate.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/edgeconnect/serviceaccount-edgeconnect_test.yaml b/config/helm/chart/default/tests/Common/edgeconnect/serviceaccount-edgeconnect_test.yaml index 8ec19702f6..becef5cba7 100644 --- a/config/helm/chart/default/tests/Common/edgeconnect/serviceaccount-edgeconnect_test.yaml +++ b/config/helm/chart/default/tests/Common/edgeconnect/serviceaccount-edgeconnect_test.yaml @@ -18,4 +18,4 @@ tests: rbac.edgeConnect.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/extensions/clusterrole-extensions-prometheus_test.yaml b/config/helm/chart/default/tests/Common/extensions/clusterrole-extensions-prometheus_test.yaml index 419927817b..988393fbe4 100644 --- a/config/helm/chart/default/tests/Common/extensions/clusterrole-extensions-prometheus_test.yaml +++ b/config/helm/chart/default/tests/Common/extensions/clusterrole-extensions-prometheus_test.yaml @@ -96,4 +96,4 @@ tests: rbac.extensions.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/extensions/role-extensions-controller_test.yaml b/config/helm/chart/default/tests/Common/extensions/role-extensions-controller_test.yaml index 9aef6a58b3..c999ea4e57 100644 --- a/config/helm/chart/default/tests/Common/extensions/role-extensions-controller_test.yaml +++ b/config/helm/chart/default/tests/Common/extensions/role-extensions-controller_test.yaml @@ -48,4 +48,4 @@ tests: rbac.extensions.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/extensions/serviceaccount-extensions-controller_test.yaml b/config/helm/chart/default/tests/Common/extensions/serviceaccount-extensions-controller_test.yaml index 9b0ddcb024..4eacee4b39 100644 --- a/config/helm/chart/default/tests/Common/extensions/serviceaccount-extensions-controller_test.yaml +++ b/config/helm/chart/default/tests/Common/extensions/serviceaccount-extensions-controller_test.yaml @@ -33,4 +33,4 @@ tests: rbac.extensions.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/kspm/clusterrole-kubernetes-monitoring_test.yaml b/config/helm/chart/default/tests/Common/kspm/clusterrole-kubernetes-monitoring_test.yaml index e345bb8268..75264e7ea0 100644 --- a/config/helm/chart/default/tests/Common/kspm/clusterrole-kubernetes-monitoring_test.yaml +++ b/config/helm/chart/default/tests/Common/kspm/clusterrole-kubernetes-monitoring_test.yaml @@ -41,4 +41,4 @@ tests: rbac.kspm.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/kspm/serviceaccount-node-config-collector_test.yaml b/config/helm/chart/default/tests/Common/kspm/serviceaccount-node-config-collector_test.yaml index 460d0aba33..4c79e0728f 100644 --- a/config/helm/chart/default/tests/Common/kspm/serviceaccount-node-config-collector_test.yaml +++ b/config/helm/chart/default/tests/Common/kspm/serviceaccount-node-config-collector_test.yaml @@ -43,4 +43,4 @@ tests: rbac.kspm.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/logmonitoring/clusterrole-logmonitoring_test.yaml b/config/helm/chart/default/tests/Common/logmonitoring/clusterrole-logmonitoring_test.yaml index c156a00522..0260050854 100644 --- a/config/helm/chart/default/tests/Common/logmonitoring/clusterrole-logmonitoring_test.yaml +++ b/config/helm/chart/default/tests/Common/logmonitoring/clusterrole-logmonitoring_test.yaml @@ -58,4 +58,4 @@ tests: rbac.oneagent.create: true asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/logmonitoring/serviceaccount-logmonitoring_test.yaml b/config/helm/chart/default/tests/Common/logmonitoring/serviceaccount-logmonitoring_test.yaml index 9ed5a243aa..9aaf740a57 100644 --- a/config/helm/chart/default/tests/Common/logmonitoring/serviceaccount-logmonitoring_test.yaml +++ b/config/helm/chart/default/tests/Common/logmonitoring/serviceaccount-logmonitoring_test.yaml @@ -31,4 +31,4 @@ tests: rbac.logMonitoring.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/oneagent/clusterrole-oneagent_test.yaml b/config/helm/chart/default/tests/Common/oneagent/clusterrole-oneagent_test.yaml index 990a9f000a..cf55fb5e94 100644 --- a/config/helm/chart/default/tests/Common/oneagent/clusterrole-oneagent_test.yaml +++ b/config/helm/chart/default/tests/Common/oneagent/clusterrole-oneagent_test.yaml @@ -47,4 +47,4 @@ tests: rbac.oneAgent.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/oneagent/serviceaccount-oneagent_test.yaml b/config/helm/chart/default/tests/Common/oneagent/serviceaccount-oneagent_test.yaml index ca37b2a6c9..71c03aa60f 100644 --- a/config/helm/chart/default/tests/Common/oneagent/serviceaccount-oneagent_test.yaml +++ b/config/helm/chart/default/tests/Common/oneagent/serviceaccount-oneagent_test.yaml @@ -42,7 +42,7 @@ tests: rbac.oneAgent.create: false asserts: - hasDocuments: - count: 0 + count: 0 - it: should have automountServiceAccountToken set to TRUE, incase of log-monitoring is available set: rbac.oneAgent.create: true diff --git a/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml b/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml index 8783e55215..b8ec64d51d 100644 --- a/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml +++ b/config/helm/chart/default/tests/Common/opentelemetry-collector/clusterrole-telemetry-endpoints_test.yaml @@ -82,4 +82,4 @@ tests: rbac.telemetryIngest.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml b/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml index df2491dc47..b5591fc128 100644 --- a/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml +++ b/config/helm/chart/default/tests/Common/opentelemetry-collector/serviceaccount-opentelemetry-collector_test.yaml @@ -23,4 +23,4 @@ tests: rbac.telemetryIngest.create: false asserts: - hasDocuments: - count: 0 + count: 0 diff --git a/config/helm/chart/default/tests/Common/operator/allowlistsynchronizer_test.yaml b/config/helm/chart/default/tests/Common/operator/allowlistsynchronizer_test.yaml new file mode 100644 index 0000000000..6d81944beb --- /dev/null +++ b/config/helm/chart/default/tests/Common/operator/allowlistsynchronizer_test.yaml @@ -0,0 +1,20 @@ +suite: test allowlistsynchronizer for GKE-Autopilot +templates: + - Common/operator/allowlistsynchronizer.yaml +tests: + - it: shouldn't exist by default + asserts: + - hasDocuments: + count: 0 + - it: should exist on GKE-Autopilot + capabilities: + apiVersions: + - auto.gke.io/v1/AllowlistSynchronizer + asserts: + - isKind: + of: AllowlistSynchronizer + - isAPIVersion: + of: auto.gke.io/v1 + - equal: + path: metadata.name + value: dynatrace-operator diff --git a/config/helm/chart/default/tests/Common/webhook/poddisruptionbudget-webhook_test.yaml b/config/helm/chart/default/tests/Common/webhook/poddisruptionbudget-webhook_test.yaml index 7dba9ec551..99cda458ed 100644 --- a/config/helm/chart/default/tests/Common/webhook/poddisruptionbudget-webhook_test.yaml +++ b/config/helm/chart/default/tests/Common/webhook/poddisruptionbudget-webhook_test.yaml @@ -19,4 +19,4 @@ tests: webhook.highAvailability: false asserts: - hasDocuments: - count: 0 + count: 0 From 5334f41545e184a13d5179c90eb02ac186e7607c Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Mon, 14 Apr 2025 12:02:11 +0200 Subject: [PATCH 410/426] Rename Helm switch kubernetes monitoring full (#4749) --- .../clusterrole-kubernetes-monitoring-full.yaml | 2 +- .../clusterrole-kubernetes-monitoring-full_test.yaml | 6 +++--- config/helm/chart/default/values.yaml | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full.yaml b/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full.yaml index dc24b8dd5d..06c095665b 100644 --- a/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full.yaml +++ b/config/helm/chart/default/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.rbac.kubernetesMonitoringFull.create .Values.rbac.activeGate.create }} +{{- if and ((.Values.preview).fullObjectCoverage).enabled .Values.rbac.activeGate.create }} # Copyright 2021 Dynatrace LLC # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full_test.yaml b/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full_test.yaml index 9e3cc8d0c9..d813fbcec6 100644 --- a/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full_test.yaml +++ b/config/helm/chart/default/tests/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring-full_test.yaml @@ -6,7 +6,7 @@ tests: documentIndex: 0 set: rbac.activeGate.create: true - rbac.kubernetesMonitoringFull.create.create: true + preview.fullObjectCoverage.enabled.create: true asserts: - isKind: @@ -44,7 +44,7 @@ tests: set: platform: openshift rbac.activeGate.create: true - rbac.kubernetesMonitoringFull.create.create: true + preview.fullObjectCoverage.enabled.create: true asserts: - isKind: of: ClusterRole @@ -67,7 +67,7 @@ tests: - use - it: shouldn't exist if activeGate is turned off set: - rbac.kubernetesMonitoringFull.create: true + preview.fullObjectCoverage.enabled: true rbac.activeGate.create: false asserts: - hasDocuments: diff --git a/config/helm/chart/default/values.yaml b/config/helm/chart/default/values.yaml index cbb41262ac..c6bf800c9d 100644 --- a/config/helm/chart/default/values.yaml +++ b/config/helm/chart/default/values.yaml @@ -220,7 +220,4 @@ rbac: kspm: create: true annotations: {} - kubernetesMonitoringFull: - create: false - annotations: {} supportability: true From e924637cddb948fe5624a4da666116e5ab7090ef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 10:51:04 +0000 Subject: [PATCH 411/426] fix(deps): update module istio.io/api to v1.25.2 (release-1.5) (#4765) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bc7c27a6bf..e4ab60f7de 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( golang.org/x/sys v0.31.0 google.golang.org/grpc v1.71.1 gopkg.in/yaml.v3 v3.0.1 - istio.io/api v1.25.1 + istio.io/api v1.25.2 istio.io/client-go v1.25.1 k8s.io/api v0.32.3 k8s.io/apiextensions-apiserver v0.32.3 diff --git a/go.sum b/go.sum index f8667a2634..5829dd51dd 100644 --- a/go.sum +++ b/go.sum @@ -379,8 +379,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -istio.io/api v1.25.1 h1:l3JS6Rh4bH+6ox84hRvtsJsr7gMJLsoJG2BQZGbXRyc= -istio.io/api v1.25.1/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= +istio.io/api v1.25.2 h1:FCRQy7iaTreKJdLemlQ1vRJEsf1soCHoTAuSf68w5I8= +istio.io/api v1.25.2/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= istio.io/client-go v1.25.1 h1:1Asibz5v2NBA6w4Sqa85NS7TkpEolZcPKAT5oUAXWi8= istio.io/client-go v1.25.1/go.mod h1:Vap9OyHJMvvDegYoZczcNybS4wbPaTk+4bZcWMb8+vE= k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= From b6ac2d1df855bd0e8d9ee845fed16fd37d65d8ea Mon Sep 17 00:00:00 2001 From: Stefan Hauth Date: Tue, 15 Apr 2025 13:30:42 +0200 Subject: [PATCH 412/426] Make assert more verbose. --- test/features/applicationmonitoring/label_version_detection.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/features/applicationmonitoring/label_version_detection.go b/test/features/applicationmonitoring/label_version_detection.go index 19ea969613..7875538514 100644 --- a/test/features/applicationmonitoring/label_version_detection.go +++ b/test/features/applicationmonitoring/label_version_detection.go @@ -217,7 +217,7 @@ func assertValue(ctx context.Context, t *testing.T, resource *resources.Resource require.NoError(t, err) stdOut := strings.TrimSpace(executionResult.StdOut.String()) - assert.Zero(t, executionResult.StdErr.Len()) + assert.Equal(t, "", executionResult.StdErr.String()) assert.Equal(t, expectedValue, stdOut, "%s:%s pod - %s variable has invalid value", podItem.Namespace, podItem.Name, variableName) } From 4db0ee0dc88838267639a14aeb224f773695ef16 Mon Sep 17 00:00:00 2001 From: Michael Eibensteiner <68381547+meibensteiner@users.noreply.github.com> Date: Tue, 15 Apr 2025 17:24:38 +0200 Subject: [PATCH 413/426] Add minimal security footprint allowlist (#4766) (#4768) Co-authored-by: Stefan Hauth --- .../templates/Common/operator/allowlistsynchronizer.yaml | 3 +++ test/features/applicationmonitoring/label_version_detection.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config/helm/chart/default/templates/Common/operator/allowlistsynchronizer.yaml b/config/helm/chart/default/templates/Common/operator/allowlistsynchronizer.yaml index 523cd7fb1b..4c8e0cffe7 100644 --- a/config/helm/chart/default/templates/Common/operator/allowlistsynchronizer.yaml +++ b/config/helm/chart/default/templates/Common/operator/allowlistsynchronizer.yaml @@ -16,8 +16,11 @@ apiVersion: auto.gke.io/v1 kind: AllowlistSynchronizer metadata: name: dynatrace-operator + annotations: + "helm.sh/hook": pre-install, post-delete, pre-upgrade, pre-rollback spec: allowlistPaths: - Dynatrace/csidriver/{{ .Chart.AppVersion }}/* - Dynatrace/logmonitoring/{{ .Chart.AppVersion }}/* + - Dynatrace/csijob/{{ .Chart.AppVersion }}/* {{- end -}} diff --git a/test/features/applicationmonitoring/label_version_detection.go b/test/features/applicationmonitoring/label_version_detection.go index 7875538514..c8d0c85612 100644 --- a/test/features/applicationmonitoring/label_version_detection.go +++ b/test/features/applicationmonitoring/label_version_detection.go @@ -217,7 +217,7 @@ func assertValue(ctx context.Context, t *testing.T, resource *resources.Resource require.NoError(t, err) stdOut := strings.TrimSpace(executionResult.StdOut.String()) - assert.Equal(t, "", executionResult.StdErr.String()) + assert.Empty(t, executionResult.StdErr.String()) assert.Equal(t, expectedValue, stdOut, "%s:%s pod - %s variable has invalid value", podItem.Namespace, podItem.Name, variableName) } From a7b22e011ad36c4fc6f1b1883d1cffc76121ba59 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 18:17:00 +0000 Subject: [PATCH 414/426] fix(deps): update module istio.io/client-go to v1.25.2 (release-1.5) (#4767) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e4ab60f7de..cedcbf68cc 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( google.golang.org/grpc v1.71.1 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.25.2 - istio.io/client-go v1.25.1 + istio.io/client-go v1.25.2 k8s.io/api v0.32.3 k8s.io/apiextensions-apiserver v0.32.3 k8s.io/apimachinery v0.32.3 diff --git a/go.sum b/go.sum index 5829dd51dd..1b9cecb41f 100644 --- a/go.sum +++ b/go.sum @@ -381,8 +381,8 @@ gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= istio.io/api v1.25.2 h1:FCRQy7iaTreKJdLemlQ1vRJEsf1soCHoTAuSf68w5I8= istio.io/api v1.25.2/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= -istio.io/client-go v1.25.1 h1:1Asibz5v2NBA6w4Sqa85NS7TkpEolZcPKAT5oUAXWi8= -istio.io/client-go v1.25.1/go.mod h1:Vap9OyHJMvvDegYoZczcNybS4wbPaTk+4bZcWMb8+vE= +istio.io/client-go v1.25.2 h1:faupTqeMD0PkuNTZdFlpxxT35jBSQapK5k+MNAkXvqA= +istio.io/client-go v1.25.2/go.mod h1:E2LTxTcCVe4cqpKy4/9Y4VmwSoLiH6ff9MEG7EhfSDo= k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= From 707f0e4277c3c75982f60f56cb43ee1a945f4db6 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Wed, 16 Apr 2025 10:27:11 +0200 Subject: [PATCH 415/426] Remove dynamic parts from args section in job container (#4770) --- .../codemodule/installer/job/bootstrapper.go | 18 ++++++++--- .../installer/job/bootstrapper_test.go | 31 ++++++++++++------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/pkg/injection/codemodule/installer/job/bootstrapper.go b/pkg/injection/codemodule/installer/job/bootstrapper.go index 07d308d708..ff1ac46fdf 100644 --- a/pkg/injection/codemodule/installer/job/bootstrapper.go +++ b/pkg/injection/codemodule/installer/job/bootstrapper.go @@ -73,7 +73,17 @@ func (inst *Installer) buildJob(name, targetDir string) (*batchv1.Job, error) { }, } - container.Args = inst.buildArgs(name, targetDir) + container.Args = inst.buildArgs() + container.Env = []corev1.EnvVar{ + { + Name: "TARGET_PATH", + Value: targetDir, + }, + { + Name: "WORK_PATH", + Value: inst.props.PathResolver.AgentJobWorkDirForJob(name), + }, + } annotations := map[string]string{ webhook.AnnotationDynatraceInject: "false", @@ -94,10 +104,10 @@ func (inst *Installer) buildJob(name, targetDir string) (*batchv1.Job, error) { ) } -func (inst *Installer) buildArgs(jobName, targetDir string) []string { +func (inst *Installer) buildArgs() []string { return []string{ "--source=" + codeModuleSource, - "--target=" + targetDir, - "--work=" + inst.props.PathResolver.AgentJobWorkDirForJob(jobName), + "--target=$(TARGET_PATH)", + "--work=$(WORK_PATH)", } } diff --git a/pkg/injection/codemodule/installer/job/bootstrapper_test.go b/pkg/injection/codemodule/installer/job/bootstrapper_test.go index 4dbece7bd0..6680a0842e 100644 --- a/pkg/injection/codemodule/installer/job/bootstrapper_test.go +++ b/pkg/injection/codemodule/installer/job/bootstrapper_test.go @@ -43,8 +43,6 @@ func TestBuildJobName(t *testing.T) { func TestBuildArgs(t *testing.T) { t.Run("args are built correctly", func(t *testing.T) { - targetDir := "1.2.3" - jobName := "test-job-123" props := &Properties{ PathResolver: metadata.PathResolver{RootDir: "root"}, } @@ -52,18 +50,12 @@ func TestBuildArgs(t *testing.T) { props: props, } - args := inst.buildArgs(jobName, targetDir) + args := inst.buildArgs() require.Len(t, args, 3) - assert.Contains(t, args[0], "--source") - assert.Contains(t, args[0], codeModuleSource) - - assert.Contains(t, args[1], "--target") - assert.Contains(t, args[1], targetDir) - - assert.Contains(t, args[2], "--work") - assert.Contains(t, args[2], props.PathResolver.RootDir) - assert.Contains(t, args[2], jobName) + assert.Equal(t, "--source=/opt/dynatrace/oneagent", args[0]) + assert.Equal(t, "--target=$(TARGET_PATH)", args[1]) + assert.Equal(t, "--work=$(WORK_PATH)", args[2]) }) } @@ -131,6 +123,21 @@ func TestBuildJob(t *testing.T) { assert.NotEmpty(t, container.Args) assert.NotEmpty(t, container.SecurityContext) + require.Len(t, container.Env, 2) + + targetEnv := corev1.EnvVar{ + Name: "TARGET_PATH", + Value: targetDir, + } + + workEnv := corev1.EnvVar{ + Name: "WORK_PATH", + Value: props.PathResolver.AgentJobWorkDirForJob(name), + } + + assert.Contains(t, container.Env, targetEnv) + assert.Contains(t, container.Env, workEnv) + require.Len(t, container.VolumeMounts, 1) assert.Equal(t, job.Spec.Template.Spec.Volumes[0].Name, container.VolumeMounts[0].Name) assert.Equal(t, props.PathResolver.RootDir, container.VolumeMounts[0].MountPath) From 13c138534460ad88fe16bd62836a4f67afa50aa5 Mon Sep 17 00:00:00 2001 From: Albian Krasniqi <62391739+waodim@users.noreply.github.com> Date: Wed, 16 Apr 2025 17:05:32 +0200 Subject: [PATCH 416/426] Remove obsolete validation warning in case of custom image is used (#4775) --- pkg/api/validation/dynakube/oneagent.go | 18 ------------------ pkg/api/validation/dynakube/validation.go | 1 - 2 files changed, 19 deletions(-) diff --git a/pkg/api/validation/dynakube/oneagent.go b/pkg/api/validation/dynakube/oneagent.go index f36fabd742..8641a92ae6 100644 --- a/pkg/api/validation/dynakube/oneagent.go +++ b/pkg/api/validation/dynakube/oneagent.go @@ -26,8 +26,6 @@ Use a nodeSelector to avoid this conflict. Conflicting DynaKubes: %s` errorVolumeStorageReadOnlyModeConflict = `The DynaKube specification specifies a read-only host file system while OneAgent has volume storage enabled.` - warningPublicImageWithWrongConfig = `You are using a custom OneAgent image without CSI driver. Only images from the tenant registry are supported."` - warningOneAgentInstallerEnvVars = `The environment variables ONEAGENT_INSTALLER_SCRIPT_URL and ONEAGENT_INSTALLER_TOKEN are only relevant for an unsupported image type. Please ensure you are using a supported image.` warningHostGroupConflict = `The DynaKube specification sets the host group using the --set-host-group parameter. Instead, specify the new spec.oneagent.hostGroup field. If both settings are used, the new field takes precedence over the parameter.` @@ -129,22 +127,6 @@ func mapKeysToString(m map[string]bool, sep string) string { return strings.Join(keys, sep) } -func publicImageSetWithoutReadOnlyMode(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { - if dk.OneAgent().GetCustomImage() != "" { - if dk.OneAgent().IsReadOnlyFSSupported() { - return "" - } - - if dk.OneAgent().IsClassicFullStackMode() { - return "" - } - - return warningPublicImageWithWrongConfig - } - - return "" -} - func imageFieldSetWithoutCSIFlag(_ context.Context, v *Validator, dk *dynakube.DynaKube) string { if dk.OneAgent().IsApplicationMonitoringMode() { if len(dk.Spec.OneAgent.ApplicationMonitoring.CodeModulesImage) > 0 && !v.modules.CSIDriver && !dk.FeatureNodeImagePull() { diff --git a/pkg/api/validation/dynakube/validation.go b/pkg/api/validation/dynakube/validation.go index cbe01f0867..8abed02462 100644 --- a/pkg/api/validation/dynakube/validation.go +++ b/pkg/api/validation/dynakube/validation.go @@ -70,7 +70,6 @@ var ( deprecatedFeatureFlag, ignoredLogMonitoringTemplate, conflictingApiUrlForExtensions, - publicImageSetWithoutReadOnlyMode, logMonitoringWithoutK8SMonitoring, kspmWithoutK8SMonitoring, extensionsWithoutK8SMonitoring, From 196b561251cf804bba86e4bc64ca475a95230dc6 Mon Sep 17 00:00:00 2001 From: Stefan Hauth Date: Thu, 17 Apr 2025 10:55:49 +0200 Subject: [PATCH 417/426] Increase CRD desc len. --- hack/make/manifests/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make/manifests/config.mk b/hack/make/manifests/config.mk index 5c6f636a7c..516cca18a8 100644 --- a/hack/make/manifests/config.mk +++ b/hack/make/manifests/config.mk @@ -1,4 +1,4 @@ -CRD_OPTIONS ?= "crd:crdVersions=v1,maxDescLen=0,ignoreUnexportedFields=true" +CRD_OPTIONS ?= "crd:crdVersions=v1,maxDescLen=100,ignoreUnexportedFields=true" OLM ?= false From 4d598bf487aa4651649dc71b029d8610aab92738 Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Thu, 17 Apr 2025 16:41:38 +0200 Subject: [PATCH 418/426] Add node pull image sample. (#4779) --- .../dynakube/v1beta4/node-image-pull.yaml | 21 + config/crd/bases/dynatrace.com_dynakubes.yaml | 3250 +++++++++++++++ .../crd/bases/dynatrace.com_edgeconnects.yaml | 334 ++ .../Common/crd/dynatrace-operator-crd.yaml | 3584 +++++++++++++++++ doc/api/dynakube-api-ref.md | 296 +- doc/api/edgeconnect-api-ref.md | 52 +- 6 files changed, 7363 insertions(+), 174 deletions(-) create mode 100644 assets/samples/dynakube/v1beta4/node-image-pull.yaml diff --git a/assets/samples/dynakube/v1beta4/node-image-pull.yaml b/assets/samples/dynakube/v1beta4/node-image-pull.yaml new file mode 100644 index 0000000000..1571a58d7e --- /dev/null +++ b/assets/samples/dynakube/v1beta4/node-image-pull.yaml @@ -0,0 +1,21 @@ +apiVersion: dynatrace.com/v1beta4 +kind: DynaKube +metadata: + name: dynakube + namespace: dynatrace + annotations: + # enable node image pull + feature.dynatrace.com/node-image-pull: "true" + +spec: + apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api + + # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment + # This can be omitted if authentication for your private registry is configured on the nodes. + # + # customPullSecret: "custom-pull-secret" + + oneAgent: + applicationMonitoring: + # the node image pull feature requires a code modules image version 1.311+ + codeModulesImage: public.ecr.aws/dynatrace/dynatrace-codemodules:1.311.70.20250416-094918 diff --git a/config/crd/bases/dynatrace.com_dynakubes.yaml b/config/crd/bases/dynatrace.com_dynakubes.yaml index 032b5ab913..088bcaceab 100644 --- a/config/crd/bases/dynatrace.com_dynakubes.yaml +++ b/config/crd/bases/dynatrace.com_dynakubes.yaml @@ -32,92 +32,144 @@ spec: name: v1beta1 schema: openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: + description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the ActiveGate pods type: object capabilities: + description: Activegate capabilities enabled (routing, kubernetes-monitoring, + metrics-ingest, dynatrace-api) items: type: string type: array customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Custom properties value. nullable: true type: string valueFrom: + description: Custom properties secret. nullable: true type: string type: object dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods type: string env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -129,30 +181,45 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -168,6 +235,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -176,39 +246,73 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tlsSecretName: + description: The name of a secret containing ActiveGate TLS cert+key + and password. type: string tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -222,27 +326,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -252,80 +374,128 @@ spec: type: array type: object apiUrl: + description: Dynatrace apiUrl, including the /api path at the end. type: string customPullSecret: + description: Defines a custom pull secret in case you use a private + registry when pulling images from the... type: string enableIstio: + description: When enabled, and if Istio is installed on the Kubernetes + environment, Dynatrace Operator will... type: boolean kubernetesMonitoring: + description: Configuration for Kubernetes Monitoring properties: customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Custom properties value. nullable: true type: string valueFrom: + description: Custom properties secret. nullable: true type: string type: object enabled: + description: Enables Capability type: boolean env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -337,28 +507,42 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -374,6 +558,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -382,37 +569,69 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -426,27 +645,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -456,15 +693,26 @@ spec: type: array type: object namespaceSelector: + description: Applicable only for applicationMonitoring or cloudNativeFullStack + configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector applies + to. type: string operator: + description: operator represents a key's relationship to + a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -478,26 +726,42 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: + description: General configuration about OneAgent instances. properties: applicationMonitoring: + description: dynatrace-webhook injects into application pods based + on labeled namespaces. nullable: true properties: codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -513,6 +777,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -521,85 +788,133 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object useCSIDriver: + description: Set if you want to use the CSIDriver. type: boolean version: + description: The OneAgent version to be used. type: string type: object classicFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -611,23 +926,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -643,6 +972,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -651,103 +983,170 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used. type: string type: object cloudNativeFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. type: string dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -759,15 +1158,26 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -783,6 +1193,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -791,24 +1204,38 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -824,6 +1251,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -832,103 +1262,171 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used. type: string type: object hostGroup: + description: Sets a host group for OneAgent. type: string hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -940,23 +1438,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -972,6 +1484,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -980,108 +1495,176 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used. type: string type: object type: object proxy: + description: Set custom proxy settings either directly or from a secret + with the field proxy. properties: value: + description: Proxy URL. It has preference over ValueFrom. nullable: true type: string valueFrom: + description: Secret containing proxy URL. nullable: true type: string type: object routing: + description: Configuration for Routing properties: customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Custom properties value. nullable: true type: string valueFrom: + description: Custom properties secret. nullable: true type: string type: object enabled: + description: Enables Capability type: boolean env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -1093,28 +1676,42 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1130,6 +1727,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1138,37 +1738,69 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -1182,27 +1814,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -1212,85 +1862,129 @@ spec: type: array type: object skipCertCheck: + description: Disable certificate check for the connection between + Dynatrace Operator and the Dynatrace Cluster. type: boolean tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. type: string trustedCAs: + description: Adds custom RootCAs from a configmap. Put the certificate + under certs within your configmap. type: string required: - apiUrl type: object status: + description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: + description: Observed state of ActiveGate properties: connectionInfoStatus: + description: Information about Active Gate's connections properties: endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator items: type: string type: array source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object codeModules: + description: Observed state of Code Modules properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -1303,72 +1997,104 @@ spec: type: object type: array dynatraceApi: + description: Observed state of Dynatrace API properties: lastTokenScopeRequest: + description: Time of the last token request format: date-time type: string type: object kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster type: string lastTokenProbeTimestamp: + description: LastTokenProbeTimestamp tracks when the last request + for the API token validity was sent format: date-time type: string oneAgent: + description: Observed state of OneAgent properties: connectionInfoStatus: + description: Information about OneAgent's connections properties: communicationHosts: + description: List of communication hosts items: properties: host: + description: Host domain type: string port: + description: Connection port format: int32 type: integer protocol: + description: Connection protocol type: string type: object type: array endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object healthcheck: + description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: + description: Image ID type: string instances: additionalProperties: properties: ipAddress: + description: IP address of the pod type: string podName: + description: Name of the OneAgent pod type: string type: object + description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: + description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated format: date-time type: string type: object @@ -1390,92 +2116,144 @@ spec: name: v1beta2 schema: openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: + description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the ActiveGate pods type: object capabilities: + description: "Defines the ActiveGate pod capabilities\nPossible + values:\n\t- `routing` enables OneAgent routing." items: type: string type: array customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Custom properties value. nullable: true type: string valueFrom: + description: Custom properties secret. nullable: true type: string type: object dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods type: string env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -1487,31 +2265,48 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: Use a custom ActiveGate image. type: string labels: additionalProperties: type: string + description: Your defined labels for ActiveGate pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes ActiveGate will be deployed. type: object priorityClassName: + description: Assign a priority class to the ActiveGate pods. By + default, no class is set. type: string replicas: default: 1 + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Resource settings for ActiveGate container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1527,6 +2322,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1535,39 +2333,73 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tlsSecretName: + description: The name of a secret containing ActiveGate TLS cert+key + and password. type: string tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints to the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -1581,27 +2413,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -1611,29 +2461,49 @@ spec: type: array type: object apiUrl: + description: Dynatrace `apiUrl`, including the `/api` path at the + end. type: string customPullSecret: + description: Defines a custom pull secret in case you use a private + registry when pulling images from the... type: string dynatraceApiRequestThreshold: default: 15 + description: Minimum minutes between Dynatrace API requests. type: integer enableIstio: + description: When enabled, and if Istio is installed in the Kubernetes + environment, Dynatrace Operator will... type: boolean metadataEnrichment: + description: Configuration for Metadata Enrichment. properties: enabled: default: false + description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: + description: The namespaces where you want Dynatrace Operator + to inject enrichment. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -1647,6 +2517,7 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic @@ -1654,22 +2525,37 @@ spec: - enabled type: object networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: + description: General configuration about OneAgent instances. properties: applicationMonitoring: + description: dynatrace-webhook injects into application pods based + on labeled namespaces. nullable: true properties: codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1685,6 +2571,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1693,18 +2582,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -1718,88 +2620,135 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic useCSIDriver: default: false + description: Set if you want to use the CSIDriver. type: boolean version: + description: The OneAgent version to be used. type: string type: object classicFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -1811,23 +2760,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1843,6 +2806,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1851,106 +2817,176 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used for OneAgents + running in the dedicated pod. type: string type: object cloudNativeFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. type: string dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -1962,15 +2998,26 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1986,6 +3033,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1994,22 +3044,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -2023,21 +3088,32 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2053,6 +3129,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2061,106 +3140,178 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used for OneAgents + running in the dedicated pod. type: string type: object hostGroup: + description: Specify the name of the group to which you want to + assign the host. type: string hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -2172,23 +3323,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2204,6 +3369,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2212,121 +3380,194 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used for OneAgents + running in the dedicated pod. type: string type: object type: object proxy: + description: Set custom proxy settings either directly or from a secret + with the field `proxy`. properties: value: + description: Proxy URL. It has preference over ValueFrom. nullable: true type: string valueFrom: + description: Secret containing proxy URL. nullable: true type: string type: object skipCertCheck: + description: Disable certificate check for the connection between + Dynatrace Operator and the Dynatrace Cluster. type: boolean tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. type: string trustedCAs: + description: |- + Adds custom RootCAs from a configmap. + The key to the data must be `certs`. type: string required: - apiUrl type: object status: + description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: + description: Observed state of ActiveGate properties: connectionInfoStatus: + description: Information about Active Gate's connections properties: endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator items: type: string type: array source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object codeModules: + description: Observed state of Code Modules properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -2339,18 +3580,27 @@ spec: type: object type: array dynatraceApi: + description: Observed state of Dynatrace API properties: lastTokenScopeRequest: + description: Time of the last token request format: date-time type: string type: object kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster type: string kubernetesClusterMEID: + description: KubernetesClusterMEID contains the ID of the monitored + entity that points to the Kubernetes cluster type: string kubernetesClusterName: + description: KubernetesClusterName contains the display name (also + know as label) of the monitored entity that... type: string metadataEnrichment: + description: Observed state of Metadata-Enrichment properties: rules: items: @@ -2367,61 +3617,87 @@ spec: type: array type: object oneAgent: + description: Observed state of OneAgent properties: connectionInfoStatus: + description: Information about OneAgent's connections properties: communicationHosts: + description: List of communication hosts items: properties: host: + description: Host domain type: string port: + description: Connection port format: int32 type: integer protocol: + description: Connection protocol type: string type: object type: array endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object healthcheck: + description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: + description: Image ID type: string instances: additionalProperties: properties: ipAddress: + description: IP address of the pod type: string podName: + description: Name of the OneAgent pod type: string type: object + description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: + description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated format: date-time type: string type: object @@ -2443,92 +3719,144 @@ spec: name: v1beta3 schema: openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: + description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the ActiveGate pods type: object capabilities: + description: Activegate capabilities enabled (routing, kubernetes-monitoring, + metrics-ingest, dynatrace-api) items: type: string type: array customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Raw value for given property. nullable: true type: string valueFrom: + description: Name of the secret to get the property from. nullable: true type: string type: object dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods type: string env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -2540,30 +3868,45 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2579,6 +3922,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2587,39 +3933,73 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tlsSecretName: + description: The name of a secret containing ActiveGate TLS cert+key + and password. type: string tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -2633,27 +4013,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -2663,19 +4061,29 @@ spec: type: array type: object apiUrl: + description: Dynatrace apiUrl, including the /api path at the end. maxLength: 128 type: string customPullSecret: + description: Defines a custom pull secret in case you use a private + registry when pulling images from the... type: string dynatraceApiRequestThreshold: + description: Configuration for thresholding Dynatrace API requests. type: integer enableIstio: + description: When enabled, and if Istio is installed on the Kubernetes + environment, Dynatrace Operator will... type: boolean extensions: + description: When an (empty) ExtensionsSpec is provided, the extensions + related components (extensions... type: object kspm: + description: General configuration about the KSPM feature. type: object logMonitoring: + description: General configuration about the LogMonitoring feature. properties: ingestRuleMatchers: items: @@ -2690,19 +4098,32 @@ spec: type: array type: object metadataEnrichment: + description: Configuration for Metadata Enrichment. properties: enabled: + description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: + description: The namespaces where you want Dynatrace Operator + to inject enrichment. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -2716,27 +4137,43 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic type: object networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: + description: General configuration about OneAgent instances. properties: applicationMonitoring: + description: dynatrace-webhook injects into application pods based + on labeled namespaces. nullable: true properties: codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2752,6 +4189,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2760,18 +4200,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -2785,84 +4238,130 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic version: + description: Use a specific OneAgent CodeModule version. type: string type: object classicFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -2874,23 +4373,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2906,6 +4419,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2914,105 +4430,175 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object cloudNativeFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. type: string dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -3024,15 +4610,26 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3048,6 +4645,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3056,22 +4656,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -3085,21 +4700,32 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3115,6 +4741,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3123,105 +4752,176 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object hostGroup: + description: Sets a host group for OneAgent. type: string hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -3233,23 +4933,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3265,6 +4979,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3273,42 +4990,72 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object type: object proxy: + description: Set custom proxy settings either directly or from a secret + with the field proxy. properties: value: + description: Raw value for given property. nullable: true type: string valueFrom: + description: Name of the secret to get the property from. nullable: true type: string type: object skipCertCheck: + description: Disable certificate check for the connection between + Dynatrace Operator and the Dynatrace Cluster. type: boolean templates: properties: @@ -3317,37 +5064,59 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations to the ExtensionExecutionController + pods type: object customConfig: + description: Defines name of ConfigMap containing custom configuration + file type: string customExtensionCertificates: + description: Defines name of Secret containing certificates + for custom extensions signature validation type: string imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the ExtensionExecutionController + pods type: object persistentVolumeClaim: + description: Defines storage device properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot. properties: apiGroup: + description: APIGroup is the group for the resource + being referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string required: - kind @@ -3355,20 +5124,31 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty... properties: apiGroup: + description: APIGroup is the group for the resource + being referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a... type: string required: - kind - name type: object resources: + description: resources represents the minimum resources + the volume should have. properties: limits: additionalProperties: @@ -3377,6 +5157,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3385,18 +5168,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. type: object type: object selector: + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -3410,26 +5206,44 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: storageClassName is the name of the StorageClass + required by the claim. type: string volumeAttributesClassName: + description: volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. type: string volumeMode: + description: volumeMode defines what type of volume is + required by the claim. type: string volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. type: string type: object resources: + description: Define resources' requests and limits for single + ExtensionExecutionController pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3445,6 +5259,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3453,39 +5270,75 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tlsRefName: type: string tolerations: + description: Set tolerations for the ExtensionExecutionController + pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ExtensionExecutionController + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching + pods. properties: matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that... properties: key: + description: key is the label key that the + selector applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string + values. items: type: string type: array @@ -3499,27 +5352,46 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of + eligible domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -3528,6 +5400,7 @@ spec: type: object type: array useEphemeralVolume: + description: Selects EmptyDir volume to be storage device type: boolean type: object kspmNodeConfigurationCollector: @@ -3535,67 +5408,108 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations for the NodeConfigurationCollector + pods type: object args: + description: Set additional arguments to the NodeConfigurationCollector + pods items: type: string type: array env: + description: Set additional environment variables for the + NodeConfigurationCollector pods items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -3607,32 +5521,59 @@ spec: type: object type: array imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the NodeConfigurationCollector + pods type: object nodeAffinity: + description: Define the nodeAffinity for the DaemonSet of + the NodeConfigurationCollector properties: preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified... items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). properties: preference: + description: A node selector term, associated with + the corresponding weight. properties: matchExpressions: + description: A list of node selector requirements + by node's labels. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3644,13 +5585,25 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: + description: A list of node selector requirements + by node's fields. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3664,6 +5617,8 @@ spec: type: object x-kubernetes-map-type: atomic weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: @@ -3673,18 +5628,38 @@ spec: type: array x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will... properties: nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. properties: matchExpressions: + description: A list of node selector requirements + by node's labels. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3696,13 +5671,25 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: + description: A list of node selector requirements + by node's fields. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3725,17 +5712,29 @@ spec: nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes NodeConfigurationCollector pods will be... type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string resources: + description: Define resources' requests and limits for single + NodeConfigurationCollector pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3751,6 +5750,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3759,81 +5761,136 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tolerations: + description: Set tolerations for the NodeConfigurationCollector + pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array updateStrategy: + description: Define the NodeConfigurationCollector daemonSet + updateStrategy properties: rollingUpdate: + description: Rolling update config params. Present only + if type = "RollingUpdate". properties: maxSurge: anyOf: - type: integer - type: string + description: |- + The maximum number of nodes with an existing available DaemonSet pod that + can have an updated... x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string + description: |- + The maximum number of DaemonSet pods that can be unavailable during the + update. x-kubernetes-int-or-string: true type: object type: + description: Type of daemon set update. Can be "RollingUpdate" + or "OnDelete". Default is RollingUpdate. type: string type: object type: object logMonitoring: + description: Low-level configuration options for the LogMonitoring + feature. properties: annotations: additionalProperties: type: string + description: Add custom annotations to the LogMonitoring pods type: object args: + description: Set additional arguments to the LogMonitoring + main container items: type: string type: array dnsPolicy: + description: Sets DNS Policy for the LogMonitoring pods type: string imageRef: + description: Overrides the default image for the LogMonitoring + pods properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Add custom labels to the LogMonitoring pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes + for the LogMonitoring pods type: object priorityClassName: + description: Assign a priority class to the LogMonitoring + pods. By default, no class is set type: string resources: + description: Define resources' requests and limits for all + the LogMonitoring pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3849,6 +5906,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3857,23 +5917,43 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode for the... type: string tolerations: + description: Set tolerations for the LogMonitoring pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array @@ -3883,30 +5963,47 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations to the OtelCollector + pods type: object imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the OtelCollector + pods type: object replicas: + description: Number of replicas for your OtelCollector format: int32 type: integer resources: + description: Define resources' requests and limits for single + OtelCollector pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3922,6 +6019,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3930,39 +6030,74 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tlsRefName: type: string tolerations: + description: Set tolerations for the OtelCollector pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the OtelCollector + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching + pods. properties: matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that... properties: key: + description: key is the label key that the + selector applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string + values. items: type: string type: array @@ -3976,27 +6111,46 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of + eligible domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -4007,83 +6161,125 @@ spec: type: object type: object tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. type: string trustedCAs: + description: Adds custom RootCAs from a configmap. Put the certificate + under certs within your configmap. type: string required: - apiUrl type: object status: + description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: + description: Observed state of ActiveGate properties: connectionInfoStatus: + description: Information about Active Gate's connections properties: endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator items: type: string type: array source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object codeModules: + description: Observed state of Code Modules properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -4096,23 +6292,35 @@ spec: type: object type: array dynatraceApi: + description: Observed state of Dynatrace API properties: lastTokenScopeRequest: + description: Time of the last token request format: date-time type: string type: object kspm: + description: Observed state of Kspm properties: tokenSecretHash: + description: TokenSecretHash contains the hash of the token that + is passed to both the ActiveGate and... type: string type: object kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster type: string kubernetesClusterMEID: + description: KubernetesClusterMEID contains the ID of the monitored + entity that points to the Kubernetes cluster type: string kubernetesClusterName: + description: KubernetesClusterName contains the display name (also + know as label) of the monitored entity that... type: string metadataEnrichment: + description: Observed state of Metadata-Enrichment properties: rules: items: @@ -4129,61 +6337,87 @@ spec: type: array type: object oneAgent: + description: Observed state of OneAgent properties: connectionInfoStatus: + description: Information about OneAgent's connections properties: communicationHosts: + description: List of communication hosts items: properties: host: + description: Host domain type: string port: + description: Connection port format: int32 type: integer protocol: + description: Connection protocol type: string type: object type: array endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object healthcheck: + description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: + description: Image ID type: string instances: additionalProperties: properties: ipAddress: + description: IP address of the pod type: string podName: + description: Name of the OneAgent pod type: string type: object + description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: + description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated format: date-time type: string type: object @@ -4205,92 +6439,144 @@ spec: name: v1beta4 schema: openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: + description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the ActiveGate pods type: object capabilities: + description: Activegate capabilities enabled (routing, kubernetes-monitoring, + metrics-ingest, dynatrace-api) items: type: string type: array customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Raw value for given property. nullable: true type: string valueFrom: + description: Name of the secret to get the property from. nullable: true type: string type: object dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods type: string env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -4302,31 +6588,46 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object persistentVolumeClaim: + description: Defines storage device properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot. properties: apiGroup: + description: APIGroup is the group for the resource being + referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string required: - kind @@ -4334,20 +6635,31 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty... properties: apiGroup: + description: APIGroup is the group for the resource being + referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a... type: string required: - kind - name type: object resources: + description: resources represents the minimum resources the + volume should have. properties: limits: additionalProperties: @@ -4356,6 +6668,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4364,18 +6679,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object selector: + description: selector is a label query over volumes to consider + for binding. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4389,31 +6717,51 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: storageClassName is the name of the StorageClass + required by the claim. type: string volumeAttributesClassName: + description: volumeAttributesClassName may be used to set + the VolumeAttributesClass used by this claim. type: string volumeMode: + description: volumeMode defines what type of volume is required + by the claim. type: string volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. type: string type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4429,6 +6777,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4437,42 +6788,78 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object terminationGracePeriodSeconds: + description: Configures the terminationGracePeriodSeconds parameter + of the ActiveGate pod. format: int64 type: integer tlsSecretName: + description: The name of a secret containing ActiveGate TLS cert+key + and password. type: string tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4486,27 +6873,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -4515,22 +6920,33 @@ spec: type: object type: array useEphemeralVolume: + description: UseEphemeralVolume type: boolean type: object apiUrl: + description: Dynatrace apiUrl, including the /api path at the end. maxLength: 128 type: string customPullSecret: + description: Defines a custom pull secret in case you use a private + registry when pulling images from the... type: string dynatraceApiRequestThreshold: + description: Configuration for thresholding Dynatrace API requests. type: integer enableIstio: + description: When enabled, and if Istio is installed on the Kubernetes + environment, Dynatrace Operator will... type: boolean extensions: + description: When an (empty) ExtensionsSpec is provided, the extensions + related components (extensions... type: object kspm: + description: General configuration about the KSPM feature. type: object logMonitoring: + description: General configuration about the LogMonitoring feature. properties: ingestRuleMatchers: items: @@ -4545,19 +6961,32 @@ spec: type: array type: object metadataEnrichment: + description: Configuration for Metadata Enrichment. properties: enabled: + description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: + description: The namespaces where you want Dynatrace Operator + to inject enrichment. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4571,27 +7000,43 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic type: object networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: + description: General configuration about OneAgent instances. properties: applicationMonitoring: + description: dynatrace-webhook injects into application pods based + on labeled namespaces. nullable: true properties: codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4607,6 +7052,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4615,18 +7063,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4640,84 +7101,130 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic version: + description: Use a specific OneAgent CodeModule version. type: string type: object classicFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -4729,23 +7236,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4761,6 +7282,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4769,107 +7293,179 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will... type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object cloudNativeFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. type: string dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -4881,15 +7477,26 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4905,6 +7512,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4913,22 +7523,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4942,21 +7567,32 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4972,6 +7608,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4980,107 +7619,180 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will... type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object hostGroup: + description: Sets a host group for OneAgent. type: string hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -5092,23 +7804,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5124,6 +7850,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5132,46 +7861,80 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will... type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object type: object proxy: + description: Set custom proxy settings either directly or from a secret + with the field proxy. properties: value: + description: Raw value for given property. nullable: true type: string valueFrom: + description: Name of the secret to get the property from. nullable: true type: string type: object skipCertCheck: + description: Disable certificate check for the connection between + Dynatrace Operator and the Dynatrace Cluster. type: boolean telemetryIngest: + description: When a TelemetryIngestSpec is provided, the OTEL collector + is deployed by the operator. properties: protocols: items: @@ -5189,37 +7952,59 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations to the ExtensionExecutionController + pods type: object customConfig: + description: Defines name of ConfigMap containing custom configuration + file type: string customExtensionCertificates: + description: Defines name of Secret containing certificates + for custom extensions signature validation type: string imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the ExtensionExecutionController + pods type: object persistentVolumeClaim: + description: Defines storage device properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot. properties: apiGroup: + description: APIGroup is the group for the resource + being referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string required: - kind @@ -5227,20 +8012,31 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty... properties: apiGroup: + description: APIGroup is the group for the resource + being referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a... type: string required: - kind - name type: object resources: + description: resources represents the minimum resources + the volume should have. properties: limits: additionalProperties: @@ -5249,6 +8045,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5257,18 +8056,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. type: object type: object selector: + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -5282,26 +8094,44 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: storageClassName is the name of the StorageClass + required by the claim. type: string volumeAttributesClassName: + description: volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. type: string volumeMode: + description: volumeMode defines what type of volume is + required by the claim. type: string volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. type: string type: object resources: + description: Define resources' requests and limits for single + ExtensionExecutionController pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5317,6 +8147,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5325,39 +8158,75 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tlsRefName: type: string tolerations: + description: Set tolerations for the ExtensionExecutionController + pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ExtensionExecutionController + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching + pods. properties: matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that... properties: key: + description: key is the label key that the + selector applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string + values. items: type: string type: array @@ -5371,27 +8240,46 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of + eligible domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -5400,6 +8288,7 @@ spec: type: object type: array useEphemeralVolume: + description: Selects EmptyDir volume to be storage device type: boolean type: object kspmNodeConfigurationCollector: @@ -5407,67 +8296,108 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations for the NodeConfigurationCollector + pods type: object args: + description: Set additional arguments to the NodeConfigurationCollector + pods items: type: string type: array env: + description: Set additional environment variables for the + NodeConfigurationCollector pods items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -5479,32 +8409,59 @@ spec: type: object type: array imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the NodeConfigurationCollector + pods type: object nodeAffinity: + description: Define the nodeAffinity for the DaemonSet of + the NodeConfigurationCollector properties: preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified... items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). properties: preference: + description: A node selector term, associated with + the corresponding weight. properties: matchExpressions: + description: A list of node selector requirements + by node's labels. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -5516,13 +8473,25 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: + description: A list of node selector requirements + by node's fields. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -5536,6 +8505,8 @@ spec: type: object x-kubernetes-map-type: atomic weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: @@ -5545,18 +8516,38 @@ spec: type: array x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will... properties: nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. properties: matchExpressions: + description: A list of node selector requirements + by node's labels. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -5568,13 +8559,25 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: + description: A list of node selector requirements + by node's fields. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -5597,17 +8600,29 @@ spec: nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes NodeConfigurationCollector pods will be... type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string resources: + description: Define resources' requests and limits for single + NodeConfigurationCollector pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5623,6 +8638,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5631,81 +8649,136 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tolerations: + description: Set tolerations for the NodeConfigurationCollector + pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array updateStrategy: + description: Define the NodeConfigurationCollector daemonSet + updateStrategy properties: rollingUpdate: + description: Rolling update config params. Present only + if type = "RollingUpdate". properties: maxSurge: anyOf: - type: integer - type: string + description: |- + The maximum number of nodes with an existing available DaemonSet pod that + can have an updated... x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string + description: |- + The maximum number of DaemonSet pods that can be unavailable during the + update. x-kubernetes-int-or-string: true type: object type: + description: Type of daemon set update. Can be "RollingUpdate" + or "OnDelete". Default is RollingUpdate. type: string type: object type: object logMonitoring: + description: Low-level configuration options for the LogMonitoring + feature. properties: annotations: additionalProperties: type: string + description: Add custom annotations to the LogMonitoring pods type: object args: + description: Set additional arguments to the LogMonitoring + main container items: type: string type: array dnsPolicy: + description: Sets DNS Policy for the LogMonitoring pods type: string imageRef: + description: Overrides the default image for the LogMonitoring + pods properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Add custom labels to the LogMonitoring pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes + for the LogMonitoring pods type: object priorityClassName: + description: Assign a priority class to the LogMonitoring + pods. By default, no class is set type: string resources: + description: Define resources' requests and limits for all + the LogMonitoring pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5721,6 +8794,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5729,23 +8805,43 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode for the... type: string tolerations: + description: Set tolerations for the LogMonitoring pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array @@ -5755,30 +8851,47 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations to the OtelCollector + pods type: object imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the OtelCollector + pods type: object replicas: + description: Number of replicas for your OtelCollector format: int32 type: integer resources: + description: Define resources' requests and limits for single + OtelCollector pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5794,6 +8907,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5802,39 +8918,74 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tlsRefName: type: string tolerations: + description: Set tolerations for the OtelCollector pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the OtelCollector + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching + pods. properties: matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that... properties: key: + description: key is the label key that the + selector applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string + values. items: type: string type: array @@ -5848,27 +8999,46 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of + eligible domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -5879,83 +9049,125 @@ spec: type: object type: object tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. type: string trustedCAs: + description: Adds custom RootCAs from a configmap. Put the certificate + under certs within your configmap. type: string required: - apiUrl type: object status: + description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: + description: Observed state of ActiveGate properties: connectionInfoStatus: + description: Information about Active Gate's connections properties: endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator items: type: string type: array source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object codeModules: + description: Observed state of Code Modules properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -5968,23 +9180,35 @@ spec: type: object type: array dynatraceApi: + description: Observed state of Dynatrace API properties: lastTokenScopeRequest: + description: Time of the last token request format: date-time type: string type: object kspm: + description: Observed state of Kspm properties: tokenSecretHash: + description: TokenSecretHash contains the hash of the token that + is passed to both the ActiveGate and... type: string type: object kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster type: string kubernetesClusterMEID: + description: KubernetesClusterMEID contains the ID of the monitored + entity that points to the Kubernetes cluster type: string kubernetesClusterName: + description: KubernetesClusterName contains the display name (also + know as label) of the monitored entity that... type: string metadataEnrichment: + description: Observed state of Metadata-Enrichment properties: rules: items: @@ -6001,61 +9225,87 @@ spec: type: array type: object oneAgent: + description: Observed state of OneAgent properties: connectionInfoStatus: + description: Information about OneAgent's connections properties: communicationHosts: + description: List of communication hosts items: properties: host: + description: Host domain type: string port: + description: Connection port format: int32 type: integer protocol: + description: Connection protocol type: string type: object type: array endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object healthcheck: + description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: + description: Image ID type: string instances: additionalProperties: properties: ipAddress: + description: IP address of the pod type: string podName: + description: Name of the OneAgent pod type: string type: object + description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: + description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated format: date-time type: string type: object diff --git a/config/crd/bases/dynatrace.com_edgeconnects.yaml b/config/crd/bases/dynatrace.com_edgeconnects.yaml index 06f0872a9b..684a2e8286 100644 --- a/config/crd/bases/dynatrace.com_edgeconnects.yaml +++ b/config/crd/bases/dynatrace.com_edgeconnects.yaml @@ -32,84 +32,132 @@ spec: name: v1alpha1 schema: openAPIV3Schema: + description: EdgeConnect is the Schema for the EdgeConnect API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: EdgeConnectSpec defines the desired state of EdgeConnect. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the EdgeConnect pods type: object apiServer: + description: Location of the Dynatrace API to connect to, including + your specific environment UUID type: string autoUpdate: default: true + description: Enables automatic restarts of EdgeConnect pods in case + a new version is available (the default... type: boolean caCertsRef: + description: Adds custom root certificate from a configmap. type: string customPullSecret: + description: Pull secret for your private registry type: string env: + description: Adds additional environment variables to the EdgeConnect + pods items: + description: EnvVar represents an environment variable present in + a Container. properties: name: + description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its key + must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the specified + API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key must + be defined type: boolean required: - key @@ -121,42 +169,63 @@ spec: type: object type: array hostPatterns: + description: Host patterns to be set in the tenant, only considered + when provisioning is enabled. items: type: string type: array hostRestrictions: + description: Restrict outgoing HTTP requests to your internal resources + to specified hosts example: internal.example.org,*.dev.example.org type: string imageRef: + description: Overrides the default image properties: repository: + description: Custom EdgeConnect image repository example: docker.io/dynatrace/edgeconnect type: string tag: + description: Indicates version of the EdgeConnect image to use type: string type: object kubernetesAutomation: + description: KubernetesAutomation enables Kubernetes Automation for + Workflows properties: enabled: + description: Enables Kubernetes Automation for Workflows type: boolean type: object labels: additionalProperties: type: string + description: Adds additional labels to the EdgeConnect pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes for the + EdgeConnect pods type: object oauth: + description: EdgeConnect uses the OAuth client to authenticate itself + with the Dynatrace platform. properties: clientSecret: + description: Name of the secret that holds oauth clientId/secret type: string endpoint: + description: Token endpoint URL of Dynatrace SSO type: string provisioner: + description: Determines if the operator will create the EdgeConnect + and light OAuth client on the cluster using... type: boolean resource: + description: URN identifying your account. You get the URN when + creating the OAuth client type: string required: - clientSecret @@ -164,29 +233,45 @@ spec: - resource type: object proxy: + description: General configurations for proxy settings. properties: authRef: + description: Secret name which contains the username and password + used for authentication with the proxy, using... type: string host: + description: Server address (hostname or IP address) of the proxy. type: string noProxy: + description: |- + NoProxy represents the NO_PROXY or no_proxy environment + variable. type: string port: + description: Port of the proxy. format: int32 type: integer type: object replicas: default: 1 + description: 'Amount of replicas for your EdgeConnect (the default + value is: 1)' format: int32 type: integer resources: + description: Defines resources requests and limits for single pods properties: claims: + description: Claims lists the names of resources, defined in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in pod.spec. type: string request: + description: Request is the name chosen for a request in + the referenced claim. type: string required: - name @@ -202,6 +287,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -210,40 +298,74 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object serviceAccountName: default: dynatrace-edgeconnect + description: ServiceAccountName that allows EdgeConnect to access + the Kubernetes API type: string tolerations: + description: Sets tolerations for the EdgeConnect pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Sets topology spread constraints for the EdgeConnect + pods items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -257,27 +379,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods may + be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -290,32 +430,47 @@ spec: - oauth type: object status: + description: EdgeConnectStatus defines the observed state of EdgeConnect. properties: conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -328,24 +483,36 @@ spec: type: object type: array kubeSystemUID: + description: kube-system namespace uid type: string phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: Indicates when the resource was last updated format: date-time type: string version: + description: Version used for the Edgeconnect image properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object type: object @@ -367,83 +534,131 @@ spec: name: v1alpha2 schema: openAPIV3Schema: + description: EdgeConnect is the Schema for the EdgeConnect API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: EdgeConnectSpec defines the desired state of EdgeConnect. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the EdgeConnect pods type: object apiServer: + description: Location of the Dynatrace API to connect to, including + your specific environment UUID type: string autoUpdate: + description: Enables automatic restarts of EdgeConnect pods in case + a new version is available (the default... type: boolean caCertsRef: + description: Adds custom root certificate from a configmap. type: string customPullSecret: + description: Pull secret for your private registry type: string env: + description: Adds additional environment variables to the EdgeConnect + pods items: + description: EnvVar represents an environment variable present in + a Container. properties: name: + description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its key + must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the specified + API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key must + be defined type: boolean required: - key @@ -455,44 +670,65 @@ spec: type: object type: array hostPatterns: + description: Host patterns to be set in the tenant, only considered + when provisioning is enabled. items: type: string type: array hostRestrictions: + description: Restrict outgoing HTTP requests to your internal resources + to specified hosts example: internal.example.org,*.dev.example.org items: type: string type: array imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object kubernetesAutomation: + description: KubernetesAutomation enables Kubernetes Automation for + Workflows properties: enabled: + description: Enables Kubernetes Automation for Workflows type: boolean type: object labels: additionalProperties: type: string + description: Adds additional labels to the EdgeConnect pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes for the + EdgeConnect pods type: object oauth: + description: EdgeConnect uses the OAuth client to authenticate itself + with the Dynatrace platform. properties: clientSecret: + description: Name of the secret that holds oauth clientId/secret type: string endpoint: + description: Token endpoint URL of Dynatrace SSO type: string provisioner: + description: Determines if the operator will create the EdgeConnect + and light OAuth client on the cluster using... type: boolean resource: + description: URN identifying your account. You get the URN when + creating the OAuth client type: string required: - clientSecret @@ -500,28 +736,44 @@ spec: - resource type: object proxy: + description: General configurations for proxy settings. properties: authRef: + description: Secret name which contains the username and password + used for authentication with the proxy, using... type: string host: + description: Server address (hostname or IP address) of the proxy. type: string noProxy: + description: |- + NoProxy represents the NO_PROXY or no_proxy environment + variable. type: string port: + description: Port of the proxy. format: int32 type: integer type: object replicas: + description: 'Amount of replicas for your EdgeConnect (the default + value is: 1)' format: int32 type: integer resources: + description: Defines resources requests and limits for single pods properties: claims: + description: Claims lists the names of resources, defined in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in pod.spec. type: string request: + description: Request is the name chosen for a request in + the referenced claim. type: string required: - name @@ -537,6 +789,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -545,39 +800,73 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object serviceAccountName: + description: ServiceAccountName that allows EdgeConnect to access + the Kubernetes API type: string tolerations: + description: Sets tolerations for the EdgeConnect pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Sets topology spread constraints for the EdgeConnect + pods items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -591,27 +880,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods may + be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -624,32 +931,47 @@ spec: - oauth type: object status: + description: EdgeConnectStatus defines the observed state of EdgeConnect. properties: conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -662,24 +984,36 @@ spec: type: object type: array kubeSystemUID: + description: kube-system namespace uid type: string phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: Indicates when the resource was last updated format: date-time type: string version: + description: Version used for the Edgeconnect image properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object type: object diff --git a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml index 92013513d0..bb618d3fd1 100644 --- a/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml +++ b/config/helm/chart/default/templates/Common/crd/dynatrace-operator-crd.yaml @@ -44,92 +44,144 @@ spec: name: v1beta1 schema: openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: + description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the ActiveGate pods type: object capabilities: + description: Activegate capabilities enabled (routing, kubernetes-monitoring, + metrics-ingest, dynatrace-api) items: type: string type: array customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Custom properties value. nullable: true type: string valueFrom: + description: Custom properties secret. nullable: true type: string type: object dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods type: string env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -141,30 +193,45 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -180,6 +247,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -188,39 +258,73 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tlsSecretName: + description: The name of a secret containing ActiveGate TLS cert+key + and password. type: string tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -234,27 +338,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -264,80 +386,128 @@ spec: type: array type: object apiUrl: + description: Dynatrace apiUrl, including the /api path at the end. type: string customPullSecret: + description: Defines a custom pull secret in case you use a private + registry when pulling images from the... type: string enableIstio: + description: When enabled, and if Istio is installed on the Kubernetes + environment, Dynatrace Operator will... type: boolean kubernetesMonitoring: + description: Configuration for Kubernetes Monitoring properties: customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Custom properties value. nullable: true type: string valueFrom: + description: Custom properties secret. nullable: true type: string type: object enabled: + description: Enables Capability type: boolean env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -349,28 +519,42 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -386,6 +570,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -394,37 +581,69 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -438,27 +657,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -468,15 +705,26 @@ spec: type: array type: object namespaceSelector: + description: Applicable only for applicationMonitoring or cloudNativeFullStack + configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector applies + to. type: string operator: + description: operator represents a key's relationship to + a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -490,26 +738,42 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: + description: General configuration about OneAgent instances. properties: applicationMonitoring: + description: dynatrace-webhook injects into application pods based + on labeled namespaces. nullable: true properties: codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -525,6 +789,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -533,85 +800,133 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object useCSIDriver: + description: Set if you want to use the CSIDriver. type: boolean version: + description: The OneAgent version to be used. type: string type: object classicFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -623,23 +938,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -655,6 +984,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -663,103 +995,170 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used. type: string type: object cloudNativeFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. type: string dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -771,15 +1170,26 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -795,6 +1205,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -803,24 +1216,38 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -836,6 +1263,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -844,103 +1274,171 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used. type: string type: object hostGroup: + description: Sets a host group for OneAgent. type: string hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -952,23 +1450,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -984,6 +1496,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -992,108 +1507,176 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used. type: string type: object type: object proxy: + description: Set custom proxy settings either directly or from a secret + with the field proxy. properties: value: + description: Proxy URL. It has preference over ValueFrom. nullable: true type: string valueFrom: + description: Secret containing proxy URL. nullable: true type: string type: object routing: + description: Configuration for Routing properties: customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Custom properties value. nullable: true type: string valueFrom: + description: Custom properties secret. nullable: true type: string type: object enabled: + description: Enables Capability type: boolean env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -1105,28 +1688,42 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1142,6 +1739,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1150,37 +1750,69 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -1194,27 +1826,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -1224,85 +1874,129 @@ spec: type: array type: object skipCertCheck: + description: Disable certificate check for the connection between + Dynatrace Operator and the Dynatrace Cluster. type: boolean tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. type: string trustedCAs: + description: Adds custom RootCAs from a configmap. Put the certificate + under certs within your configmap. type: string required: - apiUrl type: object status: + description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: + description: Observed state of ActiveGate properties: connectionInfoStatus: + description: Information about Active Gate's connections properties: endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator items: type: string type: array source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object codeModules: + description: Observed state of Code Modules properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -1315,72 +2009,104 @@ spec: type: object type: array dynatraceApi: + description: Observed state of Dynatrace API properties: lastTokenScopeRequest: + description: Time of the last token request format: date-time type: string type: object kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster type: string lastTokenProbeTimestamp: + description: LastTokenProbeTimestamp tracks when the last request + for the API token validity was sent format: date-time type: string oneAgent: + description: Observed state of OneAgent properties: connectionInfoStatus: + description: Information about OneAgent's connections properties: communicationHosts: + description: List of communication hosts items: properties: host: + description: Host domain type: string port: + description: Connection port format: int32 type: integer protocol: + description: Connection protocol type: string type: object type: array endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object healthcheck: + description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: + description: Image ID type: string instances: additionalProperties: properties: ipAddress: + description: IP address of the pod type: string podName: + description: Name of the OneAgent pod type: string type: object + description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: + description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated format: date-time type: string type: object @@ -1402,92 +2128,144 @@ spec: name: v1beta2 schema: openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: + description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the ActiveGate pods type: object capabilities: + description: "Defines the ActiveGate pod capabilities\nPossible + values:\n\t- `routing` enables OneAgent routing." items: type: string type: array customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Custom properties value. nullable: true type: string valueFrom: + description: Custom properties secret. nullable: true type: string type: object dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods type: string env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -1499,31 +2277,48 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: Use a custom ActiveGate image. type: string labels: additionalProperties: type: string + description: Your defined labels for ActiveGate pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes ActiveGate will be deployed. type: object priorityClassName: + description: Assign a priority class to the ActiveGate pods. By + default, no class is set. type: string replicas: default: 1 + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Resource settings for ActiveGate container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1539,6 +2334,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1547,39 +2345,73 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tlsSecretName: + description: The name of a secret containing ActiveGate TLS cert+key + and password. type: string tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints to the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -1593,27 +2425,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -1623,29 +2473,49 @@ spec: type: array type: object apiUrl: + description: Dynatrace `apiUrl`, including the `/api` path at the + end. type: string customPullSecret: + description: Defines a custom pull secret in case you use a private + registry when pulling images from the... type: string dynatraceApiRequestThreshold: default: 15 + description: Minimum minutes between Dynatrace API requests. type: integer enableIstio: + description: When enabled, and if Istio is installed in the Kubernetes + environment, Dynatrace Operator will... type: boolean metadataEnrichment: + description: Configuration for Metadata Enrichment. properties: enabled: default: false + description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: + description: The namespaces where you want Dynatrace Operator + to inject enrichment. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -1659,6 +2529,7 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic @@ -1666,22 +2537,37 @@ spec: - enabled type: object networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: + description: General configuration about OneAgent instances. properties: applicationMonitoring: + description: dynatrace-webhook injects into application pods based + on labeled namespaces. nullable: true properties: codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1697,6 +2583,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1705,18 +2594,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -1730,88 +2632,135 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic useCSIDriver: default: false + description: Set if you want to use the CSIDriver. type: boolean version: + description: The OneAgent version to be used. type: string type: object classicFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -1823,23 +2772,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1855,6 +2818,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1863,106 +2829,176 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used for OneAgents + running in the dedicated pod. type: string type: object cloudNativeFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. type: string dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -1974,15 +3010,26 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -1998,6 +3045,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2006,22 +3056,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -2035,21 +3100,32 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2065,6 +3141,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2073,106 +3152,178 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used for OneAgents + running in the dedicated pod. type: string type: object hostGroup: + description: Specify the name of the group to which you want to + assign the host. type: string hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: default: true + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -2184,23 +3335,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2216,6 +3381,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2224,121 +3392,194 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: The OneAgent version to be used for OneAgents + running in the dedicated pod. type: string type: object type: object proxy: + description: Set custom proxy settings either directly or from a secret + with the field `proxy`. properties: value: + description: Proxy URL. It has preference over ValueFrom. nullable: true type: string valueFrom: + description: Secret containing proxy URL. nullable: true type: string type: object skipCertCheck: + description: Disable certificate check for the connection between + Dynatrace Operator and the Dynatrace Cluster. type: boolean tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. type: string trustedCAs: + description: |- + Adds custom RootCAs from a configmap. + The key to the data must be `certs`. type: string required: - apiUrl type: object status: + description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: + description: Observed state of ActiveGate properties: connectionInfoStatus: + description: Information about Active Gate's connections properties: endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator items: type: string type: array source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object codeModules: + description: Observed state of Code Modules properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -2351,18 +3592,27 @@ spec: type: object type: array dynatraceApi: + description: Observed state of Dynatrace API properties: lastTokenScopeRequest: + description: Time of the last token request format: date-time type: string type: object kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster type: string kubernetesClusterMEID: + description: KubernetesClusterMEID contains the ID of the monitored + entity that points to the Kubernetes cluster type: string kubernetesClusterName: + description: KubernetesClusterName contains the display name (also + know as label) of the monitored entity that... type: string metadataEnrichment: + description: Observed state of Metadata-Enrichment properties: rules: items: @@ -2379,61 +3629,87 @@ spec: type: array type: object oneAgent: + description: Observed state of OneAgent properties: connectionInfoStatus: + description: Information about OneAgent's connections properties: communicationHosts: + description: List of communication hosts items: properties: host: + description: Host domain type: string port: + description: Connection port format: int32 type: integer protocol: + description: Connection protocol type: string type: object type: array endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object healthcheck: + description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: + description: Image ID type: string instances: additionalProperties: properties: ipAddress: + description: IP address of the pod type: string podName: + description: Name of the OneAgent pod type: string type: object + description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: + description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated format: date-time type: string type: object @@ -2455,92 +3731,144 @@ spec: name: v1beta3 schema: openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: + description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the ActiveGate pods type: object capabilities: + description: Activegate capabilities enabled (routing, kubernetes-monitoring, + metrics-ingest, dynatrace-api) items: type: string type: array customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Raw value for given property. nullable: true type: string valueFrom: + description: Name of the secret to get the property from. nullable: true type: string type: object dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods type: string env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -2552,30 +3880,45 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2591,6 +3934,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2599,39 +3945,73 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object tlsSecretName: + description: The name of a secret containing ActiveGate TLS cert+key + and password. type: string tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -2645,27 +4025,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -2675,19 +4073,29 @@ spec: type: array type: object apiUrl: + description: Dynatrace apiUrl, including the /api path at the end. maxLength: 128 type: string customPullSecret: + description: Defines a custom pull secret in case you use a private + registry when pulling images from the... type: string dynatraceApiRequestThreshold: + description: Configuration for thresholding Dynatrace API requests. type: integer enableIstio: + description: When enabled, and if Istio is installed on the Kubernetes + environment, Dynatrace Operator will... type: boolean extensions: + description: When an (empty) ExtensionsSpec is provided, the extensions + related components (extensions... type: object kspm: + description: General configuration about the KSPM feature. type: object logMonitoring: + description: General configuration about the LogMonitoring feature. properties: ingestRuleMatchers: items: @@ -2702,19 +4110,32 @@ spec: type: array type: object metadataEnrichment: + description: Configuration for Metadata Enrichment. properties: enabled: + description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: + description: The namespaces where you want Dynatrace Operator + to inject enrichment. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -2728,27 +4149,43 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic type: object networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: + description: General configuration about OneAgent instances. properties: applicationMonitoring: + description: dynatrace-webhook injects into application pods based + on labeled namespaces. nullable: true properties: codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2764,6 +4201,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2772,18 +4212,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -2797,84 +4250,130 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic version: + description: Use a specific OneAgent CodeModule version. type: string type: object classicFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -2886,23 +4385,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -2918,6 +4431,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2926,105 +4442,175 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object cloudNativeFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. type: string dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -3036,15 +4622,26 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3060,6 +4657,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3068,22 +4668,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -3097,21 +4712,32 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3127,6 +4753,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3135,105 +4764,176 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object hostGroup: + description: Sets a host group for OneAgent. type: string hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -3245,23 +4945,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3277,6 +4991,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3285,42 +5002,72 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object type: object proxy: + description: Set custom proxy settings either directly or from a secret + with the field proxy. properties: value: + description: Raw value for given property. nullable: true type: string valueFrom: + description: Name of the secret to get the property from. nullable: true type: string type: object skipCertCheck: + description: Disable certificate check for the connection between + Dynatrace Operator and the Dynatrace Cluster. type: boolean templates: properties: @@ -3329,37 +5076,59 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations to the ExtensionExecutionController + pods type: object customConfig: + description: Defines name of ConfigMap containing custom configuration + file type: string customExtensionCertificates: + description: Defines name of Secret containing certificates + for custom extensions signature validation type: string imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the ExtensionExecutionController + pods type: object persistentVolumeClaim: + description: Defines storage device properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot. properties: apiGroup: + description: APIGroup is the group for the resource + being referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string required: - kind @@ -3367,20 +5136,31 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty... properties: apiGroup: + description: APIGroup is the group for the resource + being referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a... type: string required: - kind - name type: object resources: + description: resources represents the minimum resources + the volume should have. properties: limits: additionalProperties: @@ -3389,6 +5169,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3397,18 +5180,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. type: object type: object selector: + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -3422,26 +5218,44 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: storageClassName is the name of the StorageClass + required by the claim. type: string volumeAttributesClassName: + description: volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. type: string volumeMode: + description: volumeMode defines what type of volume is + required by the claim. type: string volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. type: string type: object resources: + description: Define resources' requests and limits for single + ExtensionExecutionController pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3457,6 +5271,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3465,39 +5282,75 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tlsRefName: type: string tolerations: + description: Set tolerations for the ExtensionExecutionController + pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ExtensionExecutionController + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching + pods. properties: matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that... properties: key: + description: key is the label key that the + selector applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string + values. items: type: string type: array @@ -3511,27 +5364,46 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of + eligible domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -3540,6 +5412,7 @@ spec: type: object type: array useEphemeralVolume: + description: Selects EmptyDir volume to be storage device type: boolean type: object kspmNodeConfigurationCollector: @@ -3547,67 +5420,108 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations for the NodeConfigurationCollector + pods type: object args: + description: Set additional arguments to the NodeConfigurationCollector + pods items: type: string type: array env: + description: Set additional environment variables for the + NodeConfigurationCollector pods items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -3619,32 +5533,59 @@ spec: type: object type: array imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the NodeConfigurationCollector + pods type: object nodeAffinity: + description: Define the nodeAffinity for the DaemonSet of + the NodeConfigurationCollector properties: preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified... items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). properties: preference: + description: A node selector term, associated with + the corresponding weight. properties: matchExpressions: + description: A list of node selector requirements + by node's labels. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3656,13 +5597,25 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: + description: A list of node selector requirements + by node's fields. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3676,6 +5629,8 @@ spec: type: object x-kubernetes-map-type: atomic weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: @@ -3685,18 +5640,38 @@ spec: type: array x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will... properties: nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. properties: matchExpressions: + description: A list of node selector requirements + by node's labels. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3708,13 +5683,25 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: + description: A list of node selector requirements + by node's fields. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3737,17 +5724,29 @@ spec: nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes NodeConfigurationCollector pods will be... type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string resources: + description: Define resources' requests and limits for single + NodeConfigurationCollector pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3763,6 +5762,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3771,81 +5773,136 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tolerations: + description: Set tolerations for the NodeConfigurationCollector + pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array updateStrategy: + description: Define the NodeConfigurationCollector daemonSet + updateStrategy properties: rollingUpdate: + description: Rolling update config params. Present only + if type = "RollingUpdate". properties: maxSurge: anyOf: - type: integer - type: string + description: |- + The maximum number of nodes with an existing available DaemonSet pod that + can have an updated... x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string + description: |- + The maximum number of DaemonSet pods that can be unavailable during the + update. x-kubernetes-int-or-string: true type: object type: + description: Type of daemon set update. Can be "RollingUpdate" + or "OnDelete". Default is RollingUpdate. type: string type: object type: object logMonitoring: + description: Low-level configuration options for the LogMonitoring + feature. properties: annotations: additionalProperties: type: string + description: Add custom annotations to the LogMonitoring pods type: object args: + description: Set additional arguments to the LogMonitoring + main container items: type: string type: array dnsPolicy: + description: Sets DNS Policy for the LogMonitoring pods type: string imageRef: + description: Overrides the default image for the LogMonitoring + pods properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Add custom labels to the LogMonitoring pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes + for the LogMonitoring pods type: object priorityClassName: + description: Assign a priority class to the LogMonitoring + pods. By default, no class is set type: string resources: + description: Define resources' requests and limits for all + the LogMonitoring pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3861,6 +5918,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3869,23 +5929,43 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode for the... type: string tolerations: + description: Set tolerations for the LogMonitoring pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array @@ -3895,30 +5975,47 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations to the OtelCollector + pods type: object imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the OtelCollector + pods type: object replicas: + description: Number of replicas for your OtelCollector format: int32 type: integer resources: + description: Define resources' requests and limits for single + OtelCollector pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -3934,6 +6031,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3942,39 +6042,74 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tlsRefName: type: string tolerations: + description: Set tolerations for the OtelCollector pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the OtelCollector + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching + pods. properties: matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that... properties: key: + description: key is the label key that the + selector applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string + values. items: type: string type: array @@ -3988,27 +6123,46 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of + eligible domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -4019,83 +6173,125 @@ spec: type: object type: object tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. type: string trustedCAs: + description: Adds custom RootCAs from a configmap. Put the certificate + under certs within your configmap. type: string required: - apiUrl type: object status: + description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: + description: Observed state of ActiveGate properties: connectionInfoStatus: + description: Information about Active Gate's connections properties: endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator items: type: string type: array source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object codeModules: + description: Observed state of Code Modules properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -4108,23 +6304,35 @@ spec: type: object type: array dynatraceApi: + description: Observed state of Dynatrace API properties: lastTokenScopeRequest: + description: Time of the last token request format: date-time type: string type: object kspm: + description: Observed state of Kspm properties: tokenSecretHash: + description: TokenSecretHash contains the hash of the token that + is passed to both the ActiveGate and... type: string type: object kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster type: string kubernetesClusterMEID: + description: KubernetesClusterMEID contains the ID of the monitored + entity that points to the Kubernetes cluster type: string kubernetesClusterName: + description: KubernetesClusterName contains the display name (also + know as label) of the monitored entity that... type: string metadataEnrichment: + description: Observed state of Metadata-Enrichment properties: rules: items: @@ -4141,61 +6349,87 @@ spec: type: array type: object oneAgent: + description: Observed state of OneAgent properties: connectionInfoStatus: + description: Information about OneAgent's connections properties: communicationHosts: + description: List of communication hosts items: properties: host: + description: Host domain type: string port: + description: Connection port format: int32 type: integer protocol: + description: Connection protocol type: string type: object type: array endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object healthcheck: + description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: + description: Image ID type: string instances: additionalProperties: properties: ipAddress: + description: IP address of the pod type: string podName: + description: Name of the OneAgent pod type: string type: object + description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: + description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated format: date-time type: string type: object @@ -4217,92 +6451,144 @@ spec: name: v1beta4 schema: openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: DynaKubeSpec defines the desired state of DynaKube properties: activeGate: + description: General configuration about ActiveGate instances. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the ActiveGate pods type: object capabilities: + description: Activegate capabilities enabled (routing, kubernetes-monitoring, + metrics-ingest, dynatrace-api) items: type: string type: array customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced... properties: value: + description: Raw value for given property. nullable: true type: string valueFrom: + description: Name of the secret to get the property from. nullable: true type: string type: object dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods type: string env: + description: List of environment variables to set for the ActiveGate items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its + key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the + specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key + must be defined type: boolean required: - key @@ -4314,31 +6600,46 @@ spec: type: object type: array group: + description: Set activation group for ActiveGate type: string image: + description: The ActiveGate container image. type: string labels: additionalProperties: type: string + description: Adds additional labels for the ActiveGate pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes type: object persistentVolumeClaim: + description: Defines storage device properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot. properties: apiGroup: + description: APIGroup is the group for the resource being + referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string required: - kind @@ -4346,20 +6647,31 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty... properties: apiGroup: + description: APIGroup is the group for the resource being + referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a... type: string required: - kind - name type: object resources: + description: resources represents the minimum resources the + volume should have. properties: limits: additionalProperties: @@ -4368,6 +6680,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4376,18 +6691,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object selector: + description: selector is a label query over volumes to consider + for binding. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4401,31 +6729,51 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: storageClassName is the name of the StorageClass + required by the claim. type: string volumeAttributesClassName: + description: volumeAttributesClassName may be used to set + the VolumeAttributesClass used by this claim. type: string volumeMode: + description: volumeMode defines what type of volume is required + by the claim. type: string volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. type: string type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string replicas: + description: Amount of replicas for your ActiveGates format: int32 type: integer resources: + description: Define resources requests and limits for single ActiveGate + pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in + pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4441,6 +6789,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4449,42 +6800,78 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object terminationGracePeriodSeconds: + description: Configures the terminationGracePeriodSeconds parameter + of the ActiveGate pod. format: int64 type: integer tlsSecretName: + description: The name of a secret containing ActiveGate TLS cert+key + and password. type: string tolerations: + description: Set tolerations for the ActiveGate pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4498,27 +6885,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -4527,22 +6932,33 @@ spec: type: object type: array useEphemeralVolume: + description: UseEphemeralVolume type: boolean type: object apiUrl: + description: Dynatrace apiUrl, including the /api path at the end. maxLength: 128 type: string customPullSecret: + description: Defines a custom pull secret in case you use a private + registry when pulling images from the... type: string dynatraceApiRequestThreshold: + description: Configuration for thresholding Dynatrace API requests. type: integer enableIstio: + description: When enabled, and if Istio is installed on the Kubernetes + environment, Dynatrace Operator will... type: boolean extensions: + description: When an (empty) ExtensionsSpec is provided, the extensions + related components (extensions... type: object kspm: + description: General configuration about the KSPM feature. type: object logMonitoring: + description: General configuration about the LogMonitoring feature. properties: ingestRuleMatchers: items: @@ -4557,19 +6973,32 @@ spec: type: array type: object metadataEnrichment: + description: Configuration for Metadata Enrichment. properties: enabled: + description: Enables MetadataEnrichment, `false` by default. type: boolean namespaceSelector: + description: The namespaces where you want Dynatrace Operator + to inject enrichment. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4583,27 +7012,43 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic type: object networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. type: string oneAgent: + description: General configuration about OneAgent instances. properties: applicationMonitoring: + description: dynatrace-webhook injects into application pods based + on labeled namespaces. nullable: true properties: codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4619,6 +7064,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4627,18 +7075,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4652,84 +7113,130 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic version: + description: Use a specific OneAgent CodeModule version. type: string type: object classicFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -4741,23 +7248,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4773,6 +7294,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4781,107 +7305,179 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will... type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object cloudNativeFullStack: + description: Has a single OneAgent per node via DaemonSet. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean codeModulesImage: + description: Use a custom OneAgent CodeModule image to download + binaries. type: string dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -4893,15 +7489,26 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string initResources: + description: Define resources requests and limits for the + initContainer. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4917,6 +7524,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4925,22 +7535,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object namespaceSelector: + description: Applicable only for applicationMonitoring or + cloudNativeFullStack configuration types. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -4954,21 +7579,32 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -4984,6 +7620,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -4992,107 +7631,180 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will... type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object hostGroup: + description: Sets a host group for OneAgent. type: string hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. nullable: true properties: annotations: additionalProperties: type: string + description: Add custom OneAgent annotations. type: object args: + description: Set additional arguments to the OneAgent installer. items: type: string type: array x-kubernetes-list-type: set autoUpdate: + description: Disables automatic restarts of OneAgent pods + in case a new version is available (https://www. type: boolean dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes. type: string env: + description: Set additional environment variables for the + OneAgent pods. items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -5104,23 +7816,37 @@ spec: type: object type: array image: + description: Use a custom OneAgent image. Defaults to the + latest image from the Dynatrace cluster. type: string labels: additionalProperties: type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. type: object nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. type: object oneAgentResources: + description: Resource settings for OneAgent container. properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5136,6 +7862,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5144,46 +7873,80 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object priorityClassName: + description: Assign a priority class to the OneAgent pods. + By default, no class is set. type: string secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. type: string storageHostPath: + description: StorageHostPath is the writable directory on + the host filesystem where OneAgent configurations will... type: string tolerations: + description: Tolerations to include with the OneAgent DaemonSet. items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array version: + description: Use a specific OneAgent version. Defaults to + the latest version from the Dynatrace cluster. type: string type: object type: object proxy: + description: Set custom proxy settings either directly or from a secret + with the field proxy. properties: value: + description: Raw value for given property. nullable: true type: string valueFrom: + description: Name of the secret to get the property from. nullable: true type: string type: object skipCertCheck: + description: Disable certificate check for the connection between + Dynatrace Operator and the Dynatrace Cluster. type: boolean telemetryIngest: + description: When a TelemetryIngestSpec is provided, the OTEL collector + is deployed by the operator. properties: protocols: items: @@ -5201,37 +7964,59 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations to the ExtensionExecutionController + pods type: object customConfig: + description: Defines name of ConfigMap containing custom configuration + file type: string customExtensionCertificates: + description: Defines name of Secret containing certificates + for custom extensions signature validation type: string imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the ExtensionExecutionController + pods type: object persistentVolumeClaim: + description: Defines storage device properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot. properties: apiGroup: + description: APIGroup is the group for the resource + being referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string required: - kind @@ -5239,20 +8024,31 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty... properties: apiGroup: + description: APIGroup is the group for the resource + being referenced. type: string kind: + description: Kind is the type of resource being referenced type: string name: + description: Name is the name of resource being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a... type: string required: - kind - name type: object resources: + description: resources represents the minimum resources + the volume should have. properties: limits: additionalProperties: @@ -5261,6 +8057,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5269,18 +8068,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. type: object type: object selector: + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -5294,26 +8106,44 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: storageClassName is the name of the StorageClass + required by the claim. type: string volumeAttributesClassName: + description: volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. type: string volumeMode: + description: volumeMode defines what type of volume is + required by the claim. type: string volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. type: string type: object resources: + description: Define resources' requests and limits for single + ExtensionExecutionController pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5329,6 +8159,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5337,39 +8170,75 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tlsRefName: type: string tolerations: + description: Set tolerations for the ExtensionExecutionController + pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ExtensionExecutionController + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching + pods. properties: matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that... properties: key: + description: key is the label key that the + selector applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string + values. items: type: string type: array @@ -5383,27 +8252,46 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of + eligible domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -5412,6 +8300,7 @@ spec: type: object type: array useEphemeralVolume: + description: Selects EmptyDir volume to be storage device type: boolean type: object kspmNodeConfigurationCollector: @@ -5419,67 +8308,108 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations for the NodeConfigurationCollector + pods type: object args: + description: Set additional arguments to the NodeConfigurationCollector + pods items: type: string type: array env: + description: Set additional environment variables for the + NodeConfigurationCollector pods items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -5491,32 +8421,59 @@ spec: type: object type: array imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the NodeConfigurationCollector + pods type: object nodeAffinity: + description: Define the nodeAffinity for the DaemonSet of + the NodeConfigurationCollector properties: preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified... items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). properties: preference: + description: A node selector term, associated with + the corresponding weight. properties: matchExpressions: + description: A list of node selector requirements + by node's labels. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -5528,13 +8485,25 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: + description: A list of node selector requirements + by node's fields. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -5548,6 +8517,8 @@ spec: type: object x-kubernetes-map-type: atomic weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: @@ -5557,18 +8528,38 @@ spec: type: array x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will... properties: nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. properties: matchExpressions: + description: A list of node selector requirements + by node's labels. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -5580,13 +8571,25 @@ spec: type: array x-kubernetes-list-type: atomic matchFields: + description: A list of node selector requirements + by node's fields. items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates... properties: key: + description: The label key that the selector + applies to. type: string operator: + description: Represents a key's relationship + to a set of values. type: string values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -5609,17 +8612,29 @@ spec: nodeSelector: additionalProperties: type: string + description: Specify the node selector that controls on which + nodes NodeConfigurationCollector pods will be... type: object priorityClassName: + description: If specified, indicates the pod's priority. type: string resources: + description: Define resources' requests and limits for single + NodeConfigurationCollector pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5635,6 +8650,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5643,81 +8661,136 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tolerations: + description: Set tolerations for the NodeConfigurationCollector + pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array updateStrategy: + description: Define the NodeConfigurationCollector daemonSet + updateStrategy properties: rollingUpdate: + description: Rolling update config params. Present only + if type = "RollingUpdate". properties: maxSurge: anyOf: - type: integer - type: string + description: |- + The maximum number of nodes with an existing available DaemonSet pod that + can have an updated... x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string + description: |- + The maximum number of DaemonSet pods that can be unavailable during the + update. x-kubernetes-int-or-string: true type: object type: + description: Type of daemon set update. Can be "RollingUpdate" + or "OnDelete". Default is RollingUpdate. type: string type: object type: object logMonitoring: + description: Low-level configuration options for the LogMonitoring + feature. properties: annotations: additionalProperties: type: string + description: Add custom annotations to the LogMonitoring pods type: object args: + description: Set additional arguments to the LogMonitoring + main container items: type: string type: array dnsPolicy: + description: Sets DNS Policy for the LogMonitoring pods type: string imageRef: + description: Overrides the default image for the LogMonitoring + pods properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Add custom labels to the LogMonitoring pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes + for the LogMonitoring pods type: object priorityClassName: + description: Assign a priority class to the LogMonitoring + pods. By default, no class is set type: string resources: + description: Define resources' requests and limits for all + the LogMonitoring pods properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5733,6 +8806,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5741,23 +8817,43 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode for the... type: string tolerations: + description: Set tolerations for the LogMonitoring pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array @@ -5767,30 +8863,47 @@ spec: annotations: additionalProperties: type: string + description: Adds additional annotations to the OtelCollector + pods type: object imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object labels: additionalProperties: type: string + description: Adds additional labels for the OtelCollector + pods type: object replicas: + description: Number of replicas for your OtelCollector format: int32 type: integer resources: + description: Define resources' requests and limits for single + OtelCollector pod properties: claims: + description: Claims lists the names of resources, defined + in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry + in pod.spec. type: string request: + description: Request is the name chosen for a request + in the referenced claim. type: string required: - name @@ -5806,6 +8919,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -5814,39 +8930,74 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. type: object type: object tlsRefName: type: string tolerations: + description: Set tolerations for the OtelCollector pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. type: string key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration + matches to. type: string type: object type: array topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the OtelCollector + pods items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching + pods. properties: matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that... properties: key: + description: key is the label key that the + selector applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string + values. items: type: string type: array @@ -5860,27 +9011,46 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of + eligible domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -5891,83 +9061,125 @@ spec: type: object type: object tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. type: string trustedCAs: + description: Adds custom RootCAs from a configmap. Put the certificate + under certs within your configmap. type: string required: - apiUrl type: object status: + description: DynaKubeStatus defines the observed state of DynaKube properties: activeGate: + description: Observed state of ActiveGate properties: connectionInfoStatus: + description: Information about Active Gate's connections properties: endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator items: type: string type: array source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object codeModules: + description: Observed state of Code Modules properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -5980,23 +9192,35 @@ spec: type: object type: array dynatraceApi: + description: Observed state of Dynatrace API properties: lastTokenScopeRequest: + description: Time of the last token request format: date-time type: string type: object kspm: + description: Observed state of Kspm properties: tokenSecretHash: + description: TokenSecretHash contains the hash of the token that + is passed to both the ActiveGate and... type: string type: object kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster type: string kubernetesClusterMEID: + description: KubernetesClusterMEID contains the ID of the monitored + entity that points to the Kubernetes cluster type: string kubernetesClusterName: + description: KubernetesClusterName contains the display name (also + know as label) of the monitored entity that... type: string metadataEnrichment: + description: Observed state of Metadata-Enrichment properties: rules: items: @@ -6013,61 +9237,87 @@ spec: type: array type: object oneAgent: + description: Observed state of OneAgent properties: connectionInfoStatus: + description: Information about OneAgent's connections properties: communicationHosts: + description: List of communication hosts items: properties: host: + description: Host domain type: string port: + description: Connection port format: int32 type: integer protocol: + description: Connection protocol type: string type: object type: array endpoints: + description: Available connection endpoints type: string lastRequest: + description: Time of the last connection request format: date-time type: string tenantTokenHash: + description: Hash of the tenant token type: string tenantUUID: + description: UUID of the tenant, received from the tenant type: string type: object healthcheck: + description: Commands used for OneAgent's readiness probe type: object x-kubernetes-preserve-unknown-fields: true imageID: + description: Image ID type: string instances: additionalProperties: properties: ipAddress: + description: IP address of the pod type: string podName: + description: Name of the OneAgent pod type: string type: object + description: List of deployed OneAgent instances type: object lastInstanceStatusUpdate: + description: Time of the last instance status update format: date-time type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated format: date-time type: string type: object @@ -6122,84 +9372,132 @@ spec: name: v1alpha1 schema: openAPIV3Schema: + description: EdgeConnect is the Schema for the EdgeConnect API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: EdgeConnectSpec defines the desired state of EdgeConnect. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the EdgeConnect pods type: object apiServer: + description: Location of the Dynatrace API to connect to, including + your specific environment UUID type: string autoUpdate: default: true + description: Enables automatic restarts of EdgeConnect pods in case + a new version is available (the default... type: boolean caCertsRef: + description: Adds custom root certificate from a configmap. type: string customPullSecret: + description: Pull secret for your private registry type: string env: + description: Adds additional environment variables to the EdgeConnect + pods items: + description: EnvVar represents an environment variable present in + a Container. properties: name: + description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its key + must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the specified + API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key must + be defined type: boolean required: - key @@ -6211,42 +9509,63 @@ spec: type: object type: array hostPatterns: + description: Host patterns to be set in the tenant, only considered + when provisioning is enabled. items: type: string type: array hostRestrictions: + description: Restrict outgoing HTTP requests to your internal resources + to specified hosts example: internal.example.org,*.dev.example.org type: string imageRef: + description: Overrides the default image properties: repository: + description: Custom EdgeConnect image repository example: docker.io/dynatrace/edgeconnect type: string tag: + description: Indicates version of the EdgeConnect image to use type: string type: object kubernetesAutomation: + description: KubernetesAutomation enables Kubernetes Automation for + Workflows properties: enabled: + description: Enables Kubernetes Automation for Workflows type: boolean type: object labels: additionalProperties: type: string + description: Adds additional labels to the EdgeConnect pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes for the + EdgeConnect pods type: object oauth: + description: EdgeConnect uses the OAuth client to authenticate itself + with the Dynatrace platform. properties: clientSecret: + description: Name of the secret that holds oauth clientId/secret type: string endpoint: + description: Token endpoint URL of Dynatrace SSO type: string provisioner: + description: Determines if the operator will create the EdgeConnect + and light OAuth client on the cluster using... type: boolean resource: + description: URN identifying your account. You get the URN when + creating the OAuth client type: string required: - clientSecret @@ -6254,29 +9573,45 @@ spec: - resource type: object proxy: + description: General configurations for proxy settings. properties: authRef: + description: Secret name which contains the username and password + used for authentication with the proxy, using... type: string host: + description: Server address (hostname or IP address) of the proxy. type: string noProxy: + description: |- + NoProxy represents the NO_PROXY or no_proxy environment + variable. type: string port: + description: Port of the proxy. format: int32 type: integer type: object replicas: default: 1 + description: 'Amount of replicas for your EdgeConnect (the default + value is: 1)' format: int32 type: integer resources: + description: Defines resources requests and limits for single pods properties: claims: + description: Claims lists the names of resources, defined in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in pod.spec. type: string request: + description: Request is the name chosen for a request in + the referenced claim. type: string required: - name @@ -6292,6 +9627,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -6300,40 +9638,74 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object serviceAccountName: default: dynatrace-edgeconnect + description: ServiceAccountName that allows EdgeConnect to access + the Kubernetes API type: string tolerations: + description: Sets tolerations for the EdgeConnect pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Sets topology spread constraints for the EdgeConnect + pods items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -6347,27 +9719,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods may + be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -6380,32 +9770,47 @@ spec: - oauth type: object status: + description: EdgeConnectStatus defines the observed state of EdgeConnect. properties: conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -6418,24 +9823,36 @@ spec: type: object type: array kubeSystemUID: + description: kube-system namespace uid type: string phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: Indicates when the resource was last updated format: date-time type: string version: + description: Version used for the Edgeconnect image properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object type: object @@ -6457,83 +9874,131 @@ spec: name: v1alpha2 schema: openAPIV3Schema: + description: EdgeConnect is the Schema for the EdgeConnect API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: EdgeConnectSpec defines the desired state of EdgeConnect. properties: annotations: additionalProperties: type: string + description: Adds additional annotations to the EdgeConnect pods type: object apiServer: + description: Location of the Dynatrace API to connect to, including + your specific environment UUID type: string autoUpdate: + description: Enables automatic restarts of EdgeConnect pods in case + a new version is available (the default... type: boolean caCertsRef: + description: Adds custom root certificate from a configmap. type: string customPullSecret: + description: Pull secret for your private registry type: string env: + description: Adds additional environment variables to the EdgeConnect + pods items: + description: EnvVar represents an environment variable present in + a Container. properties: name: + description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in... type: string valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the ConfigMap or its key + must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in the specified + API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's namespace properties: key: + description: The key of the secret to select from. Must + be a valid secret key. type: string name: default: "" + description: Name of the referent. type: string optional: + description: Specify whether the Secret or its key must + be defined type: boolean required: - key @@ -6545,44 +10010,65 @@ spec: type: object type: array hostPatterns: + description: Host patterns to be set in the tenant, only considered + when provisioning is enabled. items: type: string type: array hostRestrictions: + description: Restrict outgoing HTTP requests to your internal resources + to specified hosts example: internal.example.org,*.dev.example.org items: type: string type: array imageRef: + description: Overrides the default image properties: repository: + description: Custom image repository example: docker.io/dynatrace/image-name type: string tag: + description: Indicates a tag of the image to use type: string type: object kubernetesAutomation: + description: KubernetesAutomation enables Kubernetes Automation for + Workflows properties: enabled: + description: Enables Kubernetes Automation for Workflows type: boolean type: object labels: additionalProperties: type: string + description: Adds additional labels to the EdgeConnect pods type: object nodeSelector: additionalProperties: type: string + description: Node selector to control the selection of nodes for the + EdgeConnect pods type: object oauth: + description: EdgeConnect uses the OAuth client to authenticate itself + with the Dynatrace platform. properties: clientSecret: + description: Name of the secret that holds oauth clientId/secret type: string endpoint: + description: Token endpoint URL of Dynatrace SSO type: string provisioner: + description: Determines if the operator will create the EdgeConnect + and light OAuth client on the cluster using... type: boolean resource: + description: URN identifying your account. You get the URN when + creating the OAuth client type: string required: - clientSecret @@ -6590,28 +10076,44 @@ spec: - resource type: object proxy: + description: General configurations for proxy settings. properties: authRef: + description: Secret name which contains the username and password + used for authentication with the proxy, using... type: string host: + description: Server address (hostname or IP address) of the proxy. type: string noProxy: + description: |- + NoProxy represents the NO_PROXY or no_proxy environment + variable. type: string port: + description: Port of the proxy. format: int32 type: integer type: object replicas: + description: 'Amount of replicas for your EdgeConnect (the default + value is: 1)' format: int32 type: integer resources: + description: Defines resources requests and limits for single pods properties: claims: + description: Claims lists the names of resources, defined in spec. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: Name must match the name of one entry in pod.spec. type: string request: + description: Request is the name chosen for a request in + the referenced claim. type: string required: - name @@ -6627,6 +10129,9 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -6635,39 +10140,73 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. type: object type: object serviceAccountName: + description: ServiceAccountName that allows EdgeConnect to access + the Kubernetes API type: string tolerations: + description: Sets tolerations for the EdgeConnect pods items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple... properties: effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. type: string key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. type: string operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. type: string tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute,... format: int64 type: integer value: + description: Value is the taint value the toleration matches + to. type: string type: object type: array topologySpreadConstraints: + description: Sets topology spread constraints for the EdgeConnect + pods items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. properties: labelSelector: + description: LabelSelector is used to find matching pods. properties: matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that... properties: key: + description: key is the label key that the selector + applies to. type: string operator: + description: operator represents a key's relationship + to a set of values. type: string values: + description: values is an array of string values. items: type: string type: array @@ -6681,27 +10220,45 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be... items: type: string type: array x-kubernetes-list-type: atomic maxSkew: + description: MaxSkew describes the degree to which pods may + be unevenly distributed. format: int32 type: integer minDomains: + description: MinDomains indicates a minimum number of eligible + domains. format: int32 type: integer nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod... type: string nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. type: string topologyKey: + description: TopologyKey is the key of node labels. type: string whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. type: string required: - maxSkew @@ -6714,32 +10271,47 @@ spec: - oauth type: object status: + description: EdgeConnectStatus defines the observed state of EdgeConnect. properties: conditions: + description: Conditions includes status about the current state of + the instance items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: message is a human readable message indicating + details about the transition. maxLength: 32768 type: string observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -6752,24 +10324,36 @@ spec: type: object type: array kubeSystemUID: + description: kube-system namespace uid type: string phase: + description: Defines the current state (Running, Updating, Error, + ...) type: string updatedTimestamp: + description: Indicates when the resource was last updated format: date-time type: string version: + description: Version used for the Edgeconnect image properties: imageID: + description: Image ID type: string lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed format: date-time type: string source: + description: Source of the image (tenant-registry, public-registry, + ...) type: string type: + description: Image type type: string version: + description: Image version type: string type: object type: object diff --git a/doc/api/dynakube-api-ref.md b/doc/api/dynakube-api-ref.md index b176b0e065..31f2787526 100644 --- a/doc/api/dynakube-api-ref.md +++ b/doc/api/dynakube-api-ref.md @@ -4,45 +4,45 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`apiUrl`||-|string| -|`customPullSecret`||-|string| -|`dynatraceApiRequestThreshold`||-|integer| -|`enableIstio`||-|boolean| -|`extensions`||-|object| -|`kspm`||-|object| -|`networkZone`||-|string| -|`proxy`||-|object| -|`skipCertCheck`||-|boolean| -|`tokens`||-|string| -|`trustedCAs`||-|string| +|`apiUrl`|Dynatrace apiUrl, including the /api path at the end.|-|string| +|`customPullSecret`|Defines a custom pull secret in case you use a private registry when pulling images from the...|-|string| +|`dynatraceApiRequestThreshold`|Configuration for thresholding Dynatrace API requests.|-|integer| +|`enableIstio`|When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will...|-|boolean| +|`extensions`|When an (empty) ExtensionsSpec is provided, the extensions related components (extensions...|-|object| +|`kspm`|General configuration about the KSPM feature.|-|object| +|`networkZone`|Sets a network zone for the OneAgent and ActiveGate pods.|-|string| +|`proxy`|Set custom proxy settings either directly or from a secret with the field proxy.|-|object| +|`skipCertCheck`|Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster.|-|boolean| +|`tokens`|Name of the secret holding the tokens used for connecting to Dynatrace.|-|string| +|`trustedCAs`|Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap.|-|string| ### .spec.oneAgent |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`hostGroup`||-|string| +|`hostGroup`|Sets a host group for OneAgent.|-|string| ### .spec.activeGate |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`||-|object| -|`capabilities`||-|array| -|`customProperties`||-|object| -|`dnsPolicy`||-|string| -|`env`||-|array| -|`group`||-|string| -|`image`||-|string| -|`labels`||-|object| -|`nodeSelector`||-|object| -|`priorityClassName`||-|string| -|`replicas`||-|integer| -|`resources`||-|object| -|`terminationGracePeriodSeconds`||-|integer| -|`tlsSecretName`||-|string| -|`tolerations`||-|array| -|`topologySpreadConstraints`||-|array| -|`useEphemeralVolume`||-|boolean| +|`annotations`|Adds additional annotations to the ActiveGate pods|-|object| +|`capabilities`|Activegate capabilities enabled (routing, kubernetes-monitoring, metrics-ingest, dynatrace-api)|-|array| +|`customProperties`|Add a custom properties file by providing it as a value or reference it from a secret
If referenced...|-|object| +|`dnsPolicy`|Sets DNS Policy for the ActiveGate pods|-|string| +|`env`|List of environment variables to set for the ActiveGate|-|array| +|`group`|Set activation group for ActiveGate|-|string| +|`image`|The ActiveGate container image.|-|string| +|`labels`|Adds additional labels for the ActiveGate pods|-|object| +|`nodeSelector`|Node selector to control the selection of nodes|-|object| +|`priorityClassName`|If specified, indicates the pod's priority.|-|string| +|`replicas`|Amount of replicas for your ActiveGates|-|integer| +|`resources`|Define resources requests and limits for single ActiveGate pods|-|object| +|`terminationGracePeriodSeconds`|Configures the terminationGracePeriodSeconds parameter of the ActiveGate pod.|-|integer| +|`tlsSecretName`|The name of a secret containing ActiveGate TLS cert+key and password.|-|string| +|`tolerations`|Set tolerations for the ActiveGate pods|-|array| +|`topologySpreadConstraints`|Adds TopologySpreadConstraints for the ActiveGate pods|-|array| +|`useEphemeralVolume`|UseEphemeralVolume|-|boolean| ### .spec.logMonitoring @@ -62,219 +62,219 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`enabled`||-|boolean| -|`namespaceSelector`||-|object| +|`enabled`|Enables MetadataEnrichment, `false` by default.|-|boolean| +|`namespaceSelector`|The namespaces where you want Dynatrace Operator to inject enrichment.|-|object| ### .spec.oneAgent.hostMonitoring |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`||-|object| -|`args`||-|array| -|`autoUpdate`||-|boolean| -|`dnsPolicy`||-|string| -|`env`||-|array| -|`image`||-|string| -|`labels`||-|object| -|`nodeSelector`||-|object| -|`oneAgentResources`||-|object| -|`priorityClassName`||-|string| -|`secCompProfile`||-|string| -|`storageHostPath`||-|string| -|`tolerations`||-|array| -|`version`||-|string| +|`annotations`|Add custom OneAgent annotations.|-|object| +|`args`|Set additional arguments to the OneAgent installer.|-|array| +|`autoUpdate`|Disables automatic restarts of OneAgent pods in case a new version is available (More info: https://kubernetes.|-|array| +|`dataSource`|dataSource field can be used to specify either:
* An existing VolumeSnapshot object (snapshot.|-|object| +|`resources`|resources represents the minimum resources the volume should have.|-|object| +|`selector`|selector is a label query over volumes to consider for binding.|-|object| +|`storageClassName`|storageClassName is the name of the StorageClass required by the claim.|-|string| +|`volumeAttributesClassName`|volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.|-|string| +|`volumeMode`|volumeMode defines what type of volume is required by the claim.|-|string| +|`volumeName`|volumeName is the binding reference to the PersistentVolume backing this claim.|-|string| ### .spec.templates.logMonitoring.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`||-|string| -|`tag`||-|string| +|`repository`|Custom image repository|-|string| +|`tag`|Indicates a tag of the image to use|-|string| ### .spec.templates.otelCollector.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`||-|string| -|`tag`||-|string| +|`repository`|Custom image repository|-|string| +|`tag`|Indicates a tag of the image to use|-|string| ### .spec.templates.extensionExecutionController |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`||-|object| -|`customConfig`||-|string| -|`customExtensionCertificates`||-|string| -|`labels`||-|object| -|`resources`||-|object| +|`annotations`|Adds additional annotations to the ExtensionExecutionController pods|-|object| +|`customConfig`|Defines name of ConfigMap containing custom configuration file|-|string| +|`customExtensionCertificates`|Defines name of Secret containing certificates for custom extensions signature validation|-|string| +|`labels`|Adds additional labels for the ExtensionExecutionController pods|-|object| +|`resources`|Define resources' requests and limits for single ExtensionExecutionController pod|-|object| |`tlsRefName`||-|string| -|`tolerations`||-|array| -|`topologySpreadConstraints`||-|array| -|`useEphemeralVolume`||-|boolean| +|`tolerations`|Set tolerations for the ExtensionExecutionController pods|-|array| +|`topologySpreadConstraints`|Adds TopologySpreadConstraints for the ExtensionExecutionController pods|-|array| +|`useEphemeralVolume`|Selects EmptyDir volume to be storage device|-|boolean| ### .spec.templates.kspmNodeConfigurationCollector |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`||-|object| -|`args`||-|array| -|`env`||-|array| -|`labels`||-|object| -|`nodeSelector`||-|object| -|`priorityClassName`||-|string| -|`resources`||-|object| -|`tolerations`||-|array| +|`annotations`|Adds additional annotations for the NodeConfigurationCollector pods|-|object| +|`args`|Set additional arguments to the NodeConfigurationCollector pods|-|array| +|`env`|Set additional environment variables for the NodeConfigurationCollector pods|-|array| +|`labels`|Adds additional labels for the NodeConfigurationCollector pods|-|object| +|`nodeSelector`|Specify the node selector that controls on which nodes NodeConfigurationCollector pods will be...|-|object| +|`priorityClassName`|If specified, indicates the pod's priority.|-|string| +|`resources`|Define resources' requests and limits for single NodeConfigurationCollector pod|-|object| +|`tolerations`|Set tolerations for the NodeConfigurationCollector pods|-|array| ### .spec.activeGate.persistentVolumeClaim.dataSourceRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`apiGroup`||-|string| -|`kind`||-|string| -|`name`||-|string| -|`namespace`||-|string| +|`apiGroup`|APIGroup is the group for the resource being referenced.|-|string| +|`kind`|Kind is the type of resource being referenced|-|string| +|`name`|Name is the name of resource being referenced|-|string| +|`namespace`|Namespace is the namespace of resource being referenced
Note that when a namespace is specified, a...|-|string| ### .spec.templates.extensionExecutionController.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`||-|string| -|`tag`||-|string| +|`repository`|Custom image repository|-|string| +|`tag`|Indicates a tag of the image to use|-|string| ### .spec.templates.kspmNodeConfigurationCollector.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`||-|string| -|`tag`||-|string| +|`repository`|Custom image repository|-|string| +|`tag`|Indicates a tag of the image to use|-|string| ### .spec.templates.kspmNodeConfigurationCollector.nodeAffinity |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`preferredDuringSchedulingIgnoredDuringExecution`||-|array| -|`requiredDuringSchedulingIgnoredDuringExecution`||-|object| +|`preferredDuringSchedulingIgnoredDuringExecution`|The scheduler will prefer to schedule pods to nodes that satisfy
the affinity expressions specified...|-|array| +|`requiredDuringSchedulingIgnoredDuringExecution`|If the affinity requirements specified by this field are not met at
scheduling time, the pod will...|-|object| ### .spec.templates.kspmNodeConfigurationCollector.updateStrategy |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`type`||-|string| +|`type`|Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is RollingUpdate.|-|string| ### .spec.templates.extensionExecutionController.persistentVolumeClaim |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`accessModes`||-|array| -|`dataSource`||-|object| -|`resources`||-|object| -|`selector`||-|object| -|`storageClassName`||-|string| -|`volumeAttributesClassName`||-|string| -|`volumeMode`||-|string| -|`volumeName`||-|string| +|`accessModes`|accessModes contains the desired access modes the volume should have.
More info: https://kubernetes.|-|array| +|`dataSource`|dataSource field can be used to specify either:
* An existing VolumeSnapshot object (snapshot.|-|object| +|`resources`|resources represents the minimum resources the volume should have.|-|object| +|`selector`|selector is a label query over volumes to consider for binding.|-|object| +|`storageClassName`|storageClassName is the name of the StorageClass required by the claim.|-|string| +|`volumeAttributesClassName`|volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.|-|string| +|`volumeMode`|volumeMode defines what type of volume is required by the claim.|-|string| +|`volumeName`|volumeName is the binding reference to the PersistentVolume backing this claim.|-|string| ### .spec.templates.kspmNodeConfigurationCollector.updateStrategy.rollingUpdate |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`maxSurge`||-|integer or string| -|`maxUnavailable`||-|integer or string| +|`maxSurge`|The maximum number of nodes with an existing available DaemonSet pod that
can have an updated...|-|integer or string| +|`maxUnavailable`|The maximum number of DaemonSet pods that can be unavailable during the
update.|-|integer or string| ### .spec.templates.extensionExecutionController.persistentVolumeClaim.dataSourceRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`apiGroup`||-|string| -|`kind`||-|string| -|`name`||-|string| -|`namespace`||-|string| +|`apiGroup`|APIGroup is the group for the resource being referenced.|-|string| +|`kind`|Kind is the type of resource being referenced|-|string| +|`name`|Name is the name of resource being referenced|-|string| +|`namespace`|Namespace is the namespace of resource being referenced
Note that when a namespace is specified, a...|-|string| diff --git a/doc/api/edgeconnect-api-ref.md b/doc/api/edgeconnect-api-ref.md index e6336e9d35..afab83dc88 100644 --- a/doc/api/edgeconnect-api-ref.md +++ b/doc/api/edgeconnect-api-ref.md @@ -4,49 +4,49 @@ |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`annotations`||-|object| -|`apiServer`||-|string| -|`autoUpdate`||-|boolean| -|`caCertsRef`||-|string| -|`customPullSecret`||-|string| -|`env`||-|array| -|`hostPatterns`||-|array| -|`hostRestrictions`||-|array| -|`labels`||-|object| -|`nodeSelector`||-|object| -|`replicas`||-|integer| -|`resources`||-|object| -|`serviceAccountName`||-|string| -|`tolerations`||-|array| -|`topologySpreadConstraints`||-|array| +|`annotations`|Adds additional annotations to the EdgeConnect pods|-|object| +|`apiServer`|Location of the Dynatrace API to connect to, including your specific environment UUID|-|string| +|`autoUpdate`|Enables automatic restarts of EdgeConnect pods in case a new version is available (the default...|-|boolean| +|`caCertsRef`|Adds custom root certificate from a configmap.|-|string| +|`customPullSecret`|Pull secret for your private registry|-|string| +|`env`|Adds additional environment variables to the EdgeConnect pods|-|array| +|`hostPatterns`|Host patterns to be set in the tenant, only considered when provisioning is enabled.|-|array| +|`hostRestrictions`|Restrict outgoing HTTP requests to your internal resources to specified hosts|-|array| +|`labels`|Adds additional labels to the EdgeConnect pods|-|object| +|`nodeSelector`|Node selector to control the selection of nodes for the EdgeConnect pods|-|object| +|`replicas`|Amount of replicas for your EdgeConnect (the default value is: 1)|-|integer| +|`resources`|Defines resources requests and limits for single pods|-|object| +|`serviceAccountName`|ServiceAccountName that allows EdgeConnect to access the Kubernetes API|-|string| +|`tolerations`|Sets tolerations for the EdgeConnect pods|-|array| +|`topologySpreadConstraints`|Sets topology spread constraints for the EdgeConnect pods|-|array| ### .spec.oauth |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`clientSecret`||-|string| -|`endpoint`||-|string| -|`provisioner`||-|boolean| -|`resource`||-|string| +|`clientSecret`|Name of the secret that holds oauth clientId/secret|-|string| +|`endpoint`|Token endpoint URL of Dynatrace SSO|-|string| +|`provisioner`|Determines if the operator will create the EdgeConnect and light OAuth client on the cluster using...|-|boolean| +|`resource`|URN identifying your account. You get the URN when creating the OAuth client|-|string| ### .spec.proxy |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`authRef`||-|string| -|`host`||-|string| -|`noProxy`||-|string| -|`port`||-|integer| +|`authRef`|Secret name which contains the username and password used for authentication with the proxy, using...|-|string| +|`host`|Server address (hostname or IP address) of the proxy.|-|string| +|`noProxy`|NoProxy represents the NO_PROXY or no_proxy environment
variable.|-|string| +|`port`|Port of the proxy.|-|integer| ### .spec.imageRef |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`repository`||-|string| -|`tag`||-|string| +|`repository`|Custom image repository|-|string| +|`tag`|Indicates a tag of the image to use|-|string| ### .spec.kubernetesAutomation |Parameter|Description|Default value|Data type| |:-|:-|:-|:-| -|`enabled`||-|boolean| +|`enabled`|Enables Kubernetes Automation for Workflows|-|boolean| From a02e3f9a4d1ed90c1718c95ded594af3c44ae00a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 19 Apr 2025 05:23:42 +0000 Subject: [PATCH 419/426] chore(deps): update softprops/action-gh-release action to v2.2.2 (release-1.5) (#4785) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9fbe0eb3e4..bacd873556 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -307,7 +307,7 @@ jobs: mkdir -p tmp echo ${COSIGN_PUBLIC_KEY} | base64 -d > tmp/cosign.pub - name: Create pre-release - uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 + uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2 if: ${{ contains(github.ref, '-rc.') }} with: body_path: ./CHANGELOG.md @@ -323,7 +323,7 @@ jobs: draft: true fail_on_unmatched_files: true - name: Create release - uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 + uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2 if: ${{ !contains(github.ref, '-rc.') }} with: body_path: ./CHANGELOG.md From 5b9b8cc24b2ddcf74e3b11af25985f790a5e422d Mon Sep 17 00:00:00 2001 From: StefanHauth <63204425+StefanHauth@users.noreply.github.com> Date: Tue, 22 Apr 2025 08:54:49 +0200 Subject: [PATCH 420/426] Fix cleanup of unused agent versions. (#4783) Co-authored-by: Marcell Sevcsik --- pkg/controllers/csi/metadata/correctness.go | 6 +++--- pkg/controllers/csi/metadata/correctness_test.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/controllers/csi/metadata/correctness.go b/pkg/controllers/csi/metadata/correctness.go index 8028816dff..a542663841 100644 --- a/pkg/controllers/csi/metadata/correctness.go +++ b/pkg/controllers/csi/metadata/correctness.go @@ -176,13 +176,13 @@ func GetRelevantOverlayMounts(mounter mount.Interface, baseFolder string) ([]Ove for _, opt := range mountPoint.Opts { switch { case strings.HasPrefix(opt, "lowerdir="): - split := strings.Split(opt, "=") + split := strings.SplitN(opt, "=", 2) overlayMount.LowerDir = split[1] case strings.HasPrefix(opt, "upperdir="): - split := strings.Split(opt, "=") + split := strings.SplitN(opt, "=", 2) overlayMount.UpperDir = split[1] case strings.HasPrefix(opt, "workdir="): - split := strings.Split(opt, "=") + split := strings.SplitN(opt, "=", 2) overlayMount.WorkDir = split[1] } } diff --git a/pkg/controllers/csi/metadata/correctness_test.go b/pkg/controllers/csi/metadata/correctness_test.go index aeb200c339..e7c5521c39 100644 --- a/pkg/controllers/csi/metadata/correctness_test.go +++ b/pkg/controllers/csi/metadata/correctness_test.go @@ -12,9 +12,9 @@ func TestGetRelevantOverlayMounts(t *testing.T) { t.Run("get only relevant mounts", func(t *testing.T) { baseFolder := "/test/folder" expectedPath := baseFolder + "/some/sub/folder" - expectedLowerDir := "/test/lower" - expectedUpperDir := "/test/upper" - expectedWorkDir := "/test/work" + expectedLowerDir := "/data/codemodules/cXVheS5pby9keW5hdHJhY2UvZHluYXRyYWNlLWJvb3RzdHJhcHBlcjpzbmFwc2hvdA==" + expectedUpperDir := "/data/appmounts/csi-a3dd8a9ab6e64e92efca99a0d180da60ab807f0e31a04e11edb451311130211c/var" + expectedWorkDir := "/data/appmounts/csi-a3dd8a9ab6e64e92efca99a0d180da60ab807f0e31a04e11edb451311130211c/work" relevantMountPoint := mount.MountPoint{ Device: "overlay", From 2f1768bfb53e7c0318226be011512ee481b2d228 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 22 Apr 2025 09:32:52 +0000 Subject: [PATCH 421/426] fix(deps): update module github.com/dynatrace/dynatrace-bootstrapper to v1.0.3 (release-1.5) (#4789) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index cedcbf68cc..28f6477b59 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Dynatrace/dynatrace-operator go 1.23.4 require ( - github.com/Dynatrace/dynatrace-bootstrapper v1.0.2 + github.com/Dynatrace/dynatrace-bootstrapper v1.0.3 github.com/container-storage-interface/spec v1.11.0 github.com/docker/cli v28.0.4+incompatible github.com/evanphx/json-patch v5.9.11+incompatible @@ -26,7 +26,7 @@ require ( golang.org/x/mod v0.24.0 golang.org/x/net v0.38.0 golang.org/x/oauth2 v0.28.0 - golang.org/x/sys v0.31.0 + golang.org/x/sys v0.32.0 google.golang.org/grpc v1.71.1 gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.25.2 diff --git a/go.sum b/go.sum index 1b9cecb41f..88090faed7 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/Dynatrace/dynatrace-bootstrapper v1.0.2 h1:IdjAJwJ7sT+q0TTyQxGcJlUif5Y7lVYJWJUQ/u/h0Tw= -github.com/Dynatrace/dynatrace-bootstrapper v1.0.2/go.mod h1:iNHaw8wmanlJCBkKG7LzAJjWDZCo3xxZmwxM33Zm4GU= +github.com/Dynatrace/dynatrace-bootstrapper v1.0.3 h1:rjYpJfoD8k42sAdQlEkZOGQXGgpCZNu+v2ZYHKWul3s= +github.com/Dynatrace/dynatrace-bootstrapper v1.0.3/go.mod h1:LHHsJDxADbZ/41Sf+VVrRuhMhQeua4/y5f8N9My5Hk0= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -335,8 +335,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 47a551cdfbf3b718f276b61badbb5c944e34bf51 Mon Sep 17 00:00:00 2001 From: Stefan Hauth Date: Tue, 22 Apr 2025 11:39:02 +0200 Subject: [PATCH 422/426] Remove node image pull sample. --- .../dynakube/v1beta4/node-image-pull.yaml | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 assets/samples/dynakube/v1beta4/node-image-pull.yaml diff --git a/assets/samples/dynakube/v1beta4/node-image-pull.yaml b/assets/samples/dynakube/v1beta4/node-image-pull.yaml deleted file mode 100644 index 1571a58d7e..0000000000 --- a/assets/samples/dynakube/v1beta4/node-image-pull.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: dynatrace.com/v1beta4 -kind: DynaKube -metadata: - name: dynakube - namespace: dynatrace - annotations: - # enable node image pull - feature.dynatrace.com/node-image-pull: "true" - -spec: - apiUrl: https://ENVIRONMENTID.live.dynatrace.com/api - - # Optional: Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment - # This can be omitted if authentication for your private registry is configured on the nodes. - # - # customPullSecret: "custom-pull-secret" - - oneAgent: - applicationMonitoring: - # the node image pull feature requires a code modules image version 1.311+ - codeModulesImage: public.ecr.aws/dynatrace/dynatrace-codemodules:1.311.70.20250416-094918 From aac443146ef49d0d74ece6e10fbab59595f88a5c Mon Sep 17 00:00:00 2001 From: Christoph Muellner <33160506+chrismuellner@users.noreply.github.com> Date: Tue, 22 Apr 2025 14:36:41 +0200 Subject: [PATCH 423/426] Align memory requests and limits for Activegate (#4790) --- assets/samples/dynakube/v1beta3/applicationMonitoring.yaml | 2 +- assets/samples/dynakube/v1beta3/classicFullStack.yaml | 2 +- assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml | 2 +- assets/samples/dynakube/v1beta3/hostMonitoring.yaml | 2 +- assets/samples/dynakube/v1beta3/kubernetesObservability.yaml | 2 +- .../dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml | 2 +- assets/samples/dynakube/v1beta3/logMonitoring.yaml | 2 +- assets/samples/dynakube/v1beta4/applicationMonitoring.yaml | 2 +- assets/samples/dynakube/v1beta4/classicFullStack.yaml | 2 +- assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml | 2 +- assets/samples/dynakube/v1beta4/hostMonitoring.yaml | 2 +- assets/samples/dynakube/v1beta4/kubernetesObservability.yaml | 2 +- .../dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml | 2 +- assets/samples/dynakube/v1beta4/logMonitoring.yaml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml b/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml index 15a2783173..e6499a5d50 100644 --- a/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml +++ b/assets/samples/dynakube/v1beta3/applicationMonitoring.yaml @@ -130,7 +130,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta3/classicFullStack.yaml b/assets/samples/dynakube/v1beta3/classicFullStack.yaml index e8766afac1..7c39b32002 100644 --- a/assets/samples/dynakube/v1beta3/classicFullStack.yaml +++ b/assets/samples/dynakube/v1beta3/classicFullStack.yaml @@ -185,7 +185,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml b/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml index 730f5e6ab6..daf9c1fe9e 100644 --- a/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml +++ b/assets/samples/dynakube/v1beta3/cloudNativeFullStack.yaml @@ -210,7 +210,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta3/hostMonitoring.yaml b/assets/samples/dynakube/v1beta3/hostMonitoring.yaml index 8b215f6f33..d56932b255 100644 --- a/assets/samples/dynakube/v1beta3/hostMonitoring.yaml +++ b/assets/samples/dynakube/v1beta3/hostMonitoring.yaml @@ -185,7 +185,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml b/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml index 0b2792fd91..de0320f8dd 100644 --- a/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml +++ b/assets/samples/dynakube/v1beta3/kubernetesObservability.yaml @@ -93,7 +93,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml b/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml index 7c9fb4d1e0..1176eed337 100644 --- a/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml +++ b/assets/samples/dynakube/v1beta3/kubernetesSecurityPostureManagement.yaml @@ -93,7 +93,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta3/logMonitoring.yaml b/assets/samples/dynakube/v1beta3/logMonitoring.yaml index f55ad58e2e..5f4549899d 100644 --- a/assets/samples/dynakube/v1beta3/logMonitoring.yaml +++ b/assets/samples/dynakube/v1beta3/logMonitoring.yaml @@ -110,7 +110,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml b/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml index 29dfee6b15..06520bd65b 100644 --- a/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/applicationMonitoring.yaml @@ -130,7 +130,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta4/classicFullStack.yaml b/assets/samples/dynakube/v1beta4/classicFullStack.yaml index ac3e4ac790..bcf2962a88 100644 --- a/assets/samples/dynakube/v1beta4/classicFullStack.yaml +++ b/assets/samples/dynakube/v1beta4/classicFullStack.yaml @@ -185,7 +185,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml b/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml index 294d5efa6d..e246b9975f 100644 --- a/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml +++ b/assets/samples/dynakube/v1beta4/cloudNativeFullStack.yaml @@ -210,7 +210,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta4/hostMonitoring.yaml b/assets/samples/dynakube/v1beta4/hostMonitoring.yaml index 934a42626f..cc44ac8571 100644 --- a/assets/samples/dynakube/v1beta4/hostMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/hostMonitoring.yaml @@ -185,7 +185,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml b/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml index 268800ae94..5393e867a7 100644 --- a/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml +++ b/assets/samples/dynakube/v1beta4/kubernetesObservability.yaml @@ -93,7 +93,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml index d59644888e..0a20caa7c3 100644 --- a/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml +++ b/assets/samples/dynakube/v1beta4/kubernetesSecurityPostureManagement.yaml @@ -95,7 +95,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi diff --git a/assets/samples/dynakube/v1beta4/logMonitoring.yaml b/assets/samples/dynakube/v1beta4/logMonitoring.yaml index 9b9cfde350..6aff2039fe 100644 --- a/assets/samples/dynakube/v1beta4/logMonitoring.yaml +++ b/assets/samples/dynakube/v1beta4/logMonitoring.yaml @@ -110,7 +110,7 @@ spec: resources: requests: cpu: 500m - memory: 512Mi + memory: 1.5Gi limits: cpu: 1000m memory: 1.5Gi From 34f7b5a76ca1b4407f05fc2c693c078fc9e36693 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 22 Apr 2025 23:07:01 +0000 Subject: [PATCH 424/426] chore(deps): update sigstore/cosign-installer action to v3.8.2 (release-1.5) (#4793) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/sign-image/action.yaml | 2 +- .github/actions/upload-sbom/action.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/sign-image/action.yaml b/.github/actions/sign-image/action.yaml index 8fbae189b8..1440c183be 100644 --- a/.github/actions/sign-image/action.yaml +++ b/.github/actions/sign-image/action.yaml @@ -14,7 +14,7 @@ runs: using: "composite" steps: - name: Install Cosign - uses: sigstore/cosign-installer@d7d6bc7722e3daa8354c50bcb52f4837da5e9b6a # v3.8.1 + uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2 - name: Sign image with a key shell: bash run: | diff --git a/.github/actions/upload-sbom/action.yaml b/.github/actions/upload-sbom/action.yaml index 11e5edc00a..c0713c6ba3 100644 --- a/.github/actions/upload-sbom/action.yaml +++ b/.github/actions/upload-sbom/action.yaml @@ -17,7 +17,7 @@ runs: using: "composite" steps: - name: Install Cosign - uses: sigstore/cosign-installer@d7d6bc7722e3daa8354c50bcb52f4837da5e9b6a # v3.8.1 + uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2 - name: Attach sbom attestation to image shell: bash run: | From 83fd26ba0130f3336401dec51b2e484d448244e6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 13:07:44 +0000 Subject: [PATCH 425/426] chore(deps): update github/codeql-action action to v3.28.16 (release-1.5) (#4801) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yaml | 6 +++--- .github/workflows/openssf-scorecards.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 06ee3751cd..02adc8aba2 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -34,12 +34,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 + uses: github/codeql-action/init@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 + uses: github/codeql-action/autobuild@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 + uses: github/codeql-action/analyze@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 diff --git a/.github/workflows/openssf-scorecards.yaml b/.github/workflows/openssf-scorecards.yaml index 5ae8f3c09e..7daf79f501 100644 --- a/.github/workflows/openssf-scorecards.yaml +++ b/.github/workflows/openssf-scorecards.yaml @@ -56,6 +56,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 + uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 with: sarif_file: results.sarif From 8071e925ebabb0527041323886a66a7f459b5630 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 15:15:37 +0000 Subject: [PATCH 426/426] fix(deps): update kubernetes packages to v0.32.4 (release-1.5) (#4802) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 28f6477b59..324b6c4140 100644 --- a/go.mod +++ b/go.mod @@ -31,11 +31,11 @@ require ( gopkg.in/yaml.v3 v3.0.1 istio.io/api v1.25.2 istio.io/client-go v1.25.2 - k8s.io/api v0.32.3 - k8s.io/apiextensions-apiserver v0.32.3 - k8s.io/apimachinery v0.32.3 - k8s.io/client-go v0.32.3 - k8s.io/mount-utils v0.32.3 + k8s.io/api v0.32.4 + k8s.io/apiextensions-apiserver v0.32.4 + k8s.io/apimachinery v0.32.4 + k8s.io/client-go v0.32.4 + k8s.io/mount-utils v0.32.4 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.20.4 sigs.k8s.io/e2e-framework v0.3.0 diff --git a/go.sum b/go.sum index 88090faed7..8f0b64444a 100644 --- a/go.sum +++ b/go.sum @@ -383,20 +383,20 @@ istio.io/api v1.25.2 h1:FCRQy7iaTreKJdLemlQ1vRJEsf1soCHoTAuSf68w5I8= istio.io/api v1.25.2/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE= istio.io/client-go v1.25.2 h1:faupTqeMD0PkuNTZdFlpxxT35jBSQapK5k+MNAkXvqA= istio.io/client-go v1.25.2/go.mod h1:E2LTxTcCVe4cqpKy4/9Y4VmwSoLiH6ff9MEG7EhfSDo= -k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= -k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= -k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= -k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= -k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= -k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= -k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= +k8s.io/api v0.32.4 h1:kw8Y/G8E7EpNy7gjB8gJZl3KJkNz8HM2YHrZPtAZsF4= +k8s.io/api v0.32.4/go.mod h1:5MYFvLvweRhyKylM3Es/6uh/5hGp0dg82vP34KifX4g= +k8s.io/apiextensions-apiserver v0.32.4 h1:IA+CoR63UDOijR/vEpow6wQnX4V6iVpzazJBskHrpHE= +k8s.io/apiextensions-apiserver v0.32.4/go.mod h1:Y06XO/b92H8ymOdG1HlA1submf7gIhbEDc3RjriqZOs= +k8s.io/apimachinery v0.32.4 h1:8EEksaxA7nd7xWJkkwLDN4SvWS5ot9g6Z/VZb3ju25I= +k8s.io/apimachinery v0.32.4/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.4 h1:zaGJS7xoYOYumoWIFXlcVrsiYioRPrXGO7dBfVC5R6M= +k8s.io/client-go v0.32.4/go.mod h1:k0jftcyYnEtwlFW92xC7MTtFv5BNcZBr+zn9jPlT9Ic= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/mount-utils v0.32.3 h1:ZPXXHblfBhYP89OnaozpFg9Ojl6HhDfxBLcdWNkaxW8= -k8s.io/mount-utils v0.32.3/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= +k8s.io/mount-utils v0.32.4 h1:Tgvgr70qGXY8zRftMAHHGVUky51NN7wvNyTBbMOMEsE= +k8s.io/mount-utils v0.32.4/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=