From 94dd491dddb58bf275c0d1a974525a222fec587e Mon Sep 17 00:00:00 2001 From: Bruno Teixeira Date: Thu, 21 Dec 2023 22:20:17 +0000 Subject: [PATCH] feat/add shareProcessNamespace capability --- .../add_shared_process_namespace_cap.yaml | 16 ++++++++ apis/v1alpha1/opentelemetrycollector_types.go | 3 ++ ...ntelemetry.io_opentelemetrycollectors.yaml | 4 ++ ...ntelemetry.io_opentelemetrycollectors.yaml | 4 ++ controllers/builder_test.go | 26 +++++++----- internal/manifests/collector/daemonset.go | 23 ++++++----- .../manifests/collector/daemonset_test.go | 32 +++++++++++++++ internal/manifests/collector/deployment.go | 1 + .../manifests/collector/deployment_test.go | 41 +++++++++++++++++++ internal/manifests/collector/statefulset.go | 1 + .../manifests/collector/statefulset_test.go | 41 +++++++++++++++++++ .../00-assert.yaml | 8 ++++ .../00-install.yaml | 26 ++++++++++++ 13 files changed, 205 insertions(+), 21 deletions(-) create mode 100755 .chloggen/add_shared_process_namespace_cap.yaml create mode 100644 tests/e2e/smoke-shareprocessnamespace/00-assert.yaml create mode 100644 tests/e2e/smoke-shareprocessnamespace/00-install.yaml diff --git a/.chloggen/add_shared_process_namespace_cap.yaml b/.chloggen/add_shared_process_namespace_cap.yaml new file mode 100755 index 0000000000..05ebbe214a --- /dev/null +++ b/.chloggen/add_shared_process_namespace_cap.yaml @@ -0,0 +1,16 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. operator, target allocator, github action) +component: operator + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add SharedProcessNamespace capabilities to the OpenTelemetryCollector CRD + +# One or more tracking issues related to the change +issues: [2472] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: diff --git a/apis/v1alpha1/opentelemetrycollector_types.go b/apis/v1alpha1/opentelemetrycollector_types.go index cb346ca80f..2dcc6bcba7 100644 --- a/apis/v1alpha1/opentelemetrycollector_types.go +++ b/apis/v1alpha1/opentelemetrycollector_types.go @@ -215,6 +215,9 @@ type OpenTelemetryCollectorSpec struct { // HostNetwork indicates if the pod should run in the host networking namespace. // +optional HostNetwork bool `json:"hostNetwork,omitempty"` + // ShareProcessNamespace indicates if the pod's containers should share process namespace. + // +optional + ShareProcessNamespace bool `json:"shareProcessNamespace,omitempty"` // If specified, indicates the pod's priority. // If not specified, the pod priority will be default or zero if there is no // default. diff --git a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml index 0ca1952e58..f385b1ebda 100644 --- a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml +++ b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml @@ -4226,6 +4226,10 @@ spec: account to use with this instance. When set, the operator will not automatically create a ServiceAccount for the collector. type: string + shareProcessNamespace: + description: ShareProcessNamespace indicates if the pod's containers + should share process namespace. + type: boolean targetAllocator: description: TargetAllocator indicates a value which determines whether to spawn a target allocation resource or not. diff --git a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml index 56f84cbb6e..d8d02e3f43 100644 --- a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml +++ b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml @@ -4223,6 +4223,10 @@ spec: account to use with this instance. When set, the operator will not automatically create a ServiceAccount for the collector. type: string + shareProcessNamespace: + description: ShareProcessNamespace indicates if the pod's containers + should share process namespace. + type: boolean targetAllocator: description: TargetAllocator indicates a value which determines whether to spawn a target allocation resource or not. diff --git a/controllers/builder_test.go b/controllers/builder_test.go index be8e635d7e..3ca0c91c6b 100644 --- a/controllers/builder_test.go +++ b/controllers/builder_test.go @@ -27,6 +27,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" colfeaturegate "go.opentelemetry.io/collector/featuregate" @@ -209,8 +210,9 @@ service: }, }, }, - DNSPolicy: "ClusterFirst", - ServiceAccountName: "test-collector", + ShareProcessNamespace: ptr.To(false), + DNSPolicy: "ClusterFirst", + ServiceAccountName: "test-collector", }, }, }, @@ -452,8 +454,9 @@ service: }, }, }, - DNSPolicy: "ClusterFirst", - ServiceAccountName: "test-collector", + ShareProcessNamespace: ptr.To(false), + DNSPolicy: "ClusterFirst", + ServiceAccountName: "test-collector", }, }, }, @@ -728,8 +731,9 @@ service: }, }, }, - DNSPolicy: "ClusterFirst", - ServiceAccountName: "my-special-sa", + ShareProcessNamespace: ptr.To(false), + DNSPolicy: "ClusterFirst", + ServiceAccountName: "my-special-sa", }, }, }, @@ -1237,8 +1241,9 @@ service: }, }, }, - DNSPolicy: "ClusterFirst", - ServiceAccountName: "test-collector", + ShareProcessNamespace: ptr.To(false), + DNSPolicy: "ClusterFirst", + ServiceAccountName: "test-collector", }, }, PodManagementPolicy: "Parallel", @@ -1597,8 +1602,9 @@ service: }, }, }, - DNSPolicy: "ClusterFirst", - ServiceAccountName: "test-collector", + ShareProcessNamespace: ptr.To(false), + DNSPolicy: "ClusterFirst", + ServiceAccountName: "test-collector", }, }, PodManagementPolicy: "Parallel", diff --git a/internal/manifests/collector/daemonset.go b/internal/manifests/collector/daemonset.go index 8566ee0828..e92a265b32 100644 --- a/internal/manifests/collector/daemonset.go +++ b/internal/manifests/collector/daemonset.go @@ -48,17 +48,18 @@ func DaemonSet(params manifests.Params) *appsv1.DaemonSet { Annotations: podAnnotations, }, Spec: corev1.PodSpec{ - ServiceAccountName: ServiceAccountName(params.OtelCol), - InitContainers: params.OtelCol.Spec.InitContainers, - Containers: append(params.OtelCol.Spec.AdditionalContainers, Container(params.Config, params.Log, params.OtelCol, true)), - Volumes: Volumes(params.Config, params.OtelCol), - Tolerations: params.OtelCol.Spec.Tolerations, - NodeSelector: params.OtelCol.Spec.NodeSelector, - HostNetwork: params.OtelCol.Spec.HostNetwork, - DNSPolicy: getDNSPolicy(params.OtelCol), - SecurityContext: params.OtelCol.Spec.PodSecurityContext, - PriorityClassName: params.OtelCol.Spec.PriorityClassName, - Affinity: params.OtelCol.Spec.Affinity, + ServiceAccountName: ServiceAccountName(params.OtelCol), + InitContainers: params.OtelCol.Spec.InitContainers, + Containers: append(params.OtelCol.Spec.AdditionalContainers, Container(params.Config, params.Log, params.OtelCol, true)), + Volumes: Volumes(params.Config, params.OtelCol), + Tolerations: params.OtelCol.Spec.Tolerations, + NodeSelector: params.OtelCol.Spec.NodeSelector, + HostNetwork: params.OtelCol.Spec.HostNetwork, + ShareProcessNamespace: ¶ms.OtelCol.Spec.ShareProcessNamespace, + DNSPolicy: getDNSPolicy(params.OtelCol), + SecurityContext: params.OtelCol.Spec.PodSecurityContext, + PriorityClassName: params.OtelCol.Spec.PriorityClassName, + Affinity: params.OtelCol.Spec.Affinity, }, }, UpdateStrategy: params.OtelCol.Spec.UpdateStrategy, diff --git a/internal/manifests/collector/daemonset_test.go b/internal/manifests/collector/daemonset_test.go index 656591e6d8..5caa9b6418 100644 --- a/internal/manifests/collector/daemonset_test.go +++ b/internal/manifests/collector/daemonset_test.go @@ -489,3 +489,35 @@ func TestDaemonSetOnDeleteUpdateStrategy(t *testing.T) { assert.Equal(t, &intstr.IntOrString{Type: intstr.Int, IntVal: int32(1)}, d.Spec.UpdateStrategy.RollingUpdate.MaxSurge) assert.Equal(t, &intstr.IntOrString{Type: intstr.Int, IntVal: int32(1)}, d.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable) } + +func TestDaemonsetShareProcessNamespace(t *testing.T) { + params1 := manifests.Params{ + Config: config.New(), + OtelCol: v1alpha1.OpenTelemetryCollector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-instance", + }, + Spec: v1alpha1.OpenTelemetryCollectorSpec{}, + }, + Log: logger, + } + // test + d1 := DaemonSet(params1) + assert.False(t, *d1.Spec.Template.Spec.ShareProcessNamespace) + + // verify custom + params2 := manifests.Params{ + Config: config.New(), + OtelCol: v1alpha1.OpenTelemetryCollector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-instance-with-shareprocessnamespace", + }, + Spec: v1alpha1.OpenTelemetryCollectorSpec{ + ShareProcessNamespace: true, + }, + }, + Log: logger, + } + d2 := DaemonSet(params2) + assert.True(t, *d2.Spec.Template.Spec.ShareProcessNamespace) +} diff --git a/internal/manifests/collector/deployment.go b/internal/manifests/collector/deployment.go index 3a1b0abf21..a4b015d9c9 100644 --- a/internal/manifests/collector/deployment.go +++ b/internal/manifests/collector/deployment.go @@ -56,6 +56,7 @@ func Deployment(params manifests.Params) *appsv1.Deployment { Volumes: Volumes(params.Config, params.OtelCol), DNSPolicy: getDNSPolicy(params.OtelCol), HostNetwork: params.OtelCol.Spec.HostNetwork, + ShareProcessNamespace: ¶ms.OtelCol.Spec.ShareProcessNamespace, Tolerations: params.OtelCol.Spec.Tolerations, NodeSelector: params.OtelCol.Spec.NodeSelector, SecurityContext: params.OtelCol.Spec.PodSecurityContext, diff --git a/internal/manifests/collector/deployment_test.go b/internal/manifests/collector/deployment_test.go index baa66f42ad..dcb851bf12 100644 --- a/internal/manifests/collector/deployment_test.go +++ b/internal/manifests/collector/deployment_test.go @@ -554,3 +554,44 @@ func TestDeploymentAdditionalContainers(t *testing.T) { assert.Len(t, d.Spec.Template.Spec.Containers, 2) assert.Equal(t, v1.Container{Name: "test"}, d.Spec.Template.Spec.Containers[0]) } + +func TestDeploymentShareProcessNamespace(t *testing.T) { + // Test default + otelcol1 := v1alpha1.OpenTelemetryCollector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-instance", + }, + } + + cfg := config.New() + + params1 := manifests.Params{ + Config: cfg, + OtelCol: otelcol1, + Log: logger, + } + + d1 := Deployment(params1) + assert.False(t, *d1.Spec.Template.Spec.ShareProcessNamespace) + + // Test hostNetwork=true + otelcol2 := v1alpha1.OpenTelemetryCollector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-instance-with-shareprocessnamespace", + }, + Spec: v1alpha1.OpenTelemetryCollectorSpec{ + ShareProcessNamespace: true, + }, + } + + cfg = config.New() + + params2 := manifests.Params{ + Config: cfg, + OtelCol: otelcol2, + Log: logger, + } + + d2 := Deployment(params2) + assert.True(t, *d2.Spec.Template.Spec.ShareProcessNamespace) +} diff --git a/internal/manifests/collector/statefulset.go b/internal/manifests/collector/statefulset.go index a08304807d..c1a03fce52 100644 --- a/internal/manifests/collector/statefulset.go +++ b/internal/manifests/collector/statefulset.go @@ -56,6 +56,7 @@ func StatefulSet(params manifests.Params) *appsv1.StatefulSet { Volumes: Volumes(params.Config, params.OtelCol), DNSPolicy: getDNSPolicy(params.OtelCol), HostNetwork: params.OtelCol.Spec.HostNetwork, + ShareProcessNamespace: ¶ms.OtelCol.Spec.ShareProcessNamespace, Tolerations: params.OtelCol.Spec.Tolerations, NodeSelector: params.OtelCol.Spec.NodeSelector, SecurityContext: params.OtelCol.Spec.PodSecurityContext, diff --git a/internal/manifests/collector/statefulset_test.go b/internal/manifests/collector/statefulset_test.go index 142f87004d..ed7a386854 100644 --- a/internal/manifests/collector/statefulset_test.go +++ b/internal/manifests/collector/statefulset_test.go @@ -551,3 +551,44 @@ func TestStatefulSetAdditionalContainers(t *testing.T) { assert.Len(t, s.Spec.Template.Spec.Containers, 2) assert.Equal(t, v1.Container{Name: "test"}, s.Spec.Template.Spec.Containers[0]) } + +func TestStatefulSetShareProcessNamespace(t *testing.T) { + // Test default + otelcol1 := v1alpha1.OpenTelemetryCollector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-instance", + }, + } + + cfg := config.New() + + params1 := manifests.Params{ + OtelCol: otelcol1, + Config: cfg, + Log: logger, + } + + d1 := StatefulSet(params1) + assert.False(t, *d1.Spec.Template.Spec.ShareProcessNamespace) + + // Test shareProcessNamespace=true + otelcol2 := v1alpha1.OpenTelemetryCollector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-instance-with-shareprocessnamespace", + }, + Spec: v1alpha1.OpenTelemetryCollectorSpec{ + ShareProcessNamespace: true, + }, + } + + cfg = config.New() + + params2 := manifests.Params{ + OtelCol: otelcol2, + Config: cfg, + Log: logger, + } + + d2 := StatefulSet(params2) + assert.True(t, *d2.Spec.Template.Spec.ShareProcessNamespace) +} diff --git a/tests/e2e/smoke-shareprocessnamespace/00-assert.yaml b/tests/e2e/smoke-shareprocessnamespace/00-assert.yaml new file mode 100644 index 0000000000..6e37157de3 --- /dev/null +++ b/tests/e2e/smoke-shareprocessnamespace/00-assert.yaml @@ -0,0 +1,8 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-shareprocns-collector +spec: + template: + spec: + shareProcessNamespace: true diff --git a/tests/e2e/smoke-shareprocessnamespace/00-install.yaml b/tests/e2e/smoke-shareprocessnamespace/00-install.yaml new file mode 100644 index 0000000000..4334d07f51 --- /dev/null +++ b/tests/e2e/smoke-shareprocessnamespace/00-install.yaml @@ -0,0 +1,26 @@ +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector +metadata: + name: test-shareprocns +spec: + shareProcessNamespace: true + config: | + receivers: + jaeger: + protocols: + grpc: + otlp: + protocols: + grpc: + http: + processors: + + exporters: + debug: + + service: + pipelines: + traces: + receivers: [jaeger,otlp] + processors: [] + exporters: [debug] \ No newline at end of file