diff --git a/.golangci.yaml b/.golangci.yaml index 29e6d293a..1c766a6b9 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -65,10 +65,20 @@ linters-settings: alias: kitk8s - pkg: github.com/kyma-project/telemetry-manager/test/testkit/kyma alias: kitkyma - - pkg: github.com/kyma-project/telemetry-manager/webhook/logparser - alias: logparserwebhook - - pkg: github.com/kyma-project/telemetry-manager/webhook/logpipeline - alias: logpipelinewebhook + - pkg: github.com/kyma-project/telemetry-manager/webhook/logparser/v1alpha1 + alias: logparserwebhookv1alpha1 + - pkg: github.com/kyma-project/telemetry-manager/webhook/logpipeline/v1alpha1 + alias: logpipelinewebhookv1alpha1 + - pkg: github.com/kyma-project/telemetry-manager/webhook/logpipeline/v1beta1 + alias: logpipelinewebhookv1beta1 + - pkg: github.com/kyma-project/telemetry-manager/webhook/metricpipeline/v1alpha1 + alias: metricpipelinewebhookv1alpha1 + - pkg: github.com/kyma-project/telemetry-manager/webhook/metricpipeline/v1beta1 + alias: metricpipelinewebhookv1beta1 + - pkg: github.com/kyma-project/telemetry-manager/webhook/tracepipeline/v1alpha1 + alias: tracepipelinewebhookv1alpha1 + - pkg: github.com/kyma-project/telemetry-manager/webhook/tracepipeline/v1beta1 + alias: tracepipelinewebhookv1beta1 - pkg: github.com/kyma-project/telemetry-manager/internal/reconciler/logpipeline/fluentbit alias: logpipelinefluentbit - pkg: github.com/prometheus/client_golang/api/prometheus/v1 diff --git a/.testcoverage.yml b/.testcoverage.yml index 2aca657b5..d9c63ab6b 100644 --- a/.testcoverage.yml +++ b/.testcoverage.yml @@ -45,10 +45,17 @@ override: path: ^internal/resourcelock$ - threshold: 84 path: ^internal/webhookcert$ - - threshold: 73 - path: ^webhook/logpipeline$ + - threshold: 87 + path: ^webhook/logpipeline/v1alpha1$ + - threshold: 84 + path: ^webhook/logpipeline/v1beta1$ - threshold: 83 path: ^internal/utils/logpipeline$ + - threshold: 75 + path: ^webhook/tracepipeline/v1alpha1$ + - threshold: 75 + path: ^webhook/tracepipeline/v1beta1$ + # Holds regexp rules which will exclude matched files or packages from coverage statistics exclude: diff --git a/apis/telemetry/v1alpha1/logpipeline_types.go b/apis/telemetry/v1alpha1/logpipeline_types.go index 72d143087..b121860fc 100644 --- a/apis/telemetry/v1alpha1/logpipeline_types.go +++ b/apis/telemetry/v1alpha1/logpipeline_types.go @@ -77,7 +77,6 @@ type LogPipelineInput struct { type LogPipelineApplicationInput struct { // If enabled, application logs are collected. The default is `true`. // +optional - // +kubebuilder:default=true Enabled *bool `json:"enabled,omitempty"` // Describes whether application logs from specific Namespaces are selected. The options are mutually exclusive. System Namespaces are excluded by default from the collection. Namespaces LogPipelineNamespaceSelector `json:"namespaces,omitempty"` @@ -89,7 +88,6 @@ type LogPipelineApplicationInput struct { DropLabels bool `json:"dropLabels,omitempty"` // If the `log` attribute contains a JSON payload and it is successfully parsed, the `log` attribute will be retained if `KeepOriginalBody` is set to `true`. Otherwise, the log attribute will be removed from the log record. The default is `true`. // +optional - // +kubebuilder:default=true KeepOriginalBody *bool `json:"keepOriginalBody,omitempty"` } diff --git a/apis/telemetry/v1alpha1/metricpipeline_types.go b/apis/telemetry/v1alpha1/metricpipeline_types.go index 80596add3..e1152b03c 100644 --- a/apis/telemetry/v1alpha1/metricpipeline_types.go +++ b/apis/telemetry/v1alpha1/metricpipeline_types.go @@ -85,7 +85,6 @@ type MetricPipelinePrometheusInput struct { Enabled bool `json:"enabled,omitempty"` // Describes whether Prometheus metrics from specific namespaces are selected. System namespaces are disabled by default. // +optional - // +kubebuilder:default={exclude: {kyma-system, kube-system, istio-system, compass-system}} Namespaces *NamespaceSelector `json:"namespaces,omitempty"` // Configures diagnostic metrics scraping // +optional @@ -98,11 +97,9 @@ type MetricPipelineRuntimeInput struct { Enabled bool `json:"enabled,omitempty"` // Describes whether runtime metrics from specific namespaces are selected. System namespaces are disabled by default. // +optional - // +kubebuilder:default={exclude: {kyma-system, kube-system, istio-system, compass-system}} Namespaces *NamespaceSelector `json:"namespaces,omitempty"` // Describes the Kubernetes resources for which runtime metrics are scraped. // +optional - // +kubebuilder:default={pod: {enabled: true}, container: {enabled: true}, node: {enabled: true}, volume: {enabled: true}, daemonset: {enabled: true}, deployment: {enabled: true}, statefulset: {enabled: true}, job: {enabled: true}} Resources *MetricPipelineRuntimeInputResources `json:"resources,omitempty"` } @@ -110,43 +107,34 @@ type MetricPipelineRuntimeInput struct { type MetricPipelineRuntimeInputResources struct { // Configures Pod runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Pod *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"pod,omitempty"` + Pod *MetricPipelineRuntimeInputResource `json:"pod,omitempty"` // Configures container runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Container *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"container,omitempty"` + Container *MetricPipelineRuntimeInputResource `json:"container,omitempty"` // Configures Node runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Node *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"node,omitempty"` + Node *MetricPipelineRuntimeInputResource `json:"node,omitempty"` // Configures Volume runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Volume *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"volume,omitempty"` + Volume *MetricPipelineRuntimeInputResource `json:"volume,omitempty"` // Configures DaemonSet runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - DaemonSet *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"daemonset,omitempty"` + DaemonSet *MetricPipelineRuntimeInputResource `json:"daemonset,omitempty"` // Configures Deployment runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Deployment *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"deployment,omitempty"` + Deployment *MetricPipelineRuntimeInputResource `json:"deployment,omitempty"` // Configures StatefulSet runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - StatefulSet *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"statefulset,omitempty"` + StatefulSet *MetricPipelineRuntimeInputResource `json:"statefulset,omitempty"` // Configures Job runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Job *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"job,omitempty"` + Job *MetricPipelineRuntimeInputResource `json:"job,omitempty"` } -// MetricPipelineRuntimeInputResourceEnabledByDefault defines if the scraping of runtime metrics is enabled for a specific resource. The scraping is enabled by default. -type MetricPipelineRuntimeInputResourceEnabledByDefault struct { +// MetricPipelineRuntimeInputResource defines if the scraping of runtime metrics is enabled for a specific resource. The scraping is enabled by default. +type MetricPipelineRuntimeInputResource struct { // If enabled, the runtime metrics for the resource are scraped. The default is `true`. // +optional - // +kubebuilder:default=true Enabled *bool `json:"enabled,omitempty"` } diff --git a/apis/telemetry/v1alpha1/shared_types.go b/apis/telemetry/v1alpha1/shared_types.go index ffc05c7a6..7b5cd4e18 100644 --- a/apis/telemetry/v1alpha1/shared_types.go +++ b/apis/telemetry/v1alpha1/shared_types.go @@ -34,7 +34,6 @@ const ( type OTLPOutput struct { // Defines the OTLP protocol (http or grpc). Default is grpc. // +kubebuilder:validation:MinLength=1 - // +kubebuilder:default:=grpc // +kubebuilder:validation:Enum=grpc;http Protocol string `json:"protocol,omitempty"` // Defines the host and port (:) of an OTLP endpoint. diff --git a/apis/telemetry/v1alpha1/zz_generated.deepcopy.go b/apis/telemetry/v1alpha1/zz_generated.deepcopy.go index 977eb6c9f..db98f03fd 100644 --- a/apis/telemetry/v1alpha1/zz_generated.deepcopy.go +++ b/apis/telemetry/v1alpha1/zz_generated.deepcopy.go @@ -721,7 +721,7 @@ func (in *MetricPipelineRuntimeInput) DeepCopy() *MetricPipelineRuntimeInput { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MetricPipelineRuntimeInputResourceEnabledByDefault) DeepCopyInto(out *MetricPipelineRuntimeInputResourceEnabledByDefault) { +func (in *MetricPipelineRuntimeInputResource) DeepCopyInto(out *MetricPipelineRuntimeInputResource) { *out = *in if in.Enabled != nil { in, out := &in.Enabled, &out.Enabled @@ -730,12 +730,12 @@ func (in *MetricPipelineRuntimeInputResourceEnabledByDefault) DeepCopyInto(out * } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricPipelineRuntimeInputResourceEnabledByDefault. -func (in *MetricPipelineRuntimeInputResourceEnabledByDefault) DeepCopy() *MetricPipelineRuntimeInputResourceEnabledByDefault { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricPipelineRuntimeInputResource. +func (in *MetricPipelineRuntimeInputResource) DeepCopy() *MetricPipelineRuntimeInputResource { if in == nil { return nil } - out := new(MetricPipelineRuntimeInputResourceEnabledByDefault) + out := new(MetricPipelineRuntimeInputResource) in.DeepCopyInto(out) return out } @@ -745,42 +745,42 @@ func (in *MetricPipelineRuntimeInputResources) DeepCopyInto(out *MetricPipelineR *out = *in if in.Pod != nil { in, out := &in.Pod, &out.Pod - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Container != nil { in, out := &in.Container, &out.Container - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Node != nil { in, out := &in.Node, &out.Node - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Volume != nil { in, out := &in.Volume, &out.Volume - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.DaemonSet != nil { in, out := &in.DaemonSet, &out.DaemonSet - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Deployment != nil { in, out := &in.Deployment, &out.Deployment - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.StatefulSet != nil { in, out := &in.StatefulSet, &out.StatefulSet - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Job != nil { in, out := &in.Job, &out.Job - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } } diff --git a/apis/telemetry/v1beta1/logpipeline_types.go b/apis/telemetry/v1beta1/logpipeline_types.go index 4419faa65..1b93a6a33 100644 --- a/apis/telemetry/v1beta1/logpipeline_types.go +++ b/apis/telemetry/v1beta1/logpipeline_types.go @@ -84,7 +84,6 @@ type LogPipelineInput struct { type LogPipelineRuntimeInput struct { // If enabled, application logs are collected. The default is `true`. // +optional - // +kubebuilder:default=true Enabled *bool `json:"enabled,omitempty"` // Describes whether application logs from specific Namespaces are selected. The options are mutually exclusive. System Namespaces are excluded by default from the collection. Namespaces LogPipelineNamespaceSelector `json:"namespaces,omitempty"` @@ -96,7 +95,6 @@ type LogPipelineRuntimeInput struct { DropLabels bool `json:"dropLabels,omitempty"` // If the `log` attribute contains a JSON payload and it is successfully parsed, the `log` attribute will be retained if `keepOriginalBody` is set to `true`. Otherwise, the log attribute will be removed from the log record. The default is `true`. // +optional - // +kubebuilder:default=true KeepOriginalBody *bool `json:"keepOriginalBody,omitempty"` } diff --git a/apis/telemetry/v1beta1/metricpipeline_types.go b/apis/telemetry/v1beta1/metricpipeline_types.go index fea776834..3e446b548 100644 --- a/apis/telemetry/v1beta1/metricpipeline_types.go +++ b/apis/telemetry/v1beta1/metricpipeline_types.go @@ -85,7 +85,6 @@ type MetricPipelinePrometheusInput struct { Enabled bool `json:"enabled,omitempty"` // Describes whether Prometheus metrics from specific namespaces are selected. System namespaces are disabled by default. // +optional - // +kubebuilder:default={exclude: {kyma-system, kube-system, istio-system, compass-system}} Namespaces *NamespaceSelector `json:"namespaces,omitempty"` // Configures diagnostic metrics scraping // +optional @@ -98,11 +97,9 @@ type MetricPipelineRuntimeInput struct { Enabled bool `json:"enabled,omitempty"` // Describes whether runtime metrics from specific namespaces are selected. System namespaces are disabled by default. // +optional - // +kubebuilder:default={exclude: {kyma-system, kube-system, istio-system, compass-system}} Namespaces *NamespaceSelector `json:"namespaces,omitempty"` // Describes the Kubernetes resources for which runtime metrics are scraped. // +optional - // +kubebuilder:default={pod: {enabled: true}, container: {enabled: true}, node: {enabled: true}, volume: {enabled: true}, daemonset: {enabled: true}, deployment: {enabled: true}, statefulset: {enabled: true}, job: {enabled: true}} Resources *MetricPipelineRuntimeInputResources `json:"resources,omitempty"` } @@ -110,43 +107,34 @@ type MetricPipelineRuntimeInput struct { type MetricPipelineRuntimeInputResources struct { // Configures Pod runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Pod *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"pod,omitempty"` + Pod *MetricPipelineRuntimeInputResource `json:"pod,omitempty"` // Configures container runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Container *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"container,omitempty"` + Container *MetricPipelineRuntimeInputResource `json:"container,omitempty"` // Configures Node runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Node *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"node,omitempty"` + Node *MetricPipelineRuntimeInputResource `json:"node,omitempty"` // Configures Volume runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Volume *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"volume,omitempty"` + Volume *MetricPipelineRuntimeInputResource `json:"volume,omitempty"` // Configures DaemonSet runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - DaemonSet *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"daemonset,omitempty"` + DaemonSet *MetricPipelineRuntimeInputResource `json:"daemonset,omitempty"` // Configures Deployment runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Deployment *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"deployment,omitempty"` + Deployment *MetricPipelineRuntimeInputResource `json:"deployment,omitempty"` // Configures StatefulSet runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - StatefulSet *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"statefulset,omitempty"` + StatefulSet *MetricPipelineRuntimeInputResource `json:"statefulset,omitempty"` // Configures Job runtime metrics scraping. // +optional - // +kubebuilder:default={enabled: true} - Job *MetricPipelineRuntimeInputResourceEnabledByDefault `json:"job,omitempty"` + Job *MetricPipelineRuntimeInputResource `json:"job,omitempty"` } -// MetricPipelineRuntimeInputResourceEnabledByDefault defines if the scraping of runtime metrics is enabled for a specific resource. The scraping is enabled by default. -type MetricPipelineRuntimeInputResourceEnabledByDefault struct { +// MetricPipelineRuntimeInputResource defines if the scraping of runtime metrics is enabled for a specific resource. The scraping is enabled by default. +type MetricPipelineRuntimeInputResource struct { // If enabled, the runtime metrics for the resource are scraped. The default is `true`. // +optional - // +kubebuilder:default=true Enabled *bool `json:"enabled,omitempty"` } diff --git a/apis/telemetry/v1beta1/shared_types.go b/apis/telemetry/v1beta1/shared_types.go index 9d159fb48..6feb4122d 100644 --- a/apis/telemetry/v1beta1/shared_types.go +++ b/apis/telemetry/v1beta1/shared_types.go @@ -35,7 +35,6 @@ const ( // +kubebuilder:validation:XValidation:rule="((!has(self.path) || size(self.path) <= 0) && (has(self.protocol) && self.protocol == 'grpc')) || (has(self.protocol) && self.protocol == 'http')", message="Path is only available with HTTP protocol" type OTLPOutput struct { // Defines the OTLP protocol (http or grpc). Default is grpc. - // +kubebuilder:default:=grpc // +kubebuilder:validation:Enum=grpc;http Protocol OTLPProtocol `json:"protocol,omitempty"` // Defines the host and port (:) of an OTLP endpoint. diff --git a/apis/telemetry/v1beta1/zz_generated.deepcopy.go b/apis/telemetry/v1beta1/zz_generated.deepcopy.go index 7957a027c..073661719 100644 --- a/apis/telemetry/v1beta1/zz_generated.deepcopy.go +++ b/apis/telemetry/v1beta1/zz_generated.deepcopy.go @@ -595,7 +595,7 @@ func (in *MetricPipelineRuntimeInput) DeepCopy() *MetricPipelineRuntimeInput { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MetricPipelineRuntimeInputResourceEnabledByDefault) DeepCopyInto(out *MetricPipelineRuntimeInputResourceEnabledByDefault) { +func (in *MetricPipelineRuntimeInputResource) DeepCopyInto(out *MetricPipelineRuntimeInputResource) { *out = *in if in.Enabled != nil { in, out := &in.Enabled, &out.Enabled @@ -604,12 +604,12 @@ func (in *MetricPipelineRuntimeInputResourceEnabledByDefault) DeepCopyInto(out * } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricPipelineRuntimeInputResourceEnabledByDefault. -func (in *MetricPipelineRuntimeInputResourceEnabledByDefault) DeepCopy() *MetricPipelineRuntimeInputResourceEnabledByDefault { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricPipelineRuntimeInputResource. +func (in *MetricPipelineRuntimeInputResource) DeepCopy() *MetricPipelineRuntimeInputResource { if in == nil { return nil } - out := new(MetricPipelineRuntimeInputResourceEnabledByDefault) + out := new(MetricPipelineRuntimeInputResource) in.DeepCopyInto(out) return out } @@ -619,42 +619,42 @@ func (in *MetricPipelineRuntimeInputResources) DeepCopyInto(out *MetricPipelineR *out = *in if in.Pod != nil { in, out := &in.Pod, &out.Pod - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Container != nil { in, out := &in.Container, &out.Container - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Node != nil { in, out := &in.Node, &out.Node - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Volume != nil { in, out := &in.Volume, &out.Volume - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.DaemonSet != nil { in, out := &in.DaemonSet, &out.DaemonSet - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Deployment != nil { in, out := &in.Deployment, &out.Deployment - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.StatefulSet != nil { in, out := &in.StatefulSet, &out.StatefulSet - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } if in.Job != nil { in, out := &in.Job, &out.Job - *out = new(MetricPipelineRuntimeInputResourceEnabledByDefault) + *out = new(MetricPipelineRuntimeInputResource) (*in).DeepCopyInto(*out) } } diff --git a/config/crd/bases/telemetry.kyma-project.io_logpipelines.yaml b/config/crd/bases/telemetry.kyma-project.io_logpipelines.yaml index 244d8232b..14083bab7 100644 --- a/config/crd/bases/telemetry.kyma-project.io_logpipelines.yaml +++ b/config/crd/bases/telemetry.kyma-project.io_logpipelines.yaml @@ -101,14 +101,12 @@ spec: description: Defines whether to drop all Kubernetes labels. The default is `false`. type: boolean enabled: - default: true description: If enabled, application logs are collected. The default is `true`. type: boolean keepAnnotations: description: Defines whether to keep all Kubernetes annotations. The default is `false`. type: boolean keepOriginalBody: - default: true description: If the `log` attribute contains a JSON payload and it is successfully parsed, the `log` attribute will be retained if `KeepOriginalBody` is set to `true`. Otherwise, the log attribute will be removed from the log record. The default is `true`. type: boolean namespaces: diff --git a/config/crd/bases/telemetry.kyma-project.io_metricpipelines.yaml b/config/crd/bases/telemetry.kyma-project.io_metricpipelines.yaml index 8a2214686..32271cdd8 100644 --- a/config/crd/bases/telemetry.kyma-project.io_metricpipelines.yaml +++ b/config/crd/bases/telemetry.kyma-project.io_metricpipelines.yaml @@ -150,12 +150,6 @@ spec: annotation are scraped. The default is `false`. type: boolean namespaces: - default: - exclude: - - kyma-system - - kube-system - - istio-system - - compass-system description: Describes whether Prometheus metrics from specific namespaces are selected. System namespaces are disabled by default. @@ -187,12 +181,6 @@ spec: default is `false`. type: boolean namespaces: - default: - exclude: - - kyma-system - - kube-system - - istio-system - - compass-system description: Describes whether runtime metrics from specific namespaces are selected. System namespaces are disabled by default. @@ -216,110 +204,69 @@ spec: rule: '!((has(self.include) && size(self.include) != 0) && (has(self.exclude) && size(self.exclude) != 0))' resources: - default: - container: - enabled: true - daemonset: - enabled: true - deployment: - enabled: true - job: - enabled: true - node: - enabled: true - pod: - enabled: true - statefulset: - enabled: true - volume: - enabled: true description: Describes the Kubernetes resources for which runtime metrics are scraped. properties: container: - default: - enabled: true description: Configures container runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object daemonset: - default: - enabled: true description: Configures DaemonSet runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object deployment: - default: - enabled: true description: Configures Deployment runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object job: - default: - enabled: true description: Configures Job runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object node: - default: - enabled: true description: Configures Node runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object pod: - default: - enabled: true description: Configures Pod runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object statefulset: - default: - enabled: true description: Configures StatefulSet runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object volume: - default: - enabled: true description: Configures Volume runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean @@ -505,7 +452,6 @@ spec: and /v1/traces type: string protocol: - default: grpc description: Defines the OTLP protocol (http or grpc). Default is grpc. enum: diff --git a/config/crd/bases/telemetry.kyma-project.io_tracepipelines.yaml b/config/crd/bases/telemetry.kyma-project.io_tracepipelines.yaml index f830d4bf7..82bdd4a5c 100644 --- a/config/crd/bases/telemetry.kyma-project.io_tracepipelines.yaml +++ b/config/crd/bases/telemetry.kyma-project.io_tracepipelines.yaml @@ -237,7 +237,6 @@ spec: and /v1/traces type: string protocol: - default: grpc description: Defines the OTLP protocol (http or grpc). Default is grpc. enum: diff --git a/config/development/crd/bases/telemetry.kyma-project.io_logpipelines.yaml b/config/development/crd/bases/telemetry.kyma-project.io_logpipelines.yaml index e67d13017..7da97ba17 100644 --- a/config/development/crd/bases/telemetry.kyma-project.io_logpipelines.yaml +++ b/config/development/crd/bases/telemetry.kyma-project.io_logpipelines.yaml @@ -109,7 +109,6 @@ spec: The default is `false`. type: boolean enabled: - default: true description: If enabled, application logs are collected. The default is `true`. type: boolean @@ -118,7 +117,6 @@ spec: The default is `false`. type: boolean keepOriginalBody: - default: true description: If the `log` attribute contains a JSON payload and it is successfully parsed, the `log` attribute will be retained if `KeepOriginalBody` is set to `true`. Otherwise, @@ -611,7 +609,6 @@ spec: and /v1/traces type: string protocol: - default: grpc description: Defines the OTLP protocol (http or grpc). Default is grpc. enum: @@ -998,7 +995,6 @@ spec: The default is `false`. type: boolean enabled: - default: true description: If enabled, application logs are collected. The default is `true`. type: boolean @@ -1007,7 +1003,6 @@ spec: The default is `false`. type: boolean keepOriginalBody: - default: true description: If the `log` attribute contains a JSON payload and it is successfully parsed, the `log` attribute will be retained if `keepOriginalBody` is set to `true`. Otherwise, @@ -1468,7 +1463,6 @@ spec: and /v1/traces type: string protocol: - default: grpc description: Defines the OTLP protocol (http or grpc). Default is grpc. enum: diff --git a/config/development/crd/bases/telemetry.kyma-project.io_metricpipelines.yaml b/config/development/crd/bases/telemetry.kyma-project.io_metricpipelines.yaml index 9d4302c27..a36467952 100644 --- a/config/development/crd/bases/telemetry.kyma-project.io_metricpipelines.yaml +++ b/config/development/crd/bases/telemetry.kyma-project.io_metricpipelines.yaml @@ -150,12 +150,6 @@ spec: annotation are scraped. The default is `false`. type: boolean namespaces: - default: - exclude: - - kyma-system - - kube-system - - istio-system - - compass-system description: Describes whether Prometheus metrics from specific namespaces are selected. System namespaces are disabled by default. @@ -187,12 +181,6 @@ spec: default is `false`. type: boolean namespaces: - default: - exclude: - - kyma-system - - kube-system - - istio-system - - compass-system description: Describes whether runtime metrics from specific namespaces are selected. System namespaces are disabled by default. @@ -216,110 +204,69 @@ spec: rule: '!((has(self.include) && size(self.include) != 0) && (has(self.exclude) && size(self.exclude) != 0))' resources: - default: - container: - enabled: true - daemonset: - enabled: true - deployment: - enabled: true - job: - enabled: true - node: - enabled: true - pod: - enabled: true - statefulset: - enabled: true - volume: - enabled: true description: Describes the Kubernetes resources for which runtime metrics are scraped. properties: container: - default: - enabled: true description: Configures container runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object daemonset: - default: - enabled: true description: Configures DaemonSet runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object deployment: - default: - enabled: true description: Configures Deployment runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object job: - default: - enabled: true description: Configures Job runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object node: - default: - enabled: true description: Configures Node runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object pod: - default: - enabled: true description: Configures Pod runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object statefulset: - default: - enabled: true description: Configures StatefulSet runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object volume: - default: - enabled: true description: Configures Volume runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean @@ -505,7 +452,6 @@ spec: and /v1/traces type: string protocol: - default: grpc description: Defines the OTLP protocol (http or grpc). Default is grpc. enum: @@ -845,12 +791,6 @@ spec: annotation are scraped. The default is `false`. type: boolean namespaces: - default: - exclude: - - kyma-system - - kube-system - - istio-system - - compass-system description: Describes whether Prometheus metrics from specific namespaces are selected. System namespaces are disabled by default. @@ -882,12 +822,6 @@ spec: default is `false`. type: boolean namespaces: - default: - exclude: - - kyma-system - - kube-system - - istio-system - - compass-system description: Describes whether runtime metrics from specific namespaces are selected. System namespaces are disabled by default. @@ -911,110 +845,69 @@ spec: rule: '!((has(self.include) && size(self.include) != 0) && (has(self.exclude) && size(self.exclude) != 0))' resources: - default: - container: - enabled: true - daemonset: - enabled: true - deployment: - enabled: true - job: - enabled: true - node: - enabled: true - pod: - enabled: true - statefulset: - enabled: true - volume: - enabled: true description: Describes the Kubernetes resources for which runtime metrics are scraped. properties: container: - default: - enabled: true description: Configures container runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object daemonset: - default: - enabled: true description: Configures DaemonSet runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object deployment: - default: - enabled: true description: Configures Deployment runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object job: - default: - enabled: true description: Configures Job runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object node: - default: - enabled: true description: Configures Node runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object pod: - default: - enabled: true description: Configures Pod runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object statefulset: - default: - enabled: true description: Configures StatefulSet runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean type: object volume: - default: - enabled: true description: Configures Volume runtime metrics scraping. properties: enabled: - default: true description: If enabled, the runtime metrics for the resource are scraped. The default is `true`. type: boolean @@ -1200,7 +1093,6 @@ spec: and /v1/traces type: string protocol: - default: grpc description: Defines the OTLP protocol (http or grpc). Default is grpc. enum: diff --git a/config/development/crd/bases/telemetry.kyma-project.io_tracepipelines.yaml b/config/development/crd/bases/telemetry.kyma-project.io_tracepipelines.yaml index d19d7f947..b8be38cce 100644 --- a/config/development/crd/bases/telemetry.kyma-project.io_tracepipelines.yaml +++ b/config/development/crd/bases/telemetry.kyma-project.io_tracepipelines.yaml @@ -237,7 +237,6 @@ spec: and /v1/traces type: string protocol: - default: grpc description: Defines the OTLP protocol (http or grpc). Default is grpc. enum: @@ -666,7 +665,6 @@ spec: and /v1/traces type: string protocol: - default: grpc description: Defines the OTLP protocol (http or grpc). Default is grpc. enum: diff --git a/config/development/kustomization.yaml b/config/development/kustomization.yaml index 4fcb0f2b3..fa495eda9 100644 --- a/config/development/kustomization.yaml +++ b/config/development/kustomization.yaml @@ -30,6 +30,12 @@ patches: target: kind: Deployment name: manager + - path: webhook-patches.yaml + target: + group: admissionregistration.k8s.io + version: v1 + kind: MutatingWebhookConfiguration + name: mutating-webhook.kyma-project.io resources: - crd diff --git a/config/development/webhook-patches.yaml b/config/development/webhook-patches.yaml new file mode 100644 index 000000000..461a8356f --- /dev/null +++ b/config/development/webhook-patches.yaml @@ -0,0 +1,88 @@ + +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook.kyma-project.io +webhooks: + - name: mutating-metricpipelines-v1beta1.kyma-project.io + clientConfig: + service: + name: telemetry-manager-webhook + namespace: kyma-system + path: /mutate-telemetry-kyma-project-io-v1beta1-metricpipeline + port: 443 + admissionReviewVersions: + - v1beta1 + - v1 + sideEffects: None + failurePolicy: Fail + matchPolicy: Exact + timeoutSeconds: 15 + namespaceSelector: {} + objectSelector: {} + rules: + - apiGroups: + - telemetry.kyma-project.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - metricpipelines + scope: '*' + - name: mutating-tracepipelines-v1beta1.kyma-project.io + clientConfig: + service: + name: telemetry-manager-webhook + namespace: kyma-system + path: /mutate-telemetry-kyma-project-io-v1beta1-tracepipeline + port: 443 + admissionReviewVersions: + - v1beta1 + - v1 + sideEffects: None + failurePolicy: Fail + matchPolicy: Exact + timeoutSeconds: 15 + namespaceSelector: {} + objectSelector: {} + rules: + - apiGroups: + - telemetry.kyma-project.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - tracepipelines + scope: '*' + - name: mutating-logpipelines-v1beta1.kyma-project.io + clientConfig: + service: + name: telemetry-manager-webhook + namespace: kyma-system + path: /mutate-telemetry-kyma-project-io-v1beta1-logpipeline + port: 443 + admissionReviewVersions: + - v1beta1 + - v1 + sideEffects: None + failurePolicy: Fail + matchPolicy: Exact + timeoutSeconds: 15 + namespaceSelector: {} + objectSelector: {} + rules: + - apiGroups: + - telemetry.kyma-project.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - logpipelines + scope: '*' diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 2a084f09b..d8fdb4040 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -44,6 +44,7 @@ rules: - apiGroups: - admissionregistration.k8s.io resources: + - mutatingwebhookconfigurations - validatingwebhookconfigurations verbs: - create diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index eae61f7d8..1fec88b4f 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -59,3 +59,91 @@ webhooks: scope: '*' sideEffects: None timeoutSeconds: 15 + +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook.kyma-project.io +webhooks: + - name: mutating-metricpipelines-v1alpha1.kyma-project.io + clientConfig: + service: + name: telemetry-manager-webhook + namespace: kyma-system + path: /mutate-telemetry-kyma-project-io-v1alpha1-metricpipeline + port: 443 + admissionReviewVersions: + - v1beta1 + - v1 + sideEffects: None + failurePolicy: Fail + matchPolicy: Exact + timeoutSeconds: 15 + namespaceSelector: {} + objectSelector: {} + rules: + - apiGroups: + - telemetry.kyma-project.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - metricpipelines + scope: '*' + - name: mutating-tracepipelines-v1alpha1.kyma-project.io + clientConfig: + service: + name: telemetry-manager-webhook + namespace: kyma-system + path: /mutate-telemetry-kyma-project-io-v1alpha1-tracepipeline + port: 443 + admissionReviewVersions: + - v1beta1 + - v1 + sideEffects: None + failurePolicy: Fail + matchPolicy: Exact + timeoutSeconds: 15 + namespaceSelector: {} + objectSelector: {} + rules: + - apiGroups: + - telemetry.kyma-project.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - tracepipelines + scope: '*' + - name: mutating-logpipelines-v1alpha1.kyma-project.io + clientConfig: + service: + name: telemetry-manager-webhook + namespace: kyma-system + path: /mutate-telemetry-kyma-project-io-v1alpha1-logpipeline + port: 443 + admissionReviewVersions: + - v1beta1 + - v1 + sideEffects: None + failurePolicy: Fail + matchPolicy: Exact + timeoutSeconds: 15 + namespaceSelector: {} + objectSelector: {} + rules: + - apiGroups: + - telemetry.kyma-project.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - logpipelines + scope: '*' diff --git a/controllers/operator/telemetry_controller.go b/controllers/operator/telemetry_controller.go index 765ef337a..cd2ca41c5 100644 --- a/controllers/operator/telemetry_controller.go +++ b/controllers/operator/telemetry_controller.go @@ -105,7 +105,7 @@ func (r *TelemetryController) mapWebhook(ctx context.Context, object client.Obje return nil } - if webhook.Name != r.config.Webhook.CertConfig.WebhookName.Name { + if webhook.Name != r.config.Webhook.CertConfig.ValidatingWebhookName.Name { return nil } diff --git a/internal/reconciler/telemetry/reconciler.go b/internal/reconciler/telemetry/reconciler.go index 074da5abc..8b75f92f6 100644 --- a/internal/reconciler/telemetry/reconciler.go +++ b/internal/reconciler/telemetry/reconciler.go @@ -293,7 +293,7 @@ func (r *Reconciler) reconcileWebhook(ctx context.Context, telemetry *operatorv1 } var webhook admissionregistrationv1.ValidatingWebhookConfiguration - if err := r.Get(ctx, r.config.Webhook.CertConfig.WebhookName, &webhook); err != nil { + if err := r.Get(ctx, r.config.Webhook.CertConfig.ValidatingWebhookName, &webhook); err != nil { return fmt.Errorf("failed to get webhook: %w", err) } diff --git a/internal/utils/test/metric_pipeline_builder.go b/internal/utils/test/metric_pipeline_builder.go index ac17774fd..44e0fb77f 100644 --- a/internal/utils/test/metric_pipeline_builder.go +++ b/internal/utils/test/metric_pipeline_builder.go @@ -187,7 +187,7 @@ func (b *MetricPipelineBuilder) WithRuntimeInputPodMetrics(enable bool) *MetricP b.initializeRuntimeInputResources() if b.inRuntime.Resources.Pod == nil { - b.inRuntime.Resources.Pod = &telemetryv1alpha1.MetricPipelineRuntimeInputResourceEnabledByDefault{} + b.inRuntime.Resources.Pod = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{} } b.inRuntime.Resources.Pod.Enabled = &enable @@ -199,7 +199,7 @@ func (b *MetricPipelineBuilder) WithRuntimeInputContainerMetrics(enable bool) *M b.initializeRuntimeInputResources() if b.inRuntime.Resources.Container == nil { - b.inRuntime.Resources.Container = &telemetryv1alpha1.MetricPipelineRuntimeInputResourceEnabledByDefault{} + b.inRuntime.Resources.Container = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{} } b.inRuntime.Resources.Container.Enabled = &enable @@ -211,7 +211,7 @@ func (b *MetricPipelineBuilder) WithRuntimeInputNodeMetrics(enable bool) *Metric b.initializeRuntimeInputResources() if b.inRuntime.Resources.Node == nil { - b.inRuntime.Resources.Node = &telemetryv1alpha1.MetricPipelineRuntimeInputResourceEnabledByDefault{} + b.inRuntime.Resources.Node = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{} } b.inRuntime.Resources.Node.Enabled = &enable @@ -223,7 +223,7 @@ func (b *MetricPipelineBuilder) WithRuntimeInputVolumeMetrics(enable bool) *Metr b.initializeRuntimeInputResources() if b.inRuntime.Resources.Volume == nil { - b.inRuntime.Resources.Volume = &telemetryv1alpha1.MetricPipelineRuntimeInputResourceEnabledByDefault{} + b.inRuntime.Resources.Volume = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{} } b.inRuntime.Resources.Volume.Enabled = &enable @@ -235,7 +235,7 @@ func (b *MetricPipelineBuilder) WithRuntimeInputDeploymentMetrics(enable bool) * b.initializeRuntimeInputResources() if b.inRuntime.Resources.Deployment == nil { - b.inRuntime.Resources.Deployment = &telemetryv1alpha1.MetricPipelineRuntimeInputResourceEnabledByDefault{} + b.inRuntime.Resources.Deployment = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{} } b.inRuntime.Resources.Deployment.Enabled = &enable @@ -247,7 +247,7 @@ func (b *MetricPipelineBuilder) WithRuntimeInputJobMetrics(enable bool) *MetricP b.initializeRuntimeInputResources() if b.inRuntime.Resources.Job == nil { - b.inRuntime.Resources.Job = &telemetryv1alpha1.MetricPipelineRuntimeInputResourceEnabledByDefault{} + b.inRuntime.Resources.Job = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{} } b.inRuntime.Resources.Job.Enabled = &enable @@ -259,7 +259,7 @@ func (b *MetricPipelineBuilder) WithRuntimeInputDaemonSetMetrics(enable bool) *M b.initializeRuntimeInputResources() if b.inRuntime.Resources.DaemonSet == nil { - b.inRuntime.Resources.DaemonSet = &telemetryv1alpha1.MetricPipelineRuntimeInputResourceEnabledByDefault{} + b.inRuntime.Resources.DaemonSet = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{} } b.inRuntime.Resources.DaemonSet.Enabled = &enable @@ -271,7 +271,7 @@ func (b *MetricPipelineBuilder) WithRuntimeInputStatefulSetMetrics(enable bool) b.initializeRuntimeInputResources() if b.inRuntime.Resources.StatefulSet == nil { - b.inRuntime.Resources.StatefulSet = &telemetryv1alpha1.MetricPipelineRuntimeInputResourceEnabledByDefault{} + b.inRuntime.Resources.StatefulSet = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{} } b.inRuntime.Resources.StatefulSet.Enabled = &enable diff --git a/internal/webhookcert/resources.go b/internal/webhookcert/resources.go index d0f53ddc0..13da1b39b 100644 --- a/internal/webhookcert/resources.go +++ b/internal/webhookcert/resources.go @@ -18,11 +18,16 @@ const ( // applyWebhookConfigResources applies the following webhook configurations: // 1- Updates validating webhook configuration with the provided CA bundle. // 2- Updates LogPipeline CRD with conversion webhook configuration. +// 3- Updates mutating webhook configuration with the provided CA bundle. func applyWebhookConfigResources(ctx context.Context, c client.Client, caBundle []byte, config Config) error { if err := updateValidatingWebhookConfig(ctx, c, caBundle, config); err != nil { return fmt.Errorf("failed to update validating webhook with CA bundle: %w", err) } + if err := updateMutatingWebhookConfig(ctx, c, caBundle, config); err != nil { + return fmt.Errorf("failed to update mutating webhook with CA bundle: %w", err) + } + conversionWebhookConfig := makeConversionWebhookConfig(caBundle, config) if err := updateLogPipelineCRDWithConversionWebhookConfig(ctx, c, conversionWebhookConfig); err != nil { return fmt.Errorf("failed to update LogPipeline CRD with conversion webhook configuration: %w", err) @@ -33,12 +38,13 @@ func applyWebhookConfigResources(ctx context.Context, c client.Client, caBundle func updateValidatingWebhookConfig(ctx context.Context, c client.Client, caBundle []byte, config Config) error { var validatingWebhookConfig admissionregistrationv1.ValidatingWebhookConfiguration - if err := c.Get(ctx, config.WebhookName, &validatingWebhookConfig); err != nil { + if err := c.Get(ctx, config.ValidatingWebhookName, &validatingWebhookConfig); err != nil { return fmt.Errorf("failed to get validating webhook configuration: %w", err) } - validatingWebhookConfig.Webhooks[0].ClientConfig.CABundle = caBundle - validatingWebhookConfig.Webhooks[1].ClientConfig.CABundle = caBundle + for i := range len(validatingWebhookConfig.Webhooks) { + validatingWebhookConfig.Webhooks[i].ClientConfig.CABundle = caBundle + } return c.Update(ctx, &validatingWebhookConfig) } @@ -71,3 +77,16 @@ func updateLogPipelineCRDWithConversionWebhookConfig(ctx context.Context, c clie return c.Update(ctx, &logPipelineCRD) } + +func updateMutatingWebhookConfig(ctx context.Context, c client.Client, caBundle []byte, config Config) error { + var mutatingWebhook admissionregistrationv1.MutatingWebhookConfiguration + if err := c.Get(ctx, config.MutatingWebhookName, &mutatingWebhook); err != nil { + return fmt.Errorf("failed to get mutating webhook: %w", err) + } + + for i := range len(mutatingWebhook.Webhooks) { + mutatingWebhook.Webhooks[i].ClientConfig.CABundle = caBundle + } + + return c.Update(ctx, &mutatingWebhook) +} diff --git a/internal/webhookcert/webhook_cert.go b/internal/webhookcert/webhook_cert.go index 35548709a..4f0030d96 100644 --- a/internal/webhookcert/webhook_cert.go +++ b/internal/webhookcert/webhook_cert.go @@ -9,10 +9,11 @@ import ( ) type Config struct { - CertDir string - ServiceName types.NamespacedName - CASecretName types.NamespacedName - WebhookName types.NamespacedName + CertDir string + ServiceName types.NamespacedName + CASecretName types.NamespacedName + ValidatingWebhookName types.NamespacedName + MutatingWebhookName types.NamespacedName } func EnsureCertificate(ctx context.Context, client client.Client, config Config) error { diff --git a/internal/webhookcert/webhook_cert_test.go b/internal/webhookcert/webhook_cert_test.go index 6b26e6f20..761740f0e 100644 --- a/internal/webhookcert/webhook_cert_test.go +++ b/internal/webhookcert/webhook_cert_test.go @@ -28,10 +28,16 @@ var ( Name: "telemetry-webhook-cert", Namespace: systemNamespace, } - name = "telemetry-validating-webhook.kyma-project.io" - webhookName = types.NamespacedName{ - Name: name, + validatingWebhookName = "telemetry-validating-webhook.kyma-project.io" + validatingWebhookNamespacedName = types.NamespacedName{ + Name: validatingWebhookName, } + + mutatingWebhookName = "telemetry-mutating-webhook.kyma-project.io" + mutatingWebhookNamespacedName = types.NamespacedName{ + Name: mutatingWebhookName, + } + logPipelinesCRD = apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{ Name: "logpipelines.telemetry.kyma-project.io", @@ -60,14 +66,14 @@ var ( admissionregistrationv1.Create, admissionregistrationv1.Update, } - apiGroups = []string{"telemetry.kyma-project.io"} - apiVersions = []string{"v1alpha1"} - scope = admissionregistrationv1.AllScopes - servicePort = int32(443) - timeout = int32(15) - initialValidatingWebhookConfiguration = admissionregistrationv1.ValidatingWebhookConfiguration{ + apiGroups = []string{"telemetry.kyma-project.io"} + apiVersions = []string{"v1alpha1"} + scope = admissionregistrationv1.AllScopes + servicePort = int32(443) + timeout = int32(15) + validatingWebhookConfiguration = admissionregistrationv1.ValidatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{ - Name: name, + Name: validatingWebhookName, Labels: labels, }, Webhooks: []admissionregistrationv1.ValidatingWebhook{ @@ -127,13 +133,103 @@ var ( }, }, } + + mutatingWebhookConfiguration = admissionregistrationv1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: mutatingWebhookName, + Labels: labels, + }, + Webhooks: []admissionregistrationv1.MutatingWebhook{ + { + AdmissionReviewVersions: []string{"v1beta1", "v1"}, + ClientConfig: admissionregistrationv1.WebhookClientConfig{ + Service: &admissionregistrationv1.ServiceReference{ + Name: webhookService.Name, + Namespace: webhookService.Namespace, + Port: &servicePort, + Path: ptr.To("/mutate-telemetry-kyma-project-io-v1alpha1-metricpipeline"), + }, + }, + FailurePolicy: &failurePolicy, + MatchPolicy: &matchPolicy, + Name: "mutating.v1alpha1.metricpipelines.telemetry.kyma-project.io", + SideEffects: &sideEffects, + TimeoutSeconds: &timeout, + Rules: []admissionregistrationv1.RuleWithOperations{ + { + Operations: operations, + Rule: admissionregistrationv1.Rule{ + APIGroups: apiGroups, + APIVersions: apiVersions, + Scope: &scope, + Resources: []string{"metricpipelines"}, + }, + }, + }, + }, + { + AdmissionReviewVersions: []string{"v1beta1", "v1"}, + ClientConfig: admissionregistrationv1.WebhookClientConfig{ + Service: &admissionregistrationv1.ServiceReference{ + Name: webhookService.Name, + Namespace: webhookService.Namespace, + Port: &servicePort, + Path: ptr.To("/mutate-telemetry-kyma-project-io-v1alpha1-tracepipeline"), + }, + }, + FailurePolicy: &failurePolicy, + MatchPolicy: &matchPolicy, + Name: "mutating.v1alpha1.tracepipelines.telemetry.kyma-project.io", + SideEffects: &sideEffects, + TimeoutSeconds: &timeout, + Rules: []admissionregistrationv1.RuleWithOperations{ + { + Operations: operations, + Rule: admissionregistrationv1.Rule{ + APIGroups: apiGroups, + APIVersions: apiVersions, + Scope: &scope, + Resources: []string{"tracepipelines"}, + }, + }, + }, + }, + { + AdmissionReviewVersions: []string{"v1beta1", "v1"}, + ClientConfig: admissionregistrationv1.WebhookClientConfig{ + Service: &admissionregistrationv1.ServiceReference{ + Name: webhookService.Name, + Namespace: webhookService.Namespace, + Port: &servicePort, + Path: ptr.To("/mutate-telemetry-kyma-project-io-v1alpha1-logpipeline"), + }, + }, + FailurePolicy: &failurePolicy, + MatchPolicy: &matchPolicy, + Name: "mutating.v1alpha1.logpipelines.telemetry.kyma-project.io", + SideEffects: &sideEffects, + TimeoutSeconds: &timeout, + Rules: []admissionregistrationv1.RuleWithOperations{ + { + Operations: operations, + Rule: admissionregistrationv1.Rule{ + APIGroups: apiGroups, + APIVersions: apiVersions, + Scope: &scope, + Resources: []string{"logpipelines"}, + }, + }, + }, + }, + }, + } ) func TestUpdateLogPipelineWithWebhookConfig(t *testing.T) { scheme := runtime.NewScheme() require.NoError(t, clientgoscheme.AddToScheme(scheme)) require.NoError(t, apiextensionsv1.AddToScheme(scheme)) - client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &initialValidatingWebhookConfiguration).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() certDir, err := os.MkdirTemp("", "certificate") require.NoError(t, err) @@ -143,10 +239,11 @@ func TestUpdateLogPipelineWithWebhookConfig(t *testing.T) { }(certDir) config := Config{ - CertDir: certDir, - ServiceName: webhookService, - CASecretName: caBundleSecret, - WebhookName: webhookName, + CertDir: certDir, + ServiceName: webhookService, + CASecretName: caBundleSecret, + ValidatingWebhookName: validatingWebhookNamespacedName, + MutatingWebhookName: mutatingWebhookNamespacedName, } err = EnsureCertificate(context.TODO(), client, config) @@ -174,12 +271,12 @@ func TestUpdateLogPipelineWithWebhookConfig(t *testing.T) { require.True(t, certValid) } -func TestUpdateValidatingWebhookConfig(t *testing.T) { +func TestUpdateWebhookConfig(t *testing.T) { scheme := runtime.NewScheme() require.NoError(t, clientgoscheme.AddToScheme(scheme)) require.NoError(t, apiextensionsv1.AddToScheme(scheme)) - client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &initialValidatingWebhookConfiguration).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() certDir, err := os.MkdirTemp("", "certificate") require.NoError(t, err) @@ -190,10 +287,11 @@ func TestUpdateValidatingWebhookConfig(t *testing.T) { }(certDir) config := Config{ - CertDir: certDir, - ServiceName: webhookService, - CASecretName: caBundleSecret, - WebhookName: webhookName, + CertDir: certDir, + ServiceName: webhookService, + CASecretName: caBundleSecret, + ValidatingWebhookName: validatingWebhookNamespacedName, + MutatingWebhookName: mutatingWebhookNamespacedName, } err = EnsureCertificate(context.TODO(), client, config) @@ -204,11 +302,7 @@ func TestUpdateValidatingWebhookConfig(t *testing.T) { var updatedValidatingWebhookConfiguration admissionregistrationv1.ValidatingWebhookConfiguration - key := types.NamespacedName{ - Name: name, - } - - err = client.Get(context.Background(), key, &updatedValidatingWebhookConfiguration) + err = client.Get(context.Background(), config.ValidatingWebhookName, &updatedValidatingWebhookConfiguration) require.NoError(t, err) var chainChecker certChainCheckerImpl @@ -219,13 +313,30 @@ func TestUpdateValidatingWebhookConfig(t *testing.T) { certValid, err = chainChecker.checkRoot(context.Background(), newServerCert, updatedValidatingWebhookConfiguration.Webhooks[1].ClientConfig.CABundle) require.NoError(t, err) require.True(t, certValid) + + var updatedMutatingWebhookConfiguration admissionregistrationv1.MutatingWebhookConfiguration + + err = client.Get(context.Background(), config.MutatingWebhookName, &updatedMutatingWebhookConfiguration) + require.NoError(t, err) + + mutatingCertValid, err := chainChecker.checkRoot(context.Background(), newServerCert, updatedMutatingWebhookConfiguration.Webhooks[0].ClientConfig.CABundle) + require.NoError(t, err) + require.True(t, mutatingCertValid) + + mutatingCertValid, err = chainChecker.checkRoot(context.Background(), newServerCert, updatedMutatingWebhookConfiguration.Webhooks[1].ClientConfig.CABundle) + require.NoError(t, err) + require.True(t, mutatingCertValid) + + mutatingCertValid, err = chainChecker.checkRoot(context.Background(), newServerCert, updatedMutatingWebhookConfiguration.Webhooks[2].ClientConfig.CABundle) + require.NoError(t, err) + require.True(t, mutatingCertValid) } func TestCreateSecret(t *testing.T) { scheme := runtime.NewScheme() require.NoError(t, clientgoscheme.AddToScheme(scheme)) require.NoError(t, apiextensionsv1.AddToScheme(scheme)) - client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &initialValidatingWebhookConfiguration).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() certDir, err := os.MkdirTemp("", "certificate") require.NoError(t, err) @@ -236,10 +347,11 @@ func TestCreateSecret(t *testing.T) { }(certDir) config := Config{ - CertDir: certDir, - ServiceName: webhookService, - CASecretName: caBundleSecret, - WebhookName: webhookName, + CertDir: certDir, + ServiceName: webhookService, + CASecretName: caBundleSecret, + ValidatingWebhookName: validatingWebhookNamespacedName, + MutatingWebhookName: mutatingWebhookNamespacedName, } err = EnsureCertificate(context.TODO(), client, config) @@ -257,7 +369,7 @@ func TestReuseExistingCertificate(t *testing.T) { scheme := runtime.NewScheme() require.NoError(t, clientgoscheme.AddToScheme(scheme)) require.NoError(t, apiextensionsv1.AddToScheme(scheme)) - client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &initialValidatingWebhookConfiguration).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() certDir, err := os.MkdirTemp("", "certificate") require.NoError(t, err) @@ -268,28 +380,44 @@ func TestReuseExistingCertificate(t *testing.T) { }(certDir) config := Config{ - CertDir: certDir, - ServiceName: webhookService, - CASecretName: caBundleSecret, - WebhookName: webhookName, + CertDir: certDir, + ServiceName: webhookService, + CASecretName: caBundleSecret, + ValidatingWebhookName: validatingWebhookNamespacedName, + MutatingWebhookName: mutatingWebhookNamespacedName, } err = EnsureCertificate(context.TODO(), client, config) require.NoError(t, err) var newValidatingWebhookConfiguration admissionregistrationv1.ValidatingWebhookConfiguration - err = client.Get(context.Background(), types.NamespacedName{Name: name}, &newValidatingWebhookConfiguration) + err = client.Get(context.Background(), config.ValidatingWebhookName, &newValidatingWebhookConfiguration) + require.NoError(t, err) + + var newMutatingWebhookConfiguration admissionregistrationv1.MutatingWebhookConfiguration + err = client.Get(context.Background(), config.MutatingWebhookName, &newMutatingWebhookConfiguration) require.NoError(t, err) err = EnsureCertificate(context.TODO(), client, config) require.NoError(t, err) var updatedValidatingWebhookConfiguration admissionregistrationv1.ValidatingWebhookConfiguration - err = client.Get(context.Background(), types.NamespacedName{Name: name}, &updatedValidatingWebhookConfiguration) + err = client.Get(context.Background(), config.ValidatingWebhookName, &updatedValidatingWebhookConfiguration) require.NoError(t, err) require.Equal(t, newValidatingWebhookConfiguration.Webhooks[0].ClientConfig.CABundle, updatedValidatingWebhookConfiguration.Webhooks[0].ClientConfig.CABundle) require.Equal(t, newValidatingWebhookConfiguration.Webhooks[1].ClientConfig.CABundle, updatedValidatingWebhookConfiguration.Webhooks[1].ClientConfig.CABundle) + + var updatedMutatingWebhookConfiguration admissionregistrationv1.MutatingWebhookConfiguration + err = client.Get(context.Background(), config.MutatingWebhookName, &updatedMutatingWebhookConfiguration) + require.NoError(t, err) + + require.Equal(t, newMutatingWebhookConfiguration.Webhooks[0].ClientConfig.CABundle, + updatedMutatingWebhookConfiguration.Webhooks[0].ClientConfig.CABundle) + require.Equal(t, newMutatingWebhookConfiguration.Webhooks[1].ClientConfig.CABundle, + updatedMutatingWebhookConfiguration.Webhooks[1].ClientConfig.CABundle) + require.Equal(t, newMutatingWebhookConfiguration.Webhooks[2].ClientConfig.CABundle, + updatedMutatingWebhookConfiguration.Webhooks[2].ClientConfig.CABundle) } diff --git a/main.go b/main.go index 10104e0ab..365134719 100644 --- a/main.go +++ b/main.go @@ -56,8 +56,13 @@ import ( selfmonitorwebhook "github.com/kyma-project/telemetry-manager/internal/selfmonitor/webhook" loggerutils "github.com/kyma-project/telemetry-manager/internal/utils/logger" "github.com/kyma-project/telemetry-manager/internal/webhookcert" - logparserwebhook "github.com/kyma-project/telemetry-manager/webhook/logparser" - logpipelinewebhook "github.com/kyma-project/telemetry-manager/webhook/logpipeline" + logparserwebhookv1alpha1 "github.com/kyma-project/telemetry-manager/webhook/logparser/v1alpha1" + logpipelinewebhookv1alpha1 "github.com/kyma-project/telemetry-manager/webhook/logpipeline/v1alpha1" + logpipelinewebhookv1beta1 "github.com/kyma-project/telemetry-manager/webhook/logpipeline/v1beta1" + metricpipelinewebhookv1alpha1 "github.com/kyma-project/telemetry-manager/webhook/metricpipeline/v1alpha1" + metricpipelinewebhookv1beta1 "github.com/kyma-project/telemetry-manager/webhook/metricpipeline/v1beta1" + tracepipelinewebhookv1alpha1 "github.com/kyma-project/telemetry-manager/webhook/tracepipeline/v1alpha1" + tracepipelinewebhookv1beta1 "github.com/kyma-project/telemetry-manager/webhook/tracepipeline/v1beta1" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. @@ -168,6 +173,8 @@ func init() { // +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=validatingwebhookconfigurations,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=mutatingwebhookconfigurations,verbs=get;list;watch;create;update;patch;delete + // +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=clusterroles,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=clusterrolebindings,verbs=get;list;watch;create;update;patch;delete @@ -316,11 +323,16 @@ func run() error { } mgr.GetWebhookServer().Register("/validate-logpipeline", &webhook.Admission{ - Handler: logpipelinewebhook.NewValidatingWebhookHandler(mgr.GetClient(), scheme), + Handler: logpipelinewebhookv1alpha1.NewValidatingWebhookHandler(mgr.GetClient(), scheme), }) mgr.GetWebhookServer().Register("/validate-logparser", &webhook.Admission{ - Handler: logparserwebhook.NewValidatingWebhookHandler(scheme), + Handler: logparserwebhookv1alpha1.NewValidatingWebhookHandler(scheme), }) + + if err := setupMutatingWebhooks(mgr); err != nil { + return fmt.Errorf("failed to setup mutating webhooks: %w", err) + } + mgr.GetWebhookServer().Register("/api/v2/alerts", selfmonitorwebhook.NewHandler( mgr.GetClient(), selfmonitorwebhook.WithTracePipelineSubscriber(tracePipelineReconcileTriggerChan), @@ -335,6 +347,40 @@ func run() error { return nil } +func setupMutatingWebhooks(mgr manager.Manager) error { + if err := metricpipelinewebhookv1alpha1.SetupMetricPipelineWebhookWithManager(mgr); err != nil { + return fmt.Errorf("failed to setup metric pipeline v1alpha1 webhook: %w", err) + } + + if featureflags.IsEnabled(featureflags.V1Beta1) { + if err := metricpipelinewebhookv1beta1.SetupMetricPipelineWebhookWithManager(mgr); err != nil { + return fmt.Errorf("failed to setup metric pipeline v1beta1 webhook: %w", err) + } + } + + if err := tracepipelinewebhookv1alpha1.SetupTracePipelineWebhookWithManager(mgr); err != nil { + return fmt.Errorf("failed to setup trace pipeline v1alpha1 webhook: %w", err) + } + + if featureflags.IsEnabled(featureflags.V1Beta1) { + if err := tracepipelinewebhookv1beta1.SetupTracePipelineWebhookWithManager(mgr); err != nil { + return fmt.Errorf("failed to setup trace pipeline v1beta1 webhook: %w", err) + } + } + + if err := logpipelinewebhookv1alpha1.SetupLogPipelineWebhookWithManager(mgr); err != nil { + return fmt.Errorf("failed to setup log pipeline v1alpha1 webhook: %w", err) + } + + if featureflags.IsEnabled(featureflags.V1Beta1) { + if err := logpipelinewebhookv1beta1.SetupLogPipelineWebhookWithManager(mgr); err != nil { + return fmt.Errorf("failed to setup log pipeline v1beta1 webhook: %w", err) + } + } + + return nil +} + func enableTelemetryModuleController(mgr manager.Manager, webhookConfig telemetry.WebhookConfig, selfMonitorConfig telemetry.SelfMonitorConfig) error { setupLog.Info("Setting up telemetry controller") @@ -527,9 +573,12 @@ func createWebhookConfig() telemetry.WebhookConfig { Name: "telemetry-webhook-cert", Namespace: telemetryNamespace, }, - WebhookName: types.NamespacedName{ + ValidatingWebhookName: types.NamespacedName{ Name: "telemetry-validating-webhook.kyma-project.io", }, + MutatingWebhookName: types.NamespacedName{ + Name: "telemetry-mutating-webhook.kyma-project.io", + }, }, } } diff --git a/webhook/logparser/spec_validator.go b/webhook/logparser/v1alpha1/spec_validator.go similarity index 96% rename from webhook/logparser/spec_validator.go rename to webhook/logparser/v1alpha1/spec_validator.go index 3ba6d346c..4b2980151 100644 --- a/webhook/logparser/spec_validator.go +++ b/webhook/logparser/v1alpha1/spec_validator.go @@ -1,4 +1,4 @@ -package logparser +package v1alpha1 import ( "fmt" diff --git a/webhook/logparser/webhook.go b/webhook/logparser/v1alpha1/webhook.go similarity index 98% rename from webhook/logparser/webhook.go rename to webhook/logparser/v1alpha1/webhook.go index 445feee0f..1854db6da 100644 --- a/webhook/logparser/webhook.go +++ b/webhook/logparser/v1alpha1/webhook.go @@ -1,4 +1,4 @@ -package logparser +package v1alpha1 import ( "context" diff --git a/webhook/logpipeline/v1alpha1/defaulter.go b/webhook/logpipeline/v1alpha1/defaulter.go new file mode 100644 index 000000000..5723568b1 --- /dev/null +++ b/webhook/logpipeline/v1alpha1/defaulter.go @@ -0,0 +1,52 @@ +package v1alpha1 + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + telemetryv1alpha1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1alpha1" +) + +// +kubebuilder:object:generate=false +var _ webhook.CustomDefaulter = &LogPipelineDefaulter{} + +type LogPipelineDefaulter struct { + ApplicationInputEnabled bool + ApplicationInputKeepOriginalBody bool +} + +func SetupLogPipelineWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&telemetryv1alpha1.LogPipeline{}). + WithDefaulter(&LogPipelineDefaulter{ + ApplicationInputEnabled: true, + ApplicationInputKeepOriginalBody: true, + }). + Complete() +} + +func (ld LogPipelineDefaulter) Default(ctx context.Context, obj runtime.Object) error { + pipeline, ok := obj.(*telemetryv1alpha1.LogPipeline) + if !ok { + return fmt.Errorf("expected an LogPipeline object but got %T", obj) + } + + ld.applyDefaults(pipeline) + + return nil +} + +func (ld LogPipelineDefaulter) applyDefaults(pipeline *telemetryv1alpha1.LogPipeline) { + if pipeline.Spec.Input.Application != nil { + if pipeline.Spec.Input.Application.Enabled == nil { + pipeline.Spec.Input.Application.Enabled = &ld.ApplicationInputEnabled + } + + if pipeline.Spec.Input.Application.KeepOriginalBody == nil { + pipeline.Spec.Input.Application.KeepOriginalBody = &ld.ApplicationInputKeepOriginalBody + } + } +} diff --git a/webhook/logpipeline/v1alpha1/defaulter_test.go b/webhook/logpipeline/v1alpha1/defaulter_test.go new file mode 100644 index 000000000..6937c5857 --- /dev/null +++ b/webhook/logpipeline/v1alpha1/defaulter_test.go @@ -0,0 +1,75 @@ +package v1alpha1 + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/utils/ptr" + + telemetryv1alpha1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1alpha1" +) + +func TestDefault(t *testing.T) { + defaulter := LogPipelineDefaulter{ + ApplicationInputEnabled: true, + ApplicationInputKeepOriginalBody: true, + } + + tests := []struct { + name string + input *telemetryv1alpha1.LogPipeline + expected *telemetryv1alpha1.LogPipeline + }{ + { + name: "should set default ApplicationInput if not set", + input: &telemetryv1alpha1.LogPipeline{ + Spec: telemetryv1alpha1.LogPipelineSpec{ + Input: telemetryv1alpha1.LogPipelineInput{ + Application: &telemetryv1alpha1.LogPipelineApplicationInput{}, + }, + }, + }, + expected: &telemetryv1alpha1.LogPipeline{ + Spec: telemetryv1alpha1.LogPipelineSpec{ + Input: telemetryv1alpha1.LogPipelineInput{ + Application: &telemetryv1alpha1.LogPipelineApplicationInput{ + Enabled: ptr.To(true), + KeepOriginalBody: ptr.To(true), + }, + }, + }, + }, + }, + { + name: "should skip default ApplicationInput if set", + input: &telemetryv1alpha1.LogPipeline{ + Spec: telemetryv1alpha1.LogPipelineSpec{ + Input: telemetryv1alpha1.LogPipelineInput{ + Application: &telemetryv1alpha1.LogPipelineApplicationInput{ + KeepOriginalBody: ptr.To(false), + }, + }, + }, + }, + expected: &telemetryv1alpha1.LogPipeline{ + Spec: telemetryv1alpha1.LogPipelineSpec{ + Input: telemetryv1alpha1.LogPipelineInput{ + Application: &telemetryv1alpha1.LogPipelineApplicationInput{ + Enabled: ptr.To(true), + KeepOriginalBody: ptr.To(false), + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := defaulter.Default(context.Background(), tt.input) + assert.NoError(t, err) + assert.Equal(t, tt.expected, tt.input) + }) + } +} diff --git a/webhook/logpipeline/files_validator.go b/webhook/logpipeline/v1alpha1/files_validator.go similarity index 98% rename from webhook/logpipeline/files_validator.go rename to webhook/logpipeline/v1alpha1/files_validator.go index 42c2484a5..bf9901981 100644 --- a/webhook/logpipeline/files_validator.go +++ b/webhook/logpipeline/v1alpha1/files_validator.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "fmt" diff --git a/webhook/logpipeline/files_validator_test.go b/webhook/logpipeline/v1alpha1/files_validator_test.go similarity index 99% rename from webhook/logpipeline/files_validator_test.go rename to webhook/logpipeline/v1alpha1/files_validator_test.go index 3325376b8..79b6331e8 100644 --- a/webhook/logpipeline/files_validator_test.go +++ b/webhook/logpipeline/v1alpha1/files_validator_test.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "context" diff --git a/webhook/logpipeline/handler.go b/webhook/logpipeline/v1alpha1/handler.go similarity index 99% rename from webhook/logpipeline/handler.go rename to webhook/logpipeline/v1alpha1/handler.go index dfb96de61..8f3103241 100644 --- a/webhook/logpipeline/handler.go +++ b/webhook/logpipeline/v1alpha1/handler.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "context" diff --git a/webhook/logpipeline/handler_test.go b/webhook/logpipeline/v1alpha1/handler_test.go similarity index 99% rename from webhook/logpipeline/handler_test.go rename to webhook/logpipeline/v1alpha1/handler_test.go index 1df1fca88..43e2addda 100644 --- a/webhook/logpipeline/handler_test.go +++ b/webhook/logpipeline/v1alpha1/handler_test.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "context" diff --git a/webhook/logpipeline/max_pipelines_validator.go b/webhook/logpipeline/v1alpha1/max_pipelines_validator.go similarity index 97% rename from webhook/logpipeline/max_pipelines_validator.go rename to webhook/logpipeline/v1alpha1/max_pipelines_validator.go index 4fb34e1ed..0d6b9be64 100644 --- a/webhook/logpipeline/max_pipelines_validator.go +++ b/webhook/logpipeline/v1alpha1/max_pipelines_validator.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "fmt" diff --git a/webhook/logpipeline/max_pipelines_validator_test.go b/webhook/logpipeline/v1alpha1/max_pipelines_validator_test.go similarity index 99% rename from webhook/logpipeline/max_pipelines_validator_test.go rename to webhook/logpipeline/v1alpha1/max_pipelines_validator_test.go index 530648d71..74107f40e 100644 --- a/webhook/logpipeline/max_pipelines_validator_test.go +++ b/webhook/logpipeline/v1alpha1/max_pipelines_validator_test.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "context" diff --git a/webhook/logpipeline/spec_validator.go b/webhook/logpipeline/v1alpha1/spec_validator.go similarity index 99% rename from webhook/logpipeline/spec_validator.go rename to webhook/logpipeline/v1alpha1/spec_validator.go index b9d8fb9a9..9ebfe35d6 100644 --- a/webhook/logpipeline/spec_validator.go +++ b/webhook/logpipeline/v1alpha1/spec_validator.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "errors" diff --git a/webhook/logpipeline/spec_validator_test.go b/webhook/logpipeline/v1alpha1/spec_validator_test.go similarity index 99% rename from webhook/logpipeline/spec_validator_test.go rename to webhook/logpipeline/v1alpha1/spec_validator_test.go index f86d18141..eec8fa9de 100644 --- a/webhook/logpipeline/spec_validator_test.go +++ b/webhook/logpipeline/v1alpha1/spec_validator_test.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "context" diff --git a/webhook/logpipeline/variable_validator.go b/webhook/logpipeline/v1alpha1/variable_validator.go similarity index 98% rename from webhook/logpipeline/variable_validator.go rename to webhook/logpipeline/v1alpha1/variable_validator.go index 12795d8de..daa826167 100644 --- a/webhook/logpipeline/variable_validator.go +++ b/webhook/logpipeline/v1alpha1/variable_validator.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "fmt" diff --git a/webhook/logpipeline/variable_validator_test.go b/webhook/logpipeline/v1alpha1/variable_validator_test.go similarity index 99% rename from webhook/logpipeline/variable_validator_test.go rename to webhook/logpipeline/v1alpha1/variable_validator_test.go index 01c48b15d..33d411245 100644 --- a/webhook/logpipeline/variable_validator_test.go +++ b/webhook/logpipeline/v1alpha1/variable_validator_test.go @@ -1,4 +1,4 @@ -package logpipeline +package v1alpha1 import ( "context" diff --git a/webhook/logpipeline/v1beta1/defaulter.go b/webhook/logpipeline/v1beta1/defaulter.go new file mode 100644 index 000000000..58777f017 --- /dev/null +++ b/webhook/logpipeline/v1beta1/defaulter.go @@ -0,0 +1,58 @@ +package v1beta1 + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" +) + +// +kubebuilder:object:generate=false +var _ webhook.CustomDefaulter = &LogPipelineDefaulter{} + +type LogPipelineDefaulter struct { + RuntimeInputEnabled bool + RuntimeInputKeepOriginalBody bool + DefaultOTLPOutputProtocol telemetryv1beta1.OTLPProtocol +} + +func SetupLogPipelineWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&telemetryv1beta1.LogPipeline{}). + WithDefaulter(&LogPipelineDefaulter{ + RuntimeInputEnabled: true, + RuntimeInputKeepOriginalBody: true, + DefaultOTLPOutputProtocol: telemetryv1beta1.OTLPProtocolGRPC, + }). + Complete() +} + +func (ld LogPipelineDefaulter) Default(ctx context.Context, obj runtime.Object) error { + pipeline, ok := obj.(*telemetryv1beta1.LogPipeline) + if !ok { + return fmt.Errorf("expected an LogPipeline object but got %T", obj) + } + + ld.applyDefaults(pipeline) + + return nil +} + +func (ld LogPipelineDefaulter) applyDefaults(pipeline *telemetryv1beta1.LogPipeline) { + if pipeline.Spec.Input.Runtime != nil { + if pipeline.Spec.Input.Runtime.Enabled == nil { + pipeline.Spec.Input.Runtime.Enabled = &ld.RuntimeInputEnabled + } + + if pipeline.Spec.Input.Runtime.KeepOriginalBody == nil { + pipeline.Spec.Input.Runtime.KeepOriginalBody = &ld.RuntimeInputKeepOriginalBody + } + } + + if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { + pipeline.Spec.Output.OTLP.Protocol = ld.DefaultOTLPOutputProtocol + } +} diff --git a/webhook/logpipeline/v1beta1/defaulter_test.go b/webhook/logpipeline/v1beta1/defaulter_test.go new file mode 100644 index 000000000..785f0e95d --- /dev/null +++ b/webhook/logpipeline/v1beta1/defaulter_test.go @@ -0,0 +1,95 @@ +package v1beta1 + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/utils/ptr" + + telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" +) + +func TestDefault(t *testing.T) { + defaulter := LogPipelineDefaulter{ + RuntimeInputEnabled: true, + RuntimeInputKeepOriginalBody: true, + DefaultOTLPOutputProtocol: telemetryv1beta1.OTLPProtocolGRPC, + } + + tests := []struct { + name string + input *telemetryv1beta1.LogPipeline + expected *telemetryv1beta1.LogPipeline + }{ + { + name: "should set default ApplicationInput if not set", + input: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{}, + }, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Enabled: ptr.To(true), + KeepOriginalBody: ptr.To(true), + }, + }, + }, + }, + }, + { + name: "should skip default ApplicationInput if set", + input: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + KeepOriginalBody: ptr.To(false), + }, + }, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Enabled: ptr.To(true), + KeepOriginalBody: ptr.To(false), + }, + }, + }, + }, + }, + { + name: "should set default OTLPOutput if not set", + input: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Output: telemetryv1beta1.LogPipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{}, + }, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Output: telemetryv1beta1.LogPipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Protocol: telemetryv1beta1.OTLPProtocolGRPC, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := defaulter.Default(context.Background(), tt.input) + assert.NoError(t, err) + assert.Equal(t, tt.expected, tt.input) + }) + } +} diff --git a/webhook/metricpipeline/v1alpha1/defaulter.go b/webhook/metricpipeline/v1alpha1/defaulter.go new file mode 100644 index 000000000..b52eb1ebe --- /dev/null +++ b/webhook/metricpipeline/v1alpha1/defaulter.go @@ -0,0 +1,144 @@ +package v1alpha1 + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + telemetryv1alpha1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1alpha1" +) + +// +kubebuilder:object:generate=false +var _ webhook.CustomDefaulter = &MetricPipelineDefaulter{} + +type MetricPipelineDefaulter struct { + ExcludeNamespaces []string + RuntimeInputResources RuntimeInputResourceDefaults + DefaultOTLPOutputProtocol string +} + +type RuntimeInputResourceDefaults struct { + Pod bool + Container bool + Node bool + Volume bool + DaemonSet bool + Deployment bool + StatefulSet bool + Job bool +} + +func SetupMetricPipelineWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&telemetryv1alpha1.MetricPipeline{}). + WithDefaulter(&MetricPipelineDefaulter{ + ExcludeNamespaces: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + RuntimeInputResources: RuntimeInputResourceDefaults{ + Pod: true, + Container: true, + Node: true, + Volume: true, + DaemonSet: true, + Deployment: true, + StatefulSet: true, + Job: true, + }, + DefaultOTLPOutputProtocol: telemetryv1alpha1.OTLPProtocolGRPC, + }). + Complete() +} + +func (md MetricPipelineDefaulter) Default(ctx context.Context, obj runtime.Object) error { + pipeline, ok := obj.(*telemetryv1alpha1.MetricPipeline) + if !ok { + return fmt.Errorf("expected an MetricPipeline object but got %T", obj) + } + + md.applyDefaults(pipeline) + + return nil +} + +func (md MetricPipelineDefaulter) applyDefaults(pipeline *telemetryv1alpha1.MetricPipeline) { + if pipeline.Spec.Input.Prometheus != nil && pipeline.Spec.Input.Prometheus.Namespaces == nil { + pipeline.Spec.Input.Prometheus.Namespaces = &telemetryv1alpha1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } + } + + if pipeline.Spec.Input.Istio != nil && pipeline.Spec.Input.Istio.Namespaces == nil { + pipeline.Spec.Input.Istio.Namespaces = &telemetryv1alpha1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } + } + + if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { + pipeline.Spec.Output.OTLP.Protocol = md.DefaultOTLPOutputProtocol + } + + if pipeline.Spec.Input.Runtime != nil && pipeline.Spec.Input.Runtime.Namespaces == nil { + pipeline.Spec.Input.Runtime.Namespaces = &telemetryv1alpha1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } + } + + if pipeline.Spec.Input.Runtime != nil { + md.applyRuntimeInputResourceDefaults(pipeline) + } +} + +func (md MetricPipelineDefaulter) applyRuntimeInputResourceDefaults(pipeline *telemetryv1alpha1.MetricPipeline) { + if pipeline.Spec.Input.Runtime.Resources == nil { + pipeline.Spec.Input.Runtime.Resources = &telemetryv1alpha1.MetricPipelineRuntimeInputResources{} + } + + if pipeline.Spec.Input.Runtime.Resources.Pod == nil { + pipeline.Spec.Input.Runtime.Resources.Pod = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Pod, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Container == nil { + pipeline.Spec.Input.Runtime.Resources.Container = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Container, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Node == nil { + pipeline.Spec.Input.Runtime.Resources.Node = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Node, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Volume == nil { + pipeline.Spec.Input.Runtime.Resources.Volume = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Volume, + } + } + + if pipeline.Spec.Input.Runtime.Resources.DaemonSet == nil { + pipeline.Spec.Input.Runtime.Resources.DaemonSet = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.DaemonSet, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Deployment == nil { + pipeline.Spec.Input.Runtime.Resources.Deployment = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Deployment, + } + } + + if pipeline.Spec.Input.Runtime.Resources.StatefulSet == nil { + pipeline.Spec.Input.Runtime.Resources.StatefulSet = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.StatefulSet, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Job == nil { + pipeline.Spec.Input.Runtime.Resources.Job = &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Job, + } + } +} diff --git a/webhook/metricpipeline/v1alpha1/defaulter_test.go b/webhook/metricpipeline/v1alpha1/defaulter_test.go new file mode 100644 index 000000000..1e50b608b --- /dev/null +++ b/webhook/metricpipeline/v1alpha1/defaulter_test.go @@ -0,0 +1,241 @@ +package v1alpha1 + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/utils/ptr" + + telemetryv1alpha1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1alpha1" +) + +func TestDefault(t *testing.T) { + defaulter := MetricPipelineDefaulter{ + ExcludeNamespaces: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + RuntimeInputResources: RuntimeInputResourceDefaults{ + Pod: true, + Container: true, + Node: true, + Volume: true, + DaemonSet: true, + Deployment: true, + StatefulSet: true, + Job: true, + }, + DefaultOTLPOutputProtocol: telemetryv1alpha1.OTLPProtocolGRPC, + } + + tests := []struct { + name string + input *telemetryv1alpha1.MetricPipeline + expected *telemetryv1alpha1.MetricPipeline + }{ + { + name: "should set default OTLP protocol if not set", + input: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Output: telemetryv1alpha1.MetricPipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{}, + }, + }, + }, + expected: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Output: telemetryv1alpha1.MetricPipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Protocol: telemetryv1alpha1.OTLPProtocolGRPC, + }, + }, + }, + }, + }, + { + name: "should not override existing OTLP protocol", + input: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Output: telemetryv1alpha1.MetricPipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Protocol: telemetryv1alpha1.OTLPProtocolHTTP, + }, + }, + }, + }, + expected: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Output: telemetryv1alpha1.MetricPipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Protocol: telemetryv1alpha1.OTLPProtocolHTTP, + }, + }, + }, + }, + }, + { + name: "should set default namespaces for Prometheus input", + input: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{}, + }, + }, + }, + expected: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{ + Exclude: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + }, + }, + }, + }, + }, + }, + { + name: "should set default namespaces for Istio input", + input: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + Istio: &telemetryv1alpha1.MetricPipelineIstioInput{}, + }, + }, + }, + expected: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{ + Exclude: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + }, + }, + }, + }, + }, + }, + + { + name: "should set default for Runtime input", + input: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{}, + }, + }, + }, + expected: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{ + Exclude: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + }, + Resources: &telemetryv1alpha1.MetricPipelineRuntimeInputResources{ + Pod: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Container: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Node: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Volume: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Deployment: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Job: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + StatefulSet: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + DaemonSet: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + }, + }, + }, + }, + }, + }, + + { + name: "should set default for Runtime input except for Pod", + input: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{ + Resources: &telemetryv1alpha1.MetricPipelineRuntimeInputResources{ + Pod: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + }, + }, + }, + }, + }, + expected: &telemetryv1alpha1.MetricPipeline{ + Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{ + Exclude: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + }, + Resources: &telemetryv1alpha1.MetricPipelineRuntimeInputResources{ + Pod: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + + Container: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Node: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Volume: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Deployment: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Job: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + StatefulSet: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + DaemonSet: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + }, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := defaulter.Default(context.Background(), tt.input) + assert.NoError(t, err) + assert.Equal(t, tt.expected, tt.input) + }) + } +} diff --git a/webhook/metricpipeline/v1beta1/defaulter.go b/webhook/metricpipeline/v1beta1/defaulter.go new file mode 100644 index 000000000..1a5e456bd --- /dev/null +++ b/webhook/metricpipeline/v1beta1/defaulter.go @@ -0,0 +1,144 @@ +package v1beta1 + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" +) + +// +kubebuilder:object:generate=false +var _ webhook.CustomDefaulter = &MetricPipelineDefaulter{} + +type MetricPipelineDefaulter struct { + ExcludeNamespaces []string + RuntimeInputResources RuntimeInputResourceDefaults + DefaultOTLPOutputProtocol telemetryv1beta1.OTLPProtocol +} + +type RuntimeInputResourceDefaults struct { + Pod bool + Container bool + Node bool + Volume bool + DaemonSet bool + Deployment bool + StatefulSet bool + Job bool +} + +func SetupMetricPipelineWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&telemetryv1beta1.MetricPipeline{}). + WithDefaulter(&MetricPipelineDefaulter{ + ExcludeNamespaces: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + RuntimeInputResources: RuntimeInputResourceDefaults{ + Pod: true, + Container: true, + Node: true, + Volume: true, + DaemonSet: true, + Deployment: true, + StatefulSet: true, + Job: true, + }, + DefaultOTLPOutputProtocol: telemetryv1beta1.OTLPProtocolGRPC, + }). + Complete() +} + +func (md MetricPipelineDefaulter) Default(ctx context.Context, obj runtime.Object) error { + pipeline, ok := obj.(*telemetryv1beta1.MetricPipeline) + if !ok { + return fmt.Errorf("expected an MetricPipeline object but got %T", obj) + } + + md.applyDefaults(pipeline) + + return nil +} + +func (md MetricPipelineDefaulter) applyDefaults(pipeline *telemetryv1beta1.MetricPipeline) { + if pipeline.Spec.Input.Prometheus != nil && pipeline.Spec.Input.Prometheus.Namespaces == nil { + pipeline.Spec.Input.Prometheus.Namespaces = &telemetryv1beta1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } + } + + if pipeline.Spec.Input.Istio != nil && pipeline.Spec.Input.Istio.Namespaces == nil { + pipeline.Spec.Input.Istio.Namespaces = &telemetryv1beta1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } + } + + if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { + pipeline.Spec.Output.OTLP.Protocol = md.DefaultOTLPOutputProtocol + } + + if pipeline.Spec.Input.Runtime != nil && pipeline.Spec.Input.Runtime.Namespaces == nil { + pipeline.Spec.Input.Runtime.Namespaces = &telemetryv1beta1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } + } + + if pipeline.Spec.Input.Runtime != nil { + md.applyRuntimeInputResourceDefaults(pipeline) + } +} + +func (md MetricPipelineDefaulter) applyRuntimeInputResourceDefaults(pipeline *telemetryv1beta1.MetricPipeline) { + if pipeline.Spec.Input.Runtime.Resources == nil { + pipeline.Spec.Input.Runtime.Resources = &telemetryv1beta1.MetricPipelineRuntimeInputResources{} + } + + if pipeline.Spec.Input.Runtime.Resources.Pod == nil { + pipeline.Spec.Input.Runtime.Resources.Pod = &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Pod, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Container == nil { + pipeline.Spec.Input.Runtime.Resources.Container = &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Container, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Node == nil { + pipeline.Spec.Input.Runtime.Resources.Node = &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Node, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Volume == nil { + pipeline.Spec.Input.Runtime.Resources.Volume = &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Volume, + } + } + + if pipeline.Spec.Input.Runtime.Resources.DaemonSet == nil { + pipeline.Spec.Input.Runtime.Resources.DaemonSet = &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.DaemonSet, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Deployment == nil { + pipeline.Spec.Input.Runtime.Resources.Deployment = &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Deployment, + } + } + + if pipeline.Spec.Input.Runtime.Resources.StatefulSet == nil { + pipeline.Spec.Input.Runtime.Resources.StatefulSet = &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.StatefulSet, + } + } + + if pipeline.Spec.Input.Runtime.Resources.Job == nil { + pipeline.Spec.Input.Runtime.Resources.Job = &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: &md.RuntimeInputResources.Job, + } + } +} diff --git a/webhook/metricpipeline/v1beta1/defaulter_test.go b/webhook/metricpipeline/v1beta1/defaulter_test.go new file mode 100644 index 000000000..668e5980c --- /dev/null +++ b/webhook/metricpipeline/v1beta1/defaulter_test.go @@ -0,0 +1,241 @@ +package v1beta1 + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/utils/ptr" + + telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" +) + +func TestDefault(t *testing.T) { + defaulter := MetricPipelineDefaulter{ + ExcludeNamespaces: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + RuntimeInputResources: RuntimeInputResourceDefaults{ + Pod: true, + Container: true, + Node: true, + Volume: true, + DaemonSet: true, + Deployment: true, + StatefulSet: true, + Job: true, + }, + DefaultOTLPOutputProtocol: telemetryv1beta1.OTLPProtocolGRPC, + } + + tests := []struct { + name string + input *telemetryv1beta1.MetricPipeline + expected *telemetryv1beta1.MetricPipeline + }{ + { + name: "should set default OTLP protocol if not set", + input: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Output: telemetryv1beta1.MetricPipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{}, + }, + }, + }, + expected: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Output: telemetryv1beta1.MetricPipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Protocol: telemetryv1beta1.OTLPProtocolGRPC, + }, + }, + }, + }, + }, + { + name: "should not override existing OTLP protocol", + input: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Output: telemetryv1beta1.MetricPipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Protocol: telemetryv1beta1.OTLPProtocolHTTP, + }, + }, + }, + }, + expected: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Output: telemetryv1beta1.MetricPipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Protocol: telemetryv1beta1.OTLPProtocolHTTP, + }, + }, + }, + }, + }, + { + name: "should set default namespaces for Prometheus input", + input: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Prometheus: &telemetryv1beta1.MetricPipelinePrometheusInput{}, + }, + }, + }, + expected: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Prometheus: &telemetryv1beta1.MetricPipelinePrometheusInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + }, + }, + }, + }, + }, + }, + { + name: "should set default namespaces for Istio input", + input: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Istio: &telemetryv1beta1.MetricPipelineIstioInput{}, + }, + }, + }, + expected: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Istio: &telemetryv1beta1.MetricPipelineIstioInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + }, + }, + }, + }, + }, + }, + + { + name: "should set default for Runtime input", + input: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{}, + }, + }, + }, + expected: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + }, + Resources: &telemetryv1beta1.MetricPipelineRuntimeInputResources{ + Pod: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Container: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Node: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Volume: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Deployment: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Job: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + StatefulSet: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + DaemonSet: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + }, + }, + }, + }, + }, + }, + + { + name: "should set default for Runtime input except for Pod", + input: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ + Resources: &telemetryv1beta1.MetricPipelineRuntimeInputResources{ + Pod: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + }, + }, + }, + }, + }, + expected: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: []string{"kyma-system", "kube-system", "istio-system", "compass-system"}, + }, + Resources: &telemetryv1beta1.MetricPipelineRuntimeInputResources{ + Pod: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + + Container: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Node: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Volume: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Deployment: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + Job: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + StatefulSet: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + + DaemonSet: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(true), + }, + }, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := defaulter.Default(context.Background(), tt.input) + assert.NoError(t, err) + assert.Equal(t, tt.expected, tt.input) + }) + } +} diff --git a/webhook/tracepipeline/v1alpha1/defaulter.go b/webhook/tracepipeline/v1alpha1/defaulter.go new file mode 100644 index 000000000..5ee8d711a --- /dev/null +++ b/webhook/tracepipeline/v1alpha1/defaulter.go @@ -0,0 +1,44 @@ +package v1alpha1 + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + telemetryv1alpha1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1alpha1" +) + +// +kubebuilder:object:generate=false +var _ webhook.CustomDefaulter = &TracePipelineDefaulter{} + +type TracePipelineDefaulter struct { + DefaultOTLPOutputProtocol string +} + +func SetupTracePipelineWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&telemetryv1alpha1.TracePipeline{}). + WithDefaulter(&TracePipelineDefaulter{ + DefaultOTLPOutputProtocol: telemetryv1alpha1.OTLPProtocolGRPC, + }). + Complete() +} + +func (td TracePipelineDefaulter) Default(ctx context.Context, obj runtime.Object) error { + pipeline, ok := obj.(*telemetryv1alpha1.TracePipeline) + if !ok { + return fmt.Errorf("expected an TracePipeline object but got %T", obj) + } + + td.applyDefaults(pipeline) + + return nil +} + +func (td TracePipelineDefaulter) applyDefaults(pipeline *telemetryv1alpha1.TracePipeline) { + if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { + pipeline.Spec.Output.OTLP.Protocol = td.DefaultOTLPOutputProtocol + } +} diff --git a/webhook/tracepipeline/v1alpha1/defaulter_test.go b/webhook/tracepipeline/v1alpha1/defaulter_test.go new file mode 100644 index 000000000..31aa25bae --- /dev/null +++ b/webhook/tracepipeline/v1alpha1/defaulter_test.go @@ -0,0 +1,71 @@ +package v1alpha1 + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + telemetryv1alpha1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1alpha1" +) + +func TestDefault(t *testing.T) { + defaulter := TracePipelineDefaulter{ + DefaultOTLPOutputProtocol: telemetryv1alpha1.OTLPProtocolGRPC, + } + + tests := []struct { + name string + input *telemetryv1alpha1.TracePipeline + expected *telemetryv1alpha1.TracePipeline + }{ + { + name: "should set default OTLP protocol if not set", + input: &telemetryv1alpha1.TracePipeline{ + Spec: telemetryv1alpha1.TracePipelineSpec{ + Output: telemetryv1alpha1.TracePipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{}, + }, + }, + }, + expected: &telemetryv1alpha1.TracePipeline{ + Spec: telemetryv1alpha1.TracePipelineSpec{ + Output: telemetryv1alpha1.TracePipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Protocol: telemetryv1alpha1.OTLPProtocolGRPC, + }, + }, + }, + }, + }, + { + name: "should not override existing OTLP protocol", + input: &telemetryv1alpha1.TracePipeline{ + Spec: telemetryv1alpha1.TracePipelineSpec{ + Output: telemetryv1alpha1.TracePipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Protocol: telemetryv1alpha1.OTLPProtocolHTTP, + }, + }, + }, + }, + expected: &telemetryv1alpha1.TracePipeline{ + Spec: telemetryv1alpha1.TracePipelineSpec{ + Output: telemetryv1alpha1.TracePipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Protocol: telemetryv1alpha1.OTLPProtocolHTTP, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := defaulter.Default(context.Background(), tt.input) + assert.NoError(t, err) + assert.Equal(t, tt.expected, tt.input) + }) + } +} diff --git a/webhook/tracepipeline/v1beta1/defaulter.go b/webhook/tracepipeline/v1beta1/defaulter.go new file mode 100644 index 000000000..a0d11bed4 --- /dev/null +++ b/webhook/tracepipeline/v1beta1/defaulter.go @@ -0,0 +1,44 @@ +package v1beta1 + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" +) + +// +kubebuilder:object:generate=false +var _ webhook.CustomDefaulter = &TracePipelineDefaulter{} + +type TracePipelineDefaulter struct { + DefaultOTLPOutputProtocol telemetryv1beta1.OTLPProtocol +} + +func SetupTracePipelineWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&telemetryv1beta1.TracePipeline{}). + WithDefaulter(&TracePipelineDefaulter{ + DefaultOTLPOutputProtocol: telemetryv1beta1.OTLPProtocolGRPC, + }). + Complete() +} + +func (td TracePipelineDefaulter) Default(ctx context.Context, obj runtime.Object) error { + pipeline, ok := obj.(*telemetryv1beta1.TracePipeline) + if !ok { + return fmt.Errorf("expected an TracePipeline object but got %T", obj) + } + + td.applyDefaults(pipeline) + + return nil +} + +func (td TracePipelineDefaulter) applyDefaults(pipeline *telemetryv1beta1.TracePipeline) { + if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { + pipeline.Spec.Output.OTLP.Protocol = td.DefaultOTLPOutputProtocol + } +} diff --git a/webhook/tracepipeline/v1beta1/defaulter_test.go b/webhook/tracepipeline/v1beta1/defaulter_test.go new file mode 100644 index 000000000..d93596607 --- /dev/null +++ b/webhook/tracepipeline/v1beta1/defaulter_test.go @@ -0,0 +1,71 @@ +package v1beta1 + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" +) + +func TestDefault(t *testing.T) { + defaulter := TracePipelineDefaulter{ + DefaultOTLPOutputProtocol: telemetryv1beta1.OTLPProtocolGRPC, + } + + tests := []struct { + name string + input *telemetryv1beta1.TracePipeline + expected *telemetryv1beta1.TracePipeline + }{ + { + name: "should set default OTLP protocol if not set", + input: &telemetryv1beta1.TracePipeline{ + Spec: telemetryv1beta1.TracePipelineSpec{ + Output: telemetryv1beta1.TracePipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{}, + }, + }, + }, + expected: &telemetryv1beta1.TracePipeline{ + Spec: telemetryv1beta1.TracePipelineSpec{ + Output: telemetryv1beta1.TracePipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Protocol: telemetryv1beta1.OTLPProtocolGRPC, + }, + }, + }, + }, + }, + { + name: "should not override existing OTLP protocol", + input: &telemetryv1beta1.TracePipeline{ + Spec: telemetryv1beta1.TracePipelineSpec{ + Output: telemetryv1beta1.TracePipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Protocol: telemetryv1beta1.OTLPProtocolHTTP, + }, + }, + }, + }, + expected: &telemetryv1beta1.TracePipeline{ + Spec: telemetryv1beta1.TracePipelineSpec{ + Output: telemetryv1beta1.TracePipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Protocol: telemetryv1beta1.OTLPProtocolHTTP, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := defaulter.Default(context.Background(), tt.input) + assert.NoError(t, err) + assert.Equal(t, tt.expected, tt.input) + }) + } +}