diff --git a/.testcoverage.yml b/.testcoverage.yml index dafbe05e93..3a6955a1ce 100644 --- a/.testcoverage.yml +++ b/.testcoverage.yml @@ -47,7 +47,7 @@ override: path: ^internal/validators/secretref$ - threshold: 75 path: ^internal/resourcelock$ - - threshold: 84 + - threshold: 83 path: ^internal/webhookcert$ - threshold: 74 path: ^webhook/logpipeline/v1alpha1$ diff --git a/apis/telemetry/v1alpha1/groupversion_info.go b/apis/telemetry/v1alpha1/groupversion_info.go index 2ad0488684..198f98b724 100644 --- a/apis/telemetry/v1alpha1/groupversion_info.go +++ b/apis/telemetry/v1alpha1/groupversion_info.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - // Package v1alpha1 contains API Schema definitions for the telemetry v1alpha1 API group // +kubebuilder:object:generate=true // +groupName=telemetry.kyma-project.io diff --git a/apis/telemetry/v1alpha1/logparser_types.go b/apis/telemetry/v1alpha1/logparser_types.go index a0b2e17e38..cb98a58a4a 100644 --- a/apis/telemetry/v1alpha1/logparser_types.go +++ b/apis/telemetry/v1alpha1/logparser_types.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - package v1alpha1 import ( diff --git a/apis/telemetry/v1alpha1/logpipeline_conversion.go b/apis/telemetry/v1alpha1/logpipeline_conversion.go index cbc22c8139..5b614db1a6 100644 --- a/apis/telemetry/v1alpha1/logpipeline_conversion.go +++ b/apis/telemetry/v1alpha1/logpipeline_conversion.go @@ -6,26 +6,47 @@ import ( "sigs.k8s.io/controller-runtime/pkg/conversion" telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" + "github.com/kyma-project/telemetry-manager/internal/namespaces" ) -var errSrcTypeUnsupported = errors.New("source type is not LogPipeline v1alpha1") -var errDstTypeUnsupported = errors.New("destination type is not LogPipeline v1beta1") +// Converts between v1alpha1 and v1beta1 LogPipeline CRDs +// Major API changes which require specific conversion logic are: +// - input.application (v1alpha1) is renamed to input.runtime (v1beta1). +// - NamespaceSelector in input.runtime (v1beta1) is using the shared selector of input.otlp which lead to not having a 'System' boolean field anymore. +// - output.http in v1beta1 is using the shared TLS section of the output.otlp, leading to a rename of 'Disabled' field to 'Insecure' and 'SkipCertificateValidation' to 'InsecureSkipVerify'. +// - input.runtime namespaces and containers are now pointers in v1beta1, requiring nil checks during conversion. +// Additionally, changes were done in shared types which are documented in the related file. -// ConvertTo converts this LogPipeline to the Hub version (v1beta1). +var errSrcTypeUnsupportedLogPipeline = errors.New("source type is not LogPipeline v1alpha1") +var errDstTypeUnsupportedLogPipeline = errors.New("destination type is not LogPipeline v1beta1") + +// ConvertTo converts this LogPipeline to the Hub version (v1alpha1 -> v1beta1). func (lp *LogPipeline) ConvertTo(dstRaw conversion.Hub) error { src := lp dst, ok := dstRaw.(*telemetryv1beta1.LogPipeline) if !ok { - return errDstTypeUnsupported + return errDstTypeUnsupportedLogPipeline } + // Copy metadata dst.ObjectMeta = src.ObjectMeta + // Copy Input fields dst.Spec.Input = telemetryv1beta1.LogPipelineInput{} - dst.Spec.Input.Runtime = v1Alpha1ApplicationToV1Beta1(src.Spec.Input.Application) - dst.Spec.Input.OTLP = v1Alpha1OTLPInputToV1Beta1(src.Spec.Input.OTLP) + dst.Spec.Input.Runtime = convertApplicationToBeta(src.Spec.Input.Application) + dst.Spec.Input.OTLP = convertOTLPInputToBeta(src.Spec.Input.OTLP) + + // Copy Output fields + dst.Spec.Output = telemetryv1beta1.LogPipelineOutput{} + dst.Spec.Output.HTTP = convertHTTPOutputToBeta(src.Spec.Output.HTTP) + dst.Spec.Output.OTLP = convertOTLPOutputToBeta(src.Spec.Output.OTLP) + if src.Spec.Output.Custom != "" { + dst.Spec.Output.Custom = src.Spec.Output.Custom + } + + // Copy everything else for _, f := range src.Spec.Files { dst.Spec.Files = append(dst.Spec.Files, telemetryv1beta1.LogPipelineFileMount(f)) } @@ -34,52 +55,15 @@ func (lp *LogPipeline) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.FluentBitFilters = append(dst.Spec.FluentBitFilters, telemetryv1beta1.LogPipelineFilter(f)) } - if srcHTTPOutput := src.Spec.Output.HTTP; srcHTTPOutput != nil { - dst.Spec.Output.HTTP = &telemetryv1beta1.LogPipelineHTTPOutput{ - Host: v1Alpha1ValueTypeToV1Beta1(srcHTTPOutput.Host), - URI: srcHTTPOutput.URI, - Port: srcHTTPOutput.Port, - Compress: srcHTTPOutput.Compress, - Format: srcHTTPOutput.Format, - TLSConfig: v1Alpha1TLSToV1Beta1(srcHTTPOutput.TLS), - Dedot: srcHTTPOutput.Dedot, - } - - if srcHTTPOutput.User != nil && (srcHTTPOutput.User.Value != "" || srcHTTPOutput.User.ValueFrom != nil) { - user := v1Alpha1ValueTypeToV1Beta1(*srcHTTPOutput.User) - dst.Spec.Output.HTTP.User = &user - } - - if srcHTTPOutput.Password != nil && (srcHTTPOutput.Password.Value != "" || srcHTTPOutput.Password.ValueFrom != nil) { - password := v1Alpha1ValueTypeToV1Beta1(*srcHTTPOutput.Password) - dst.Spec.Output.HTTP.Password = &password - } - } - - if srcOTLPOutput := src.Spec.Output.OTLP; srcOTLPOutput != nil { - dst.Spec.Output.OTLP = &telemetryv1beta1.OTLPOutput{ - Protocol: telemetryv1beta1.OTLPProtocol(srcOTLPOutput.Protocol), - Endpoint: v1Alpha1ValueTypeToV1Beta1(srcOTLPOutput.Endpoint), - Path: srcOTLPOutput.Path, - Authentication: v1Alpha1AuthenticationToV1Beta1(srcOTLPOutput.Authentication), - Headers: v1Alpha1HeadersToV1Beta1(srcOTLPOutput.Headers), - TLS: v1Alpha1OTLPTLSToV1Beta1(srcOTLPOutput.TLS), - } - } - - if srcCustomOutput := src.Spec.Output.Custom; srcCustomOutput != "" { - dst.Spec.Output.Custom = srcCustomOutput - } - if src.Spec.Transforms != nil { for _, t := range src.Spec.Transforms { - dst.Spec.Transforms = append(dst.Spec.Transforms, v1Alpha1TransformSpecToV1Beta1(t)) + dst.Spec.Transforms = append(dst.Spec.Transforms, convertTransformSpecToBeta(t)) } } if src.Spec.Filters != nil { for _, t := range src.Spec.Filters { - dst.Spec.Filters = append(dst.Spec.Filters, v1Alpha1FilterSpecToV1Beta1(t)) + dst.Spec.Filters = append(dst.Spec.Filters, convertFilterSpecToBeta(t)) } } @@ -88,184 +72,108 @@ func (lp *LogPipeline) ConvertTo(dstRaw conversion.Hub) error { return nil } -func v1Alpha1OTLPInputToV1Beta1(otlp *OTLPInput) *telemetryv1beta1.OTLPInput { - if otlp == nil { +func convertHTTPOutputToBeta(output *LogPipelineHTTPOutput) *telemetryv1beta1.LogPipelineHTTPOutput { + if output == nil { return nil } - input := &telemetryv1beta1.OTLPInput{ - Disabled: otlp.Disabled, + result := &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: convertValueTypeToBeta(output.Host), + URI: output.URI, + Port: output.Port, + Compress: output.Compress, + Format: output.Format, + TLSConfig: convertOutputTLSToBeta(output.TLS), + Dedot: output.Dedot, } - if otlp.Namespaces != nil { - input.Namespaces = &telemetryv1beta1.NamespaceSelector{ - Include: otlp.Namespaces.Include, - Exclude: otlp.Namespaces.Exclude, - } + + if output.User != nil && (output.User.Value != "" || output.User.ValueFrom != nil) { + user := convertValueTypeToBeta(*output.User) + result.User = &user + } + + if output.Password != nil && (output.Password.Value != "" || output.Password.ValueFrom != nil) { + password := convertValueTypeToBeta(*output.Password) + result.Password = &password } - return input + return result } -func v1Alpha1ApplicationToV1Beta1(application *LogPipelineApplicationInput) *telemetryv1beta1.LogPipelineRuntimeInput { +func convertApplicationToBeta(application *LogPipelineApplicationInput) *telemetryv1beta1.LogPipelineRuntimeInput { if application == nil { return nil } runtime := &telemetryv1beta1.LogPipelineRuntimeInput{ - Enabled: application.Enabled, - Namespaces: telemetryv1beta1.LogPipelineNamespaceSelector{ - Include: application.Namespaces.Include, - Exclude: application.Namespaces.Exclude, - System: application.Namespaces.System, - }, - Containers: telemetryv1beta1.LogPipelineContainerSelector{ - Include: application.Containers.Include, - Exclude: application.Containers.Exclude, - }, + Enabled: application.Enabled, KeepAnnotations: application.KeepAnnotations, DropLabels: application.DropLabels, KeepOriginalBody: application.KeepOriginalBody, } - return runtime -} - -func v1Alpha1OTLPTLSToV1Beta1(tls *OTLPTLS) *telemetryv1beta1.OutputTLS { - if tls == nil { - return nil - } - - betaTLS := &telemetryv1beta1.OutputTLS{ - Disabled: tls.Insecure, - SkipCertificateValidation: tls.InsecureSkipVerify, + var excludes []string + if len(application.Namespaces.Include) == 0 && len(application.Namespaces.Exclude) == 0 && !application.Namespaces.System { + excludes = namespaces.System() + } else { + excludes = application.Namespaces.Exclude } - if tls.CA != nil { - ca := v1Alpha1ValueTypeToV1Beta1(*tls.CA) - betaTLS.CA = &ca + runtime.Namespaces = &telemetryv1beta1.NamespaceSelector{ + Include: sanitizeNamespaceNames(application.Namespaces.Include), + Exclude: sanitizeNamespaceNames(excludes), } - if tls.Key != nil { - key := v1Alpha1ValueTypeToV1Beta1(*tls.Key) - betaTLS.Key = &key + if len(application.Containers.Include) > 0 || len(application.Containers.Exclude) > 0 { + runtime.Containers = + &telemetryv1beta1.LogPipelineContainerSelector{ + Include: append([]string{}, application.Containers.Include...), + Exclude: append([]string{}, application.Containers.Exclude...), + } } - if tls.Cert != nil { - cert := v1Alpha1ValueTypeToV1Beta1(*tls.Cert) - betaTLS.Cert = &cert - } - - return betaTLS -} - -func v1Alpha1HeadersToV1Beta1(headers []Header) []telemetryv1beta1.Header { - var dst []telemetryv1beta1.Header - for _, h := range headers { - dst = append(dst, v1Alpha1HeaderToV1Beta1(h)) - } - - return dst -} - -func v1Alpha1HeaderToV1Beta1(h Header) telemetryv1beta1.Header { - return telemetryv1beta1.Header{ - Name: h.Name, - ValueType: v1Alpha1ValueTypeToV1Beta1(h.ValueType), - Prefix: h.Prefix, - } -} - -func v1Alpha1AuthenticationToV1Beta1(authentication *AuthenticationOptions) *telemetryv1beta1.AuthenticationOptions { - if authentication == nil { - return nil - } - - return &telemetryv1beta1.AuthenticationOptions{ - Basic: v1Alpha1BasicAuthOptionsToV1Beta1(authentication.Basic), - } -} - -func v1Alpha1BasicAuthOptionsToV1Beta1(basic *BasicAuthOptions) *telemetryv1beta1.BasicAuthOptions { - if basic == nil { - return nil - } - - return &telemetryv1beta1.BasicAuthOptions{ - User: v1Alpha1ValueTypeToV1Beta1(basic.User), - Password: v1Alpha1ValueTypeToV1Beta1(basic.Password), - } -} - -func v1Alpha1ValueTypeToV1Beta1(src ValueType) telemetryv1beta1.ValueType { - if src.ValueFrom != nil && src.ValueFrom.SecretKeyRef != nil { - return telemetryv1beta1.ValueType{ - ValueFrom: &telemetryv1beta1.ValueFromSource{ - SecretKeyRef: (*telemetryv1beta1.SecretKeyRef)(src.ValueFrom.SecretKeyRef), - }, - } - } - - return telemetryv1beta1.ValueType{ - Value: src.Value, - } + return runtime } -func v1Alpha1TLSToV1Beta1(src LogPipelineOutputTLS) telemetryv1beta1.OutputTLS { +func convertOutputTLSToBeta(src LogPipelineOutputTLS) telemetryv1beta1.OutputTLS { var dst telemetryv1beta1.OutputTLS - if src.CA != nil { - ca := v1Alpha1ValueTypeToV1Beta1(*src.CA) - dst.CA = &ca - } - - if src.Cert != nil { - cert := v1Alpha1ValueTypeToV1Beta1(*src.Cert) - dst.Cert = &cert - } - - if src.Key != nil { - key := v1Alpha1ValueTypeToV1Beta1(*src.Key) - dst.Key = &key - } - - dst.Disabled = src.Disabled - dst.SkipCertificateValidation = src.SkipCertificateValidation - - return dst -} - -func v1Alpha1TransformSpecToV1Beta1(src TransformSpec) telemetryv1beta1.TransformSpec { - var dst telemetryv1beta1.TransformSpec - - dst.Conditions = append(dst.Conditions, src.Conditions...) - - dst.Statements = append(dst.Statements, src.Statements...) + dst.CA = convertValueTypeToBetaPtr(src.CA) + dst.Cert = convertValueTypeToBetaPtr(src.Cert) + dst.Key = convertValueTypeToBetaPtr(src.Key) + dst.Insecure = src.Disabled + dst.InsecureSkipVerify = src.SkipCertificateValidation return dst } -func v1Alpha1FilterSpecToV1Beta1(src FilterSpec) telemetryv1beta1.FilterSpec { - var dst telemetryv1beta1.FilterSpec - - dst.Conditions = append(dst.Conditions, src.Conditions...) - - return dst -} - -// ConvertFrom converts from the Hub version (v1beta1) to this version. +// ConvertFrom converts from the Hub version (v1beta1 -> v1alpha1) to this version. func (lp *LogPipeline) ConvertFrom(srcRaw conversion.Hub) error { dst := lp src, ok := srcRaw.(*telemetryv1beta1.LogPipeline) if !ok { - return errSrcTypeUnsupported + return errSrcTypeUnsupportedLogPipeline } + // Copy metadata dst.ObjectMeta = src.ObjectMeta - dst.Spec.Input.Application = v1Beta1RuntimeToV1Alpha1(src.Spec.Input.Runtime) - dst.Spec.Input.OTLP = v1Beta1OTLPInputToV1Alpha1(src.Spec.Input.OTLP) + // Copy input fields + dst.Spec.Input = LogPipelineInput{} + dst.Spec.Input.Application = convertRuntimeToAlpha(src.Spec.Input.Runtime) + dst.Spec.Input.OTLP = convertOTLPInputToAlpha(src.Spec.Input.OTLP) + + // Copy output fields + dst.Spec.Output = LogPipelineOutput{} + dst.Spec.Output.HTTP = convertHTTPOutputToAlpha(src.Spec.Output.HTTP) + + dst.Spec.Output.OTLP = convertOTLPOutputToAlpha(src.Spec.Output.OTLP) + if src.Spec.Output.Custom != "" { + dst.Spec.Output.Custom = src.Spec.Output.Custom + } + // Copy everything else for _, f := range src.Spec.Files { dst.Spec.Files = append(dst.Spec.Files, LogPipelineFileMount(f)) } @@ -274,52 +182,15 @@ func (lp *LogPipeline) ConvertFrom(srcRaw conversion.Hub) error { dst.Spec.FluentBitFilters = append(dst.Spec.FluentBitFilters, LogPipelineFilter(f)) } - if srcHTTPOutput := src.Spec.Output.HTTP; srcHTTPOutput != nil { - dst.Spec.Output.HTTP = &LogPipelineHTTPOutput{ - Host: v1Beta1ValueTypeToV1Alpha1(srcHTTPOutput.Host), - URI: srcHTTPOutput.URI, - Port: srcHTTPOutput.Port, - Compress: srcHTTPOutput.Compress, - Format: srcHTTPOutput.Format, - TLS: v1Beta1TLSToV1Alpha1(srcHTTPOutput.TLSConfig), - Dedot: srcHTTPOutput.Dedot, - } - - if srcHTTPOutput.User != nil { - user := v1Beta1ValueTypeToV1Alpha1(*srcHTTPOutput.User) - dst.Spec.Output.HTTP.User = &user - } - - if srcHTTPOutput.Password != nil { - password := v1Beta1ValueTypeToV1Alpha1(*srcHTTPOutput.Password) - dst.Spec.Output.HTTP.Password = &password - } - } - - if srcOTLPOutput := src.Spec.Output.OTLP; srcOTLPOutput != nil { - dst.Spec.Output.OTLP = &OTLPOutput{ - Protocol: (string)(srcOTLPOutput.Protocol), - Endpoint: v1Beta1ValueTypeToV1Alpha1(srcOTLPOutput.Endpoint), - Path: srcOTLPOutput.Path, - Authentication: v1Beta1AuthenticationToV1Alpha1(srcOTLPOutput.Authentication), - Headers: v1Beta1HeadersToV1Alpha1(srcOTLPOutput.Headers), - TLS: v1Beta1OTLPTLSToV1Alpha1(srcOTLPOutput.TLS), - } - } - - if srcCustomOutput := src.Spec.Output.Custom; srcCustomOutput != "" { - dst.Spec.Output.Custom = srcCustomOutput - } - if src.Spec.Transforms != nil { for _, t := range src.Spec.Transforms { - dst.Spec.Transforms = append(dst.Spec.Transforms, v1Beta1TransformSpecToV1Alpha1(t)) + dst.Spec.Transforms = append(dst.Spec.Transforms, convertTransformSpecToAlpha(t)) } } if src.Spec.Filters != nil { for _, t := range src.Spec.Filters { - dst.Spec.Filters = append(dst.Spec.Filters, v1Beta1FilterSpecToV1Alpha1(t)) + dst.Spec.Filters = append(dst.Spec.Filters, convertFilterSpecToAlpha(t)) } } @@ -328,166 +199,73 @@ func (lp *LogPipeline) ConvertFrom(srcRaw conversion.Hub) error { return nil } -func v1Beta1RuntimeToV1Alpha1(runtime *telemetryv1beta1.LogPipelineRuntimeInput) *LogPipelineApplicationInput { - if runtime == nil { - return nil - } - - application := &LogPipelineApplicationInput{ - Enabled: runtime.Enabled, - Namespaces: LogPipelineNamespaceSelector{ - Include: runtime.Namespaces.Include, - Exclude: runtime.Namespaces.Exclude, - System: runtime.Namespaces.System, - }, - Containers: LogPipelineContainerSelector{ - Include: runtime.Containers.Include, - Exclude: runtime.Containers.Exclude, - }, - KeepAnnotations: runtime.KeepAnnotations, - DropLabels: runtime.DropLabels, - KeepOriginalBody: runtime.KeepOriginalBody, - } - - return application -} - -func v1Beta1OTLPInputToV1Alpha1(otlp *telemetryv1beta1.OTLPInput) *OTLPInput { - if otlp == nil { +func convertHTTPOutputToAlpha(output *telemetryv1beta1.LogPipelineHTTPOutput) *LogPipelineHTTPOutput { + if output == nil { return nil } - input := &OTLPInput{ - Disabled: otlp.Disabled, - } - if otlp.Namespaces != nil { - input.Namespaces = &NamespaceSelector{ - Include: otlp.Namespaces.Include, - Exclude: otlp.Namespaces.Exclude, - } + result := &LogPipelineHTTPOutput{ + Host: convertValueTypeToAlpha(output.Host), + URI: output.URI, + Port: output.Port, + Compress: output.Compress, + Format: output.Format, + TLS: convertOutputTLSToAlpha(output.TLSConfig), + Dedot: output.Dedot, } - return input -} - -func v1Beta1OTLPTLSToV1Alpha1(tls *telemetryv1beta1.OutputTLS) *OTLPTLS { - if tls == nil { - return nil - } - - alphaTLS := &OTLPTLS{ - Insecure: tls.Disabled, - InsecureSkipVerify: tls.SkipCertificateValidation, - } - - if tls.CA != nil { - ca := v1Beta1ValueTypeToV1Alpha1(*tls.CA) - alphaTLS.CA = &ca + if output.User != nil && (output.User.Value != "" || output.User.ValueFrom != nil) { + user := convertValueTypeToAlpha(*output.User) + result.User = &user } - if tls.Key != nil { - key := v1Beta1ValueTypeToV1Alpha1(*tls.Key) - alphaTLS.Key = &key + if output.Password != nil && (output.Password.Value != "" || output.Password.ValueFrom != nil) { + password := convertValueTypeToAlpha(*output.Password) + result.Password = &password } - if tls.Cert != nil { - cert := v1Beta1ValueTypeToV1Alpha1(*tls.Cert) - alphaTLS.Cert = &cert - } - - return alphaTLS + return result } -func v1Beta1HeadersToV1Alpha1(headers []telemetryv1beta1.Header) []Header { - var dst []Header - for _, h := range headers { - dst = append(dst, v1Beta1HeaderToV1Alpha1(h)) - } - - return dst -} - -func v1Beta1HeaderToV1Alpha1(h telemetryv1beta1.Header) Header { - return Header{ - Name: h.Name, - ValueType: v1Beta1ValueTypeToV1Alpha1(h.ValueType), - Prefix: h.Prefix, - } -} - -func v1Beta1AuthenticationToV1Alpha1(authentication *telemetryv1beta1.AuthenticationOptions) *AuthenticationOptions { - if authentication == nil { - return nil - } - - return &AuthenticationOptions{ - Basic: v1Beta1BasicAuthOptionsToV1Alpha1(authentication.Basic), - } -} - -func v1Beta1BasicAuthOptionsToV1Alpha1(basic *telemetryv1beta1.BasicAuthOptions) *BasicAuthOptions { - if basic == nil { +func convertRuntimeToAlpha(runtime *telemetryv1beta1.LogPipelineRuntimeInput) *LogPipelineApplicationInput { + if runtime == nil { return nil } - return &BasicAuthOptions{ - User: v1Beta1ValueTypeToV1Alpha1(basic.User), - Password: v1Beta1ValueTypeToV1Alpha1(basic.Password), - } -} - -func v1Beta1TLSToV1Alpha1(src telemetryv1beta1.OutputTLS) LogPipelineOutputTLS { - var dst LogPipelineOutputTLS - - if src.CA != nil { - ca := v1Beta1ValueTypeToV1Alpha1(*src.CA) - dst.CA = &ca - } - - if src.Cert != nil { - cert := v1Beta1ValueTypeToV1Alpha1(*src.Cert) - dst.Cert = &cert + application := &LogPipelineApplicationInput{ + Enabled: runtime.Enabled, + KeepAnnotations: runtime.KeepAnnotations, + DropLabels: runtime.DropLabels, + KeepOriginalBody: runtime.KeepOriginalBody, } - if src.Key != nil { - key := v1Beta1ValueTypeToV1Alpha1(*src.Key) - dst.Key = &key + if runtime.Namespaces != nil && (len(runtime.Namespaces.Include) > 0 || len(runtime.Namespaces.Exclude) > 0) { + application.Namespaces = LogPipelineNamespaceSelector{ + Include: append([]string{}, runtime.Namespaces.Include...), + Exclude: append([]string{}, runtime.Namespaces.Exclude...), + System: false, + } } - dst.Disabled = src.Disabled - dst.SkipCertificateValidation = src.SkipCertificateValidation - - return dst -} - -func v1Beta1ValueTypeToV1Alpha1(src telemetryv1beta1.ValueType) ValueType { - if src.ValueFrom != nil && src.ValueFrom.SecretKeyRef != nil { - return ValueType{ - ValueFrom: &ValueFromSource{ - SecretKeyRef: (*SecretKeyRef)(src.ValueFrom.SecretKeyRef), - }, + if runtime.Containers != nil && (len(runtime.Containers.Include) > 0 || len(runtime.Containers.Exclude) > 0) { + application.Containers = LogPipelineContainerSelector{ + Include: append([]string{}, runtime.Containers.Include...), + Exclude: append([]string{}, runtime.Containers.Exclude...), } } - return ValueType{ - Value: src.Value, - } + return application } -func v1Beta1TransformSpecToV1Alpha1(src telemetryv1beta1.TransformSpec) TransformSpec { - var dst TransformSpec - - dst.Conditions = append(dst.Conditions, src.Conditions...) - - dst.Statements = append(dst.Statements, src.Statements...) - - return dst -} +func convertOutputTLSToAlpha(src telemetryv1beta1.OutputTLS) LogPipelineOutputTLS { + var dst LogPipelineOutputTLS -func v1Beta1FilterSpecToV1Alpha1(src telemetryv1beta1.FilterSpec) FilterSpec { - var dst FilterSpec + dst.CA = convertValueTypeToAlphaPtr(src.CA) + dst.Cert = convertValueTypeToAlphaPtr(src.Cert) + dst.Key = convertValueTypeToAlphaPtr(src.Key) - dst.Conditions = append(dst.Conditions, src.Conditions...) + dst.Disabled = src.Insecure + dst.SkipCertificateValidation = src.InsecureSkipVerify return dst } diff --git a/apis/telemetry/v1alpha1/logpipeline_conversion_test.go b/apis/telemetry/v1alpha1/logpipeline_conversion_test.go index 2c963626fd..4d1c07cb80 100644 --- a/apis/telemetry/v1alpha1/logpipeline_conversion_test.go +++ b/apis/telemetry/v1alpha1/logpipeline_conversion_test.go @@ -3,403 +3,511 @@ package v1alpha1 import ( "testing" - "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" + "github.com/kyma-project/telemetry-manager/internal/namespaces" ) -func TestConvertTo(t *testing.T) { - src := &LogPipeline{ - ObjectMeta: metav1.ObjectMeta{ - Name: "log-pipeline-test", - }, - Spec: LogPipelineSpec{ - Input: LogPipelineInput{ - Application: &LogPipelineApplicationInput{ - Enabled: ptr.To(true), - Namespaces: LogPipelineNamespaceSelector{ - Include: []string{"default", "kube-system"}, - Exclude: []string{"kube-public"}, - System: true, - }, - Containers: LogPipelineContainerSelector{ - Include: []string{"nginx", "app"}, - Exclude: []string{"sidecar"}, - }, - KeepAnnotations: ptr.To(true), - DropLabels: ptr.To(true), - KeepOriginalBody: ptr.To(true), - }, - OTLP: &OTLPInput{ - Disabled: true, - Namespaces: &NamespaceSelector{ - Include: []string{"include", "include2"}, - Exclude: []string{"exclude", "exclude2"}, - }, +var v1alpha1LogPipeline = &LogPipeline{ + ObjectMeta: metav1.ObjectMeta{ + Name: "log-pipeline-test", + }, + Spec: LogPipelineSpec{ + Input: LogPipelineInput{ + Application: &LogPipelineApplicationInput{ + Enabled: ptr.To(true), + Namespaces: LogPipelineNamespaceSelector{ + Include: []string{"default", "kube-system"}, + Exclude: []string{"kube-public"}, + System: false, + }, + Containers: LogPipelineContainerSelector{ + Include: []string{"nginx", "app"}, + Exclude: []string{"sidecar"}, }, + KeepAnnotations: ptr.To(true), + DropLabels: ptr.To(true), + KeepOriginalBody: ptr.To(true), }, - Files: []LogPipelineFileMount{ - {Name: "file1", Content: "file1-content"}, + OTLP: &OTLPInput{ + Disabled: true, + Namespaces: &NamespaceSelector{ + Include: []string{"include", "include2"}, + Exclude: []string{"exclude", "exclude2"}, + }, }, - FluentBitFilters: []LogPipelineFilter{ - {Custom: "name stdout"}, + }, + Files: []LogPipelineFileMount{ + {Name: "file1", Content: "file1-content"}, + }, + FluentBitFilters: []LogPipelineFilter{ + {Custom: "name stdout"}, + }, + Transforms: []TransformSpec{ + { + Conditions: []string{"resource.attributes[\"k8s.pod.name\"] == nil"}, + Statements: []string{"set(resource.attributes[\"k8s.pod.name\"]", "nginx"}, }, - Transforms: []TransformSpec{ - { - Conditions: []string{"resource.attributes[\"k8s.pod.name\"] == nil"}, - Statements: []string{"set(resource.attributes[\"k8s.pod.name\"]", "nginx"}, - }, + }, + Filters: []FilterSpec{ + { + Conditions: []string{"log.time == nil"}, }, - Filters: []FilterSpec{ - { - Conditions: []string{"log.time == nil"}, + }, + Output: LogPipelineOutput{ + Custom: "custom-output", + HTTP: &LogPipelineHTTPOutput{ + Host: ValueType{ + Value: "http://localhost", }, - }, - Output: LogPipelineOutput{ - Custom: "custom-output", - HTTP: &LogPipelineHTTPOutput{ - Host: ValueType{ - Value: "http://localhost", + User: &ValueType{ + Value: "user", + }, + Password: &ValueType{ + ValueFrom: &ValueFromSource{ + SecretKeyRef: &SecretKeyRef{ + Name: "secret-name", + Namespace: "secret-namespace", + Key: "secret-key", + }, }, - User: &ValueType{ - Value: "user", + }, + URI: "/ingest/v1beta1/logs", + Port: "8080", + Compress: "on", + Format: "json", + TLS: LogPipelineOutputTLS{ + Disabled: true, + SkipCertificateValidation: true, + CA: &ValueType{ + Value: "ca", }, - Password: &ValueType{ - ValueFrom: &ValueFromSource{ - SecretKeyRef: &SecretKeyRef{ - Name: "secret-name", - Namespace: "secret-namespace", - Key: "secret-key", - }, - }, + Cert: &ValueType{ + Value: "cert", }, - URI: "/ingest/v1beta1/logs", - Port: "8080", - Compress: "on", - Format: "json", - TLS: LogPipelineOutputTLS{ - SkipCertificateValidation: true, - CA: &ValueType{ - Value: "ca", - }, - Cert: &ValueType{ - Value: "cert", + Key: &ValueType{ + Value: "key", + }, + }, + Dedot: true, + }, + OTLP: &OTLPOutput{ + Protocol: OTLPProtocolGRPC, + Endpoint: ValueType{ + Value: "localhost:4317", + }, + Path: "/v1/logs", + Authentication: &AuthenticationOptions{ + Basic: &BasicAuthOptions{ + User: ValueType{ + Value: "user", }, - Key: &ValueType{ - Value: "key", + Password: ValueType{ + Value: "password", }, }, - Dedot: true, }, - OTLP: &OTLPOutput{ - Protocol: OTLPProtocolGRPC, - Endpoint: ValueType{ - Value: "localhost:4317", - }, - Path: "/v1/logs", - Authentication: &AuthenticationOptions{ - Basic: &BasicAuthOptions{ - User: ValueType{ - Value: "user", - }, - Password: ValueType{ - Value: "password", - }, + Headers: []Header{ + { + Name: "header1", + ValueType: ValueType{ + Value: "value1", }, + Prefix: "prefix1", }, - Headers: []Header{ - { - Name: "header1", - ValueType: ValueType{ - Value: "value1", - }, - Prefix: "prefix1", - }, - { - Name: "header2", - ValueType: ValueType{ - Value: "value2", - }, - Prefix: "prefix2", + { + Name: "header2", + ValueType: ValueType{ + Value: "value2", }, + Prefix: "prefix2", }, - TLS: &OTLPTLS{ - Insecure: true, - InsecureSkipVerify: true, - CA: &ValueType{ - Value: "ca", - }, - Cert: &ValueType{ - Value: "cert", - }, - Key: &ValueType{ - Value: "key", - }, + }, + TLS: &OTLPTLS{ + Insecure: true, + InsecureSkipVerify: true, + CA: &ValueType{ + Value: "ca", + }, + Cert: &ValueType{ + Value: "cert", + }, + Key: &ValueType{ + Value: "key", }, }, }, }, - Status: LogPipelineStatus{ - Conditions: []metav1.Condition{ - { - Type: "LogAgentHealthy", - Status: "True", - Reason: "FluentBitReady", - Message: "FluentBit is and collecting logs", - }, + }, + Status: LogPipelineStatus{ + Conditions: []metav1.Condition{ + { + Type: "LogAgentHealthy", + Status: "True", + Reason: "FluentBitReady", + Message: "FluentBit is and collecting logs", }, - UnsupportedMode: ptr.To(true), }, - } - - dst := &telemetryv1beta1.LogPipeline{} - - err := src.ConvertTo(dst) - require.NoError(t, err) - - requireLogPipelinesEquivalent(t, src, dst) - - srcAfterRoundTrip := &LogPipeline{} - err = srcAfterRoundTrip.ConvertFrom(dst) - require.NoError(t, err) - require.Empty(t, cmp.Diff(src, srcAfterRoundTrip), "expected source be equal to itself after round-trip") + UnsupportedMode: ptr.To(true), + }, } -func TestConvertFrom(t *testing.T) { - src := &telemetryv1beta1.LogPipeline{ - ObjectMeta: metav1.ObjectMeta{ - Name: "log-pipeline-test", - }, - Spec: telemetryv1beta1.LogPipelineSpec{ - Input: telemetryv1beta1.LogPipelineInput{ - Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ - Enabled: ptr.To(true), - Namespaces: telemetryv1beta1.LogPipelineNamespaceSelector{ - Include: []string{"default", "kube-system"}, - Exclude: []string{"kube-public"}, - System: true, - }, - Containers: telemetryv1beta1.LogPipelineContainerSelector{ - Include: []string{"nginx", "app"}, - Exclude: []string{"sidecar"}, - }, - KeepAnnotations: ptr.To(true), - DropLabels: ptr.To(true), - KeepOriginalBody: ptr.To(true), - }, - OTLP: &telemetryv1beta1.OTLPInput{ - Disabled: true, - Namespaces: &telemetryv1beta1.NamespaceSelector{ - Include: []string{"include", "include2"}, - Exclude: []string{"exclude", "exclude2"}, - }, +var v1beta1LogPipeline = &telemetryv1beta1.LogPipeline{ + ObjectMeta: metav1.ObjectMeta{ + Name: "log-pipeline-test", + }, + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Enabled: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"default", "kube-system"}, + Exclude: []string{"kube-public"}, + }, + Containers: &telemetryv1beta1.LogPipelineContainerSelector{ + Include: []string{"nginx", "app"}, + Exclude: []string{"sidecar"}, }, + KeepAnnotations: ptr.To(true), + DropLabels: ptr.To(true), + KeepOriginalBody: ptr.To(true), }, - Files: []telemetryv1beta1.LogPipelineFileMount{ - {Name: "file1", Content: "file1-content"}, + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"include", "include2"}, + Exclude: []string{"exclude", "exclude2"}, + }, }, - FluentBitFilters: []telemetryv1beta1.LogPipelineFilter{ - {Custom: "name stdout"}, + }, + Files: []telemetryv1beta1.LogPipelineFileMount{ + {Name: "file1", Content: "file1-content"}, + }, + FluentBitFilters: []telemetryv1beta1.LogPipelineFilter{ + {Custom: "name stdout"}, + }, + Transforms: []telemetryv1beta1.TransformSpec{ + { + Conditions: []string{"resource.attributes[\"k8s.pod.name\"] == nil"}, + Statements: []string{"set(resource.attributes[\"k8s.pod.name\"]", "nginx"}, }, - Transforms: []telemetryv1beta1.TransformSpec{ - { - Conditions: []string{"resource.attributes[\"k8s.pod.name\"] == nil"}, - Statements: []string{"set(resource.attributes[\"k8s.pod.name\"]", "nginx"}, - }, + }, + Filters: []telemetryv1beta1.FilterSpec{ + { + Conditions: []string{"log.time == nil"}, }, - Filters: []telemetryv1beta1.FilterSpec{ - { - Conditions: []string{"log.time == nil"}, + }, + Output: telemetryv1beta1.LogPipelineOutput{ + Custom: "custom-output", + HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: telemetryv1beta1.ValueType{ + Value: "http://localhost", }, - }, - Output: telemetryv1beta1.LogPipelineOutput{ - Custom: "custom-output", - HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ - Host: telemetryv1beta1.ValueType{ - Value: "http://localhost", + User: &telemetryv1beta1.ValueType{ + Value: "user", + }, + Password: &telemetryv1beta1.ValueType{ + ValueFrom: &telemetryv1beta1.ValueFromSource{ + SecretKeyRef: &telemetryv1beta1.SecretKeyRef{ + Name: "secret-name", + Namespace: "secret-namespace", + Key: "secret-key", + }, }, - User: &telemetryv1beta1.ValueType{ + }, + URI: "/ingest/v1beta1/logs", + Port: "8080", + Compress: "on", + Format: "json", + TLSConfig: telemetryv1beta1.OutputTLS{ + Insecure: true, + InsecureSkipVerify: true, + CA: &telemetryv1beta1.ValueType{ + Value: "ca", + }, + Cert: &telemetryv1beta1.ValueType{ + Value: "cert", + }, + Key: &telemetryv1beta1.ValueType{ + Value: "key", + }, + }, + Dedot: true, + }, + OTLP: &telemetryv1beta1.OTLPOutput{ + Protocol: telemetryv1beta1.OTLPProtocolGRPC, + Endpoint: telemetryv1beta1.ValueType{Value: "localhost:4317"}, + Path: "/v1/logs", + Authentication: &telemetryv1beta1.AuthenticationOptions{Basic: &telemetryv1beta1.BasicAuthOptions{ + User: telemetryv1beta1.ValueType{ Value: "user", }, - Password: &telemetryv1beta1.ValueType{ - ValueFrom: &telemetryv1beta1.ValueFromSource{ - SecretKeyRef: &telemetryv1beta1.SecretKeyRef{ - Name: "secret-name", - Namespace: "secret-namespace", - Key: "secret-key", + Password: telemetryv1beta1.ValueType{ + Value: "password", + }, + }}, + Headers: []telemetryv1beta1.Header{ + { + Name: "header1", + ValueType: telemetryv1beta1.ValueType{ + Value: "value1", + }, + Prefix: "prefix1", + }, + { + Name: "header2", + ValueType: telemetryv1beta1.ValueType{ + Value: "value2", + }, + Prefix: "prefix2", + }, + }, + TLS: &telemetryv1beta1.OutputTLS{ + Insecure: true, + InsecureSkipVerify: true, + CA: &telemetryv1beta1.ValueType{Value: "ca"}, + Cert: &telemetryv1beta1.ValueType{Value: "cert"}, + Key: &telemetryv1beta1.ValueType{Value: "key"}, + }, + }, + }, + }, + Status: telemetryv1beta1.LogPipelineStatus{ + Conditions: []metav1.Condition{ + { + Type: "LogAgentHealthy", + Status: "True", + Reason: "FluentBitReady", + Message: "FluentBit is and collecting logs", + }, + }, + UnsupportedMode: ptr.To(true), + }, +} + +func TestLogPipelineConvertTo(t *testing.T) { + tests := []struct { + name string + input *LogPipeline + expected *telemetryv1beta1.LogPipeline + }{ + { + name: "should sanitize otlp namespace selectors", + input: &LogPipeline{ + Spec: LogPipelineSpec{ + Input: LogPipelineInput{ + OTLP: &OTLPInput{ + Namespaces: &NamespaceSelector{ + Include: []string{"valid-ns", "Invalid_NS", "another-valid-ns"}, + Exclude: []string{"valid-excluded", "Invalid@NS", "another-valid-excluded"}, + }, + }, + }, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"valid-ns", "another-valid-ns"}, + Exclude: []string{"valid-excluded", "another-valid-excluded"}, }, }, }, - URI: "/ingest/v1beta1/logs", - Port: "8080", - Compress: "on", - Format: "json", - TLSConfig: telemetryv1beta1.OutputTLS{ - SkipCertificateValidation: true, - CA: &telemetryv1beta1.ValueType{ - Value: "ca", + }, + }, + }, + { + name: "should sanitize application namespace selectors", + input: &LogPipeline{ + Spec: LogPipelineSpec{ + Input: LogPipelineInput{ + Application: &LogPipelineApplicationInput{ + Namespaces: LogPipelineNamespaceSelector{ + Include: []string{"valid-ns", "Invalid_NS", "another-valid-ns"}, + Exclude: []string{"valid-excluded", "Invalid@NS", "another-valid-excluded"}, + }, }, - Cert: &telemetryv1beta1.ValueType{ - Value: "cert", + }, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"valid-ns", "another-valid-ns"}, + Exclude: []string{"valid-excluded", "another-valid-excluded"}, + }, }, - Key: &telemetryv1beta1.ValueType{ - Value: "key", + }, + }, + }, + }, + { + name: "should fill default exclude if nothing is defined", + input: &LogPipeline{ + Spec: LogPipelineSpec{ + Input: LogPipelineInput{ + Application: &LogPipelineApplicationInput{ + Namespaces: LogPipelineNamespaceSelector{}, }, }, - Dedot: true, }, - OTLP: &telemetryv1beta1.OTLPOutput{ - Protocol: telemetryv1beta1.OTLPProtocolGRPC, - Endpoint: telemetryv1beta1.ValueType{Value: "localhost:4317"}, - Path: "/v1/logs", - Authentication: &telemetryv1beta1.AuthenticationOptions{Basic: &telemetryv1beta1.BasicAuthOptions{ - User: telemetryv1beta1.ValueType{ - Value: "user", + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: namespaces.System(), + }, }, - Password: telemetryv1beta1.ValueType{ - Value: "password", + }, + }, + }, + }, + { + name: "should not fill defaults if includes are defined", + input: &LogPipeline{ + Spec: LogPipelineSpec{ + Input: LogPipelineInput{ + Application: &LogPipelineApplicationInput{ + Namespaces: LogPipelineNamespaceSelector{ + Include: []string{"test"}, + }, }, - }}, - Headers: []telemetryv1beta1.Header{ - { - Name: "header1", - ValueType: telemetryv1beta1.ValueType{ - Value: "value1", + }, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"test"}, }, - Prefix: "prefix1", }, - { - Name: "header2", - ValueType: telemetryv1beta1.ValueType{ - Value: "value2", + }, + }, + }, + }, + { + name: "should not fill defaults if excludes are defined", + input: &LogPipeline{ + Spec: LogPipelineSpec{ + Input: LogPipelineInput{ + Application: &LogPipelineApplicationInput{ + Namespaces: LogPipelineNamespaceSelector{ + Exclude: []string{"test"}, }, - Prefix: "prefix2", }, }, - TLS: &telemetryv1beta1.OutputTLS{ - Disabled: true, - SkipCertificateValidation: true, - CA: &telemetryv1beta1.ValueType{Value: "ca"}, - Cert: &telemetryv1beta1.ValueType{Value: "cert"}, - Key: &telemetryv1beta1.ValueType{Value: "key"}, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: []string{"test"}, + }, + }, }, }, }, }, - Status: telemetryv1beta1.LogPipelineStatus{ - Conditions: []metav1.Condition{ - { - Type: "LogAgentHealthy", - Status: "True", - Reason: "FluentBitReady", - Message: "FluentBit is and collecting logs", + { + name: "should not fill defaults if system is true", + input: &LogPipeline{ + Spec: LogPipelineSpec{ + Input: LogPipelineInput{ + Application: &LogPipelineApplicationInput{ + Namespaces: LogPipelineNamespaceSelector{ + System: true, + }, + }, + }, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{}, + }, + }, }, }, - UnsupportedMode: ptr.To(true), + }, + { + name: "should convert all fields", + input: v1alpha1LogPipeline, + expected: v1beta1LogPipeline, }, } - dst := &LogPipeline{} - - err := dst.ConvertFrom(src) - require.NoError(t, err, "expected no error during ConvertTo") - - requireLogPipelinesEquivalent(t, dst, src) - - srcAfterRoundTrip := &telemetryv1beta1.LogPipeline{} - err = dst.ConvertTo(srcAfterRoundTrip) - require.NoError(t, err, "expected no error during ConvertFrom (round-trip)") - require.Empty(t, cmp.Diff(src, srcAfterRoundTrip), "expected source be equal to itself after round-trip") + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dst := &telemetryv1beta1.LogPipeline{} + err := tt.input.ConvertTo(dst) + require.NoError(t, err) + require.Equal(t, tt.expected, dst) + }) + } } -func requireLogPipelinesEquivalent(t *testing.T, x *LogPipeline, y *telemetryv1beta1.LogPipeline) { - require.Equal(t, x.ObjectMeta, y.ObjectMeta) - - xAppInput := x.Spec.Input.Application - yRuntimeInput := y.Spec.Input.Runtime - require.Equal(t, xAppInput.Namespaces.Include, yRuntimeInput.Namespaces.Include, "included namespaces mismatch") - require.Equal(t, xAppInput.Namespaces.Exclude, yRuntimeInput.Namespaces.Exclude, "excluded namespaces mismatch") - require.Equal(t, xAppInput.Namespaces.System, yRuntimeInput.Namespaces.System, "system namespaces mismatch") - require.Equal(t, xAppInput.Containers.Include, yRuntimeInput.Containers.Include, "included containers mismatch") - require.Equal(t, xAppInput.Containers.Exclude, yRuntimeInput.Containers.Exclude, "excluded containers mismatch") - require.Equal(t, xAppInput.KeepAnnotations, yRuntimeInput.KeepAnnotations, "keep annotations mismatch") - require.Equal(t, xAppInput.DropLabels, yRuntimeInput.DropLabels, "drop labels mismatch") - require.Equal(t, xAppInput.KeepOriginalBody, yRuntimeInput.KeepOriginalBody, "keep original body mismatch") - - xOTLPInput := x.Spec.Input.OTLP - yOTLPInput := y.Spec.Input.OTLP - require.Equal(t, xOTLPInput.Disabled, yOTLPInput.Disabled, "OTLP input disabled mismatch") - require.Equal(t, xOTLPInput.Namespaces.Include, yOTLPInput.Namespaces.Include, "OTLP included namespaces mismatch") - require.Equal(t, xOTLPInput.Namespaces.Exclude, yOTLPInput.Namespaces.Exclude, "OTLP excluded namespaces mismatch") - - require.Len(t, y.Spec.Files, 1, "expected one file") - require.Equal(t, x.Spec.Files[0].Name, y.Spec.Files[0].Name, "file name mismatch") - - require.Len(t, y.Spec.FluentBitFilters, 1, "expected one filter") - require.Equal(t, x.Spec.FluentBitFilters[0].Custom, y.Spec.FluentBitFilters[0].Custom, "custom filter mismatch") - - require.Equal(t, x.Spec.Output.Custom, y.Spec.Output.Custom, "custom output mismatch") - - xHTTP := x.Spec.Output.HTTP - yHTTP := y.Spec.Output.HTTP - require.Equal(t, xHTTP.Host.Value, yHTTP.Host.Value, "HTTP host mismatch") - require.Equal(t, xHTTP.User.Value, yHTTP.User.Value, "HTTP user mismatch") - require.Equal(t, xHTTP.Password.ValueFrom.SecretKeyRef.Name, yHTTP.Password.ValueFrom.SecretKeyRef.Name, "HTTP password secret name mismatch") - require.Equal(t, xHTTP.Password.ValueFrom.SecretKeyRef.Namespace, yHTTP.Password.ValueFrom.SecretKeyRef.Namespace, "HTTP password secret namespace mismatch") - require.Equal(t, xHTTP.Password.ValueFrom.SecretKeyRef.Key, yHTTP.Password.ValueFrom.SecretKeyRef.Key, "HTTP password secret key mismatch") - require.Equal(t, xHTTP.URI, yHTTP.URI, "HTTP URI mismatch") - require.Equal(t, xHTTP.Port, yHTTP.Port, "HTTP port mismatch") - require.Equal(t, xHTTP.Compress, yHTTP.Compress, "HTTP compress mismatch") - require.Equal(t, xHTTP.Format, yHTTP.Format, "HTTP format mismatch") - require.Equal(t, xHTTP.TLS.SkipCertificateValidation, yHTTP.TLSConfig.SkipCertificateValidation, "HTTP TLS skip certificate validation mismatch") - require.Equal(t, xHTTP.TLS.CA.Value, yHTTP.TLSConfig.CA.Value, "HTTP TLS CA mismatch") - require.Equal(t, xHTTP.TLS.Cert.Value, yHTTP.TLSConfig.Cert.Value, "HTTP TLS cert mismatch") - require.Equal(t, xHTTP.TLS.Key.Value, yHTTP.TLSConfig.Key.Value, "HTTP TLS key mismatch") - - xOTLP := x.Spec.Output.OTLP - yOTLP := y.Spec.Output.OTLP - - require.NotNil(t, xOTLP, "expected OTLP output") - require.NotNil(t, yOTLP, "expected OTLP output") - require.Equal(t, xOTLP.Protocol, string(yOTLP.Protocol), "OTLP protocol mismatch") - require.Equal(t, xOTLP.Endpoint.Value, yOTLP.Endpoint.Value, "OTLP endpoint mismatch") - require.Equal(t, xOTLP.Path, yOTLP.Path, "OTLP path mismatch") - require.Equal(t, xOTLP.Authentication.Basic.User.Value, yOTLP.Authentication.Basic.User.Value, "OTLP basic auth user mismatch") - require.Equal(t, xOTLP.Authentication.Basic.Password.Value, yOTLP.Authentication.Basic.Password.Value, "OTLP basic auth password mismatch") - require.Len(t, yOTLP.Headers, 2, "expected two headers") - require.Equal(t, xOTLP.Headers[0].Name, yOTLP.Headers[0].Name, "OTLP header name mismatch") - require.Equal(t, xOTLP.Headers[0].Value, yOTLP.Headers[0].Value, "OTLP header value mismatch") - require.Equal(t, xOTLP.Headers[0].Prefix, yOTLP.Headers[0].Prefix, "OTLP header prefix mismatch") - require.Equal(t, xOTLP.Headers[1].Name, yOTLP.Headers[1].Name, "OTLP header name mismatch") - require.Equal(t, xOTLP.Headers[1].Value, yOTLP.Headers[1].Value, "OTLP header value mismatch") - require.Equal(t, xOTLP.Headers[1].Prefix, yOTLP.Headers[1].Prefix, "OTLP header prefix mismatch") - require.Equal(t, xOTLP.TLS.Insecure, yOTLP.TLS.Disabled, "OTLP TLS insecure mismatch") - require.Equal(t, xOTLP.TLS.InsecureSkipVerify, yOTLP.TLS.SkipCertificateValidation, "OTLP TLS insecure skip verify mismatch") - require.Equal(t, xOTLP.TLS.CA.Value, yOTLP.TLS.CA.Value, "OTLP TLS CA mismatch") - require.Equal(t, xOTLP.TLS.Cert.Value, yOTLP.TLS.Cert.Value, "OTLP TLS cert mismatch") - require.Equal(t, xOTLP.TLS.Key.Value, yOTLP.TLS.Key.Value, "OTLP TLS key mismatch") - - require.Equal(t, x.Status.UnsupportedMode, y.Status.UnsupportedMode, "status unsupported mode mismatch") - require.ElementsMatch(t, x.Status.Conditions, y.Status.Conditions, "status conditions mismatch") - - xTransforms := x.Spec.Transforms - yTransforms := y.Spec.Transforms - require.Len(t, xTransforms, len(yTransforms), "expected same number of transforms") - - for i := range xTransforms { - require.ElementsMatch(t, xTransforms[i].Conditions, yTransforms[i].Conditions, "transform conditions mismatch at index %d", i) - require.Equal(t, xTransforms[i].Statements, yTransforms[i].Statements, "transform statements mismatch at index %d", i) +func TestLogPipelineConvertFrom(t *testing.T) { + tests := []struct { + name string + input *telemetryv1beta1.LogPipeline + expected *LogPipeline + }{ + { + name: "should convert namespace selectors without validation", + input: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"valid-ns", "Invalid_NS"}, + Exclude: []string{"valid-excluded", "Invalid@NS"}, + }, + }, + }, + }, + }, + expected: &LogPipeline{ + Spec: LogPipelineSpec{ + Input: LogPipelineInput{ + Application: &LogPipelineApplicationInput{ + Namespaces: LogPipelineNamespaceSelector{ + Include: []string{"valid-ns", "Invalid_NS"}, + Exclude: []string{"valid-excluded", "Invalid@NS"}, + }, + }, + }, + }, + }, + }, + { + name: "should convert all fields", + input: v1beta1LogPipeline, + expected: v1alpha1LogPipeline, + }, } - xFilter := x.Spec.Filters - yFilter := y.Spec.Filters - - require.Len(t, xFilter, len(yFilter), "expected same number of filters") - - for i := range xFilter { - require.ElementsMatch(t, xFilter[i].Conditions, yFilter[i].Conditions, "filter conditions mismatch at index %d", i) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dst := &LogPipeline{} + err := dst.ConvertFrom(tt.input) + require.NoError(t, err) + require.Equal(t, tt.expected, dst) + }) } } diff --git a/apis/telemetry/v1alpha1/logpipeline_types.go b/apis/telemetry/v1alpha1/logpipeline_types.go index 0fdbc1460d..663b2a8a48 100644 --- a/apis/telemetry/v1alpha1/logpipeline_types.go +++ b/apis/telemetry/v1alpha1/logpipeline_types.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - package v1alpha1 import ( diff --git a/apis/telemetry/v1alpha1/metricpipeline_conversion.go b/apis/telemetry/v1alpha1/metricpipeline_conversion.go new file mode 100644 index 0000000000..3c529e69d9 --- /dev/null +++ b/apis/telemetry/v1alpha1/metricpipeline_conversion.go @@ -0,0 +1,235 @@ +package v1alpha1 + +import ( + "errors" + + "sigs.k8s.io/controller-runtime/pkg/conversion" + + telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" +) + +// Converts between v1alpha1 and v1beta1 MetricPipeline CRDs +// There are no major changes to the MetricPipeline API between v1alpha1 and v1beta1. +// However, some changes were done in shared types which are documented in the related file and require to convert MetricPipelines. + +var errSrcTypeUnsupportedMetricPipeline = errors.New("source type is not MetricPipeline v1alpha1") +var errDstTypeUnsupportedMetricPipeline = errors.New("destination type is not MetricPipeline v1beta1") + +// ConvertTo implements conversion.Hub for MetricPipeline (v1alpha1 -> v1beta1) +func (src *MetricPipeline) ConvertTo(dstRaw conversion.Hub) error { + dst, ok := dstRaw.(*telemetryv1beta1.MetricPipeline) + if !ok { + return errDstTypeUnsupportedMetricPipeline + } + + // Copy metadata + dst.ObjectMeta = src.ObjectMeta + + // Copy input fields + dst.Spec.Input = telemetryv1beta1.MetricPipelineInput{} + if src.Spec.Input.Prometheus != nil { + dst.Spec.Input.Prometheus = &telemetryv1beta1.MetricPipelinePrometheusInput{ + Enabled: src.Spec.Input.Prometheus.Enabled, + Namespaces: convertNamespaceSelectorToBeta(src.Spec.Input.Prometheus.Namespaces), + DiagnosticMetrics: convertDiagnosticMetricsToBeta(src.Spec.Input.Prometheus.DiagnosticMetrics), + } + } + + if src.Spec.Input.Runtime != nil { + dst.Spec.Input.Runtime = &telemetryv1beta1.MetricPipelineRuntimeInput{ + Enabled: src.Spec.Input.Runtime.Enabled, + Namespaces: convertNamespaceSelectorToBeta(src.Spec.Input.Runtime.Namespaces), + Resources: convertRuntimeResourcesToBeta(src.Spec.Input.Runtime.Resources), + } + } + + if src.Spec.Input.Istio != nil { + dst.Spec.Input.Istio = &telemetryv1beta1.MetricPipelineIstioInput{ + Enabled: src.Spec.Input.Istio.Enabled, + Namespaces: convertNamespaceSelectorToBeta(src.Spec.Input.Istio.Namespaces), + DiagnosticMetrics: convertDiagnosticMetricsToBeta(src.Spec.Input.Istio.DiagnosticMetrics), + EnvoyMetrics: convertEnvoyMetricsToBeta(src.Spec.Input.Istio.EnvoyMetrics), + } + } + + dst.Spec.Input.OTLP = convertOTLPInputToBeta(src.Spec.Input.OTLP) + + // Copy output fields + dst.Spec.Output = telemetryv1beta1.MetricPipelineOutput{} + dst.Spec.Output.OTLP = convertOTLPOutputToBeta(src.Spec.Output.OTLP) + + // Copy everything else + if src.Spec.Transforms != nil { + for _, t := range src.Spec.Transforms { + dst.Spec.Transforms = append(dst.Spec.Transforms, convertTransformSpecToBeta(t)) + } + } + + if src.Spec.Filters != nil { + for _, t := range src.Spec.Filters { + dst.Spec.Filters = append(dst.Spec.Filters, convertFilterSpecToBeta(t)) + } + } + + dst.Status = telemetryv1beta1.MetricPipelineStatus(src.Status) + + return nil +} + +// ConvertFrom implements conversion.Hub for MetricPipeline (v1beta1 -> v1alpha1) +func (dst *MetricPipeline) ConvertFrom(srcRaw conversion.Hub) error { + src, ok := srcRaw.(*telemetryv1beta1.MetricPipeline) + if !ok { + return errSrcTypeUnsupportedMetricPipeline + } + + // Copy metadata + dst.ObjectMeta = src.ObjectMeta + + // Copy input fields + dst.Spec.Input = MetricPipelineInput{} + if src.Spec.Input.Prometheus != nil { + dst.Spec.Input.Prometheus = &MetricPipelinePrometheusInput{ + Enabled: src.Spec.Input.Prometheus.Enabled, + Namespaces: convertNamespaceSelectorToAlpha(src.Spec.Input.Prometheus.Namespaces), + DiagnosticMetrics: convertDiagnosticMetricsToAlpha(src.Spec.Input.Prometheus.DiagnosticMetrics), + } + } + + if src.Spec.Input.Runtime != nil { + dst.Spec.Input.Runtime = &MetricPipelineRuntimeInput{ + Enabled: src.Spec.Input.Runtime.Enabled, + Namespaces: convertNamespaceSelectorToAlpha(src.Spec.Input.Runtime.Namespaces), + Resources: convertRuntimeResourcesToAlpha(src.Spec.Input.Runtime.Resources), + } + } + + if src.Spec.Input.Istio != nil { + dst.Spec.Input.Istio = &MetricPipelineIstioInput{ + Enabled: src.Spec.Input.Istio.Enabled, + Namespaces: convertNamespaceSelectorToAlpha(src.Spec.Input.Istio.Namespaces), + DiagnosticMetrics: convertDiagnosticMetricsToAlpha(src.Spec.Input.Istio.DiagnosticMetrics), + EnvoyMetrics: convertEnvoyMetricsToAlpha(src.Spec.Input.Istio.EnvoyMetrics), + } + } + + dst.Spec.Input.OTLP = convertOTLPInputToAlpha(src.Spec.Input.OTLP) + + // Copy output fields + dst.Spec.Output = MetricPipelineOutput{} + if src.Spec.Output.OTLP != nil { + dst.Spec.Output.OTLP = convertOTLPOutputToAlpha(src.Spec.Output.OTLP) + } + + // Copy everything else + if src.Spec.Transforms != nil { + for _, t := range src.Spec.Transforms { + dst.Spec.Transforms = append(dst.Spec.Transforms, convertTransformSpecToAlpha(t)) + } + } + + if src.Spec.Filters != nil { + for _, t := range src.Spec.Filters { + dst.Spec.Filters = append(dst.Spec.Filters, convertFilterSpecToAlpha(t)) + } + } + + dst.Status = MetricPipelineStatus(src.Status) + + return nil +} + +// Helper conversion functions +func convertDiagnosticMetricsToBeta(dm *MetricPipelineIstioInputDiagnosticMetrics) *telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics { + if dm == nil { + return nil + } + + return &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: dm.Enabled, + } +} + +func convertDiagnosticMetricsToAlpha(dm *telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics) *MetricPipelineIstioInputDiagnosticMetrics { + if dm == nil { + return nil + } + + return &MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: dm.Enabled, + } +} + +func convertEnvoyMetricsToBeta(em *EnvoyMetrics) *telemetryv1beta1.EnvoyMetrics { + if em == nil { + return nil + } + + return &telemetryv1beta1.EnvoyMetrics{ + Enabled: em.Enabled, + } +} + +func convertEnvoyMetricsToAlpha(em *telemetryv1beta1.EnvoyMetrics) *EnvoyMetrics { + if em == nil { + return nil + } + + return &EnvoyMetrics{ + Enabled: em.Enabled, + } +} + +func convertRuntimeResourcesToBeta(r *MetricPipelineRuntimeInputResources) *telemetryv1beta1.MetricPipelineRuntimeInputResources { + if r == nil { + return nil + } + + return &telemetryv1beta1.MetricPipelineRuntimeInputResources{ + Pod: convertRuntimeResourceToBeta(r.Pod), + Container: convertRuntimeResourceToBeta(r.Container), + Node: convertRuntimeResourceToBeta(r.Node), + Volume: convertRuntimeResourceToBeta(r.Volume), + DaemonSet: convertRuntimeResourceToBeta(r.DaemonSet), + Deployment: convertRuntimeResourceToBeta(r.Deployment), + StatefulSet: convertRuntimeResourceToBeta(r.StatefulSet), + Job: convertRuntimeResourceToBeta(r.Job), + } +} + +func convertRuntimeResourcesToAlpha(r *telemetryv1beta1.MetricPipelineRuntimeInputResources) *MetricPipelineRuntimeInputResources { + if r == nil { + return nil + } + + return &MetricPipelineRuntimeInputResources{ + Pod: convertRuntimeResourceToAlpha(r.Pod), + Container: convertRuntimeResourceToAlpha(r.Container), + Node: convertRuntimeResourceToAlpha(r.Node), + Volume: convertRuntimeResourceToAlpha(r.Volume), + DaemonSet: convertRuntimeResourceToAlpha(r.DaemonSet), + Deployment: convertRuntimeResourceToAlpha(r.Deployment), + StatefulSet: convertRuntimeResourceToAlpha(r.StatefulSet), + Job: convertRuntimeResourceToAlpha(r.Job), + } +} + +func convertRuntimeResourceToBeta(r *MetricPipelineRuntimeInputResource) *telemetryv1beta1.MetricPipelineRuntimeInputResource { + if r == nil { + return nil + } + + return &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: r.Enabled, + } +} + +func convertRuntimeResourceToAlpha(r *telemetryv1beta1.MetricPipelineRuntimeInputResource) *MetricPipelineRuntimeInputResource { + if r == nil { + return nil + } + + return &MetricPipelineRuntimeInputResource{ + Enabled: r.Enabled, + } +} diff --git a/apis/telemetry/v1alpha1/metricpipeline_conversion_test.go b/apis/telemetry/v1alpha1/metricpipeline_conversion_test.go new file mode 100644 index 0000000000..43c4b67e5b --- /dev/null +++ b/apis/telemetry/v1alpha1/metricpipeline_conversion_test.go @@ -0,0 +1,313 @@ +package v1alpha1 + +import ( + "testing" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + + telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" +) + +var v1alpha1MetricPipeline = &MetricPipeline{ + ObjectMeta: metav1.ObjectMeta{ + Name: "full-pipeline", + Namespace: "default", + }, + Spec: MetricPipelineSpec{ + Input: MetricPipelineInput{ + Runtime: &MetricPipelineRuntimeInput{ + Enabled: ptr.To(true), + Namespaces: &NamespaceSelector{ + Include: []string{"ns-1", "ns-2"}, + Exclude: []string{"ns-3"}, + }, + Resources: &MetricPipelineRuntimeInputResources{ + Pod: &MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Container: &MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Node: &MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Volume: &MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Deployment: &MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + DaemonSet: &MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + StatefulSet: &MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Job: &MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + }, + }, + Istio: &MetricPipelineIstioInput{ + Enabled: ptr.To(false), + Namespaces: &NamespaceSelector{ + Include: []string{"app-ns-1"}, + Exclude: []string{"app-ns-2"}, + }, + DiagnosticMetrics: &MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: ptr.To(true), + }, + EnvoyMetrics: &EnvoyMetrics{ + Enabled: ptr.To(true), + }, + }, + Prometheus: &MetricPipelinePrometheusInput{ + Enabled: ptr.To(true), + Namespaces: &NamespaceSelector{ + Include: []string{"prom-ns-1"}, + Exclude: []string{"prom-ns-2"}, + }, + DiagnosticMetrics: &MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: ptr.To(true), + }, + }, + OTLP: &OTLPInput{ + Disabled: true, + Namespaces: &NamespaceSelector{ + Include: []string{"otlp-ns-1"}, + Exclude: []string{"otlp-ns-2"}, + }, + }, + }, + Output: MetricPipelineOutput{ + OTLP: &OTLPOutput{ + Endpoint: ValueType{ + Value: "otlp-collector:4317", + }, + TLS: &OTLPTLS{ + Insecure: true, + InsecureSkipVerify: true, + CA: &ValueType{Value: "ca-cert"}, + Cert: &ValueType{Value: "cert"}, + Key: &ValueType{Value: "key"}, + }, + Headers: []Header{ + {Name: "header1", ValueType: ValueType{Value: "value1"}, Prefix: "myPrefix"}, + }, + }, + }, + }, + Status: MetricPipelineStatus{ + Conditions: []metav1.Condition{ + { + Type: "type", + Status: "True", + Reason: "Ready", + Message: "message", + }, + }, + }, +} + +var v1beta1MetricPipeline = &telemetryv1beta1.MetricPipeline{ + ObjectMeta: metav1.ObjectMeta{ + Name: "full-pipeline", + Namespace: "default", + }, + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ + Enabled: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"ns-1", "ns-2"}, + Exclude: []string{"ns-3"}, + }, + Resources: &telemetryv1beta1.MetricPipelineRuntimeInputResources{ + Pod: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Container: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Node: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Volume: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Deployment: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + DaemonSet: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + StatefulSet: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + Job: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ + Enabled: ptr.To(false), + }, + }, + }, + Istio: &telemetryv1beta1.MetricPipelineIstioInput{ + Enabled: ptr.To(false), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"app-ns-1"}, + Exclude: []string{"app-ns-2"}, + }, + DiagnosticMetrics: &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: ptr.To(true), + }, + EnvoyMetrics: &telemetryv1beta1.EnvoyMetrics{ + Enabled: ptr.To(true), + }, + }, + Prometheus: &telemetryv1beta1.MetricPipelinePrometheusInput{ + Enabled: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"prom-ns-1"}, + Exclude: []string{"prom-ns-2"}, + }, + DiagnosticMetrics: &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: ptr.To(true), + }, + }, + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"otlp-ns-1"}, + Exclude: []string{"otlp-ns-2"}, + }, + }, + }, + Output: telemetryv1beta1.MetricPipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Endpoint: telemetryv1beta1.ValueType{ + Value: "otlp-collector:4317", + }, + TLS: &telemetryv1beta1.OutputTLS{ + Insecure: true, + InsecureSkipVerify: true, + CA: &telemetryv1beta1.ValueType{Value: "ca-cert"}, + Cert: &telemetryv1beta1.ValueType{Value: "cert"}, + Key: &telemetryv1beta1.ValueType{Value: "key"}, + }, + Headers: []telemetryv1beta1.Header{ + {Name: "header1", ValueType: telemetryv1beta1.ValueType{Value: "value1"}, Prefix: "myPrefix"}, + }, + }, + }, + }, + Status: telemetryv1beta1.MetricPipelineStatus{ + Conditions: []metav1.Condition{ + { + Type: "type", + Status: "True", + Reason: "Ready", + Message: "message", + }, + }, + }, +} + +func TestMetricPipelineConvertTo(t *testing.T) { + tests := []struct { + name string + input *MetricPipeline + expected *telemetryv1beta1.MetricPipeline + }{ + { + name: "should sanitize namespace selectors", + input: &MetricPipeline{ + Spec: MetricPipelineSpec{ + Input: MetricPipelineInput{ + Runtime: &MetricPipelineRuntimeInput{ + Namespaces: &NamespaceSelector{ + Include: []string{"valid-ns", "Invalid_NS", "another-valid-ns"}, + Exclude: []string{"valid-excluded", "Invalid@NS", "another-valid-excluded"}, + }, + }, + }, + }, + }, + expected: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"valid-ns", "another-valid-ns"}, + Exclude: []string{"valid-excluded", "another-valid-excluded"}, + }, + }, + }, + }, + }, + }, + { + name: "should convert all fields", + input: v1alpha1MetricPipeline, + expected: v1beta1MetricPipeline, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dst := &telemetryv1beta1.MetricPipeline{} + err := tt.input.ConvertTo(dst) + require.NoError(t, err) + require.Equal(t, tt.expected, dst) + }) + } +} + +func TestMetricPipelineConvertFrom(t *testing.T) { + tests := []struct { + name string + input *telemetryv1beta1.MetricPipeline + expected *MetricPipeline + }{ + { + name: "should convert namespace selectors without validation", + input: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Include: []string{"valid-ns", "Invalid_NS"}, + Exclude: []string{"valid-excluded", "Invalid@NS"}, + }, + }, + }, + }, + }, + expected: &MetricPipeline{ + Spec: MetricPipelineSpec{ + Input: MetricPipelineInput{ + Runtime: &MetricPipelineRuntimeInput{ + Namespaces: &NamespaceSelector{ + Include: []string{"valid-ns", "Invalid_NS"}, + Exclude: []string{"valid-excluded", "Invalid@NS"}, + }, + }, + }, + }, + }, + }, + { + name: "should convert all fields", + input: v1beta1MetricPipeline, + expected: v1alpha1MetricPipeline, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dst := &MetricPipeline{} + err := dst.ConvertFrom(tt.input) + require.NoError(t, err) + require.Equal(t, tt.expected, dst) + }) + } +} diff --git a/apis/telemetry/v1alpha1/metricpipeline_types.go b/apis/telemetry/v1alpha1/metricpipeline_types.go index 8322f2c899..39104eb237 100644 --- a/apis/telemetry/v1alpha1/metricpipeline_types.go +++ b/apis/telemetry/v1alpha1/metricpipeline_types.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - package v1alpha1 import ( @@ -72,7 +56,7 @@ type MetricPipelineSpec struct { // +kubebuilder:validation:Optional Transforms []TransformSpec `json:"transform,omitempty"` - // Filters specifies a list of filters to apply to telemetry data. + // Filter specifies a list of filters to apply to telemetry data. // +kubebuilder:validation:Optional Filters []FilterSpec `json:"filter,omitempty"` } @@ -159,7 +143,7 @@ type MetricPipelineIstioInput struct { // Enabled specifies if the 'istio' input is enabled. If enabled, istio-proxy metrics are scraped from Pods that have the istio-proxy sidecar injected. The default is `false`. // +kubebuilder:validation:Optional Enabled *bool `json:"enabled,omitempty"` - // Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces including system namespaces are enabled. + // Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces excluding system namespaces are enabled. To enable all namespaces including system namespaces, use an empty struct notation. // +kubebuilder:validation:Optional Namespaces *NamespaceSelector `json:"namespaces,omitempty"` // DiagnosticMetrics configures collection of additional diagnostic metrics. The default is `false`. diff --git a/apis/telemetry/v1alpha1/shared_types_conversion.go b/apis/telemetry/v1alpha1/shared_types_conversion.go new file mode 100644 index 0000000000..57ee5e0445 --- /dev/null +++ b/apis/telemetry/v1alpha1/shared_types_conversion.go @@ -0,0 +1,322 @@ +package v1alpha1 + +import ( + "regexp" + + "k8s.io/utils/ptr" + + telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" +) + +// Converts shared structs between v1alpha1 and v1beta1 CRDs. +// Major API changes which require specific conversion logic are: +// - input.otlp.Disabled (v1alpha1) is renamed to input.otlp.Enabled (v1beta1) and its logic is inverted. +// - output.otlp.protocol is now of type enum in v1beta1 instead of string in v1alpha1. +// - output.otlp.TLS struct got renamed + +// Remove invalid namespace names from NamespaceSelector slices (include/exclude) +func sanitizeNamespaceNames(names []string) []string { + var valid []string + // Kubernetes namespace regex + var nsRegex = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`) + for _, n := range names { + if len(n) <= 63 && nsRegex.MatchString(n) { + valid = append(valid, n) + } + } + + return valid +} + +func convertOTLPInputToBeta(src *OTLPInput) *telemetryv1beta1.OTLPInput { + if src == nil { + return nil + } + + return &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(!src.Disabled), + Namespaces: convertNamespaceSelectorToBeta(src.Namespaces), + } +} + +func convertOTLPInputToAlpha(src *telemetryv1beta1.OTLPInput) *OTLPInput { + if src == nil { + return nil + } + + return &OTLPInput{ + Disabled: src.Enabled != nil && !ptr.Deref(src.Enabled, false), + Namespaces: convertNamespaceSelectorToAlpha(src.Namespaces), + } +} + +func convertNamespaceSelectorToBeta(ns *NamespaceSelector) *telemetryv1beta1.NamespaceSelector { + if ns == nil { + return nil + } + + return &telemetryv1beta1.NamespaceSelector{ + Include: sanitizeNamespaceNames(ns.Include), + Exclude: sanitizeNamespaceNames(ns.Exclude), + } +} + +func convertNamespaceSelectorToAlpha(ns *telemetryv1beta1.NamespaceSelector) *NamespaceSelector { + if ns == nil { + return nil + } + + return &NamespaceSelector{ + Include: append([]string{}, ns.Include...), + Exclude: append([]string{}, ns.Exclude...), + } +} + +func convertOTLPOutputToBeta(o *OTLPOutput) *telemetryv1beta1.OTLPOutput { + if o == nil { + return nil + } + + return &telemetryv1beta1.OTLPOutput{ + Protocol: telemetryv1beta1.OTLPProtocol(o.Protocol), + Endpoint: convertValueTypeToBeta(o.Endpoint), + Path: o.Path, + Authentication: convertAuthenticationToBeta(o.Authentication), + Headers: convertHeadersToBeta(o.Headers), + TLS: convertOTLPTLSToBeta(o.TLS), + } +} + +func convertOTLPOutputToAlpha(o *telemetryv1beta1.OTLPOutput) *OTLPOutput { + if o == nil { + return nil + } + + return &OTLPOutput{ + Protocol: string(o.Protocol), + Endpoint: convertValueTypeToAlpha(o.Endpoint), + Path: o.Path, + Authentication: convertAuthenticationToAlpha(o.Authentication), + Headers: convertHeadersToAlpha(o.Headers), + TLS: convertOTLPTLSToAlpha(o.TLS), + } +} + +func convertValueTypeToBeta(v ValueType) telemetryv1beta1.ValueType { + result := telemetryv1beta1.ValueType{ + Value: v.Value, + } + + if v.ValueFrom != nil && v.ValueFrom.SecretKeyRef != nil { + result.ValueFrom = convertValueFromSourceToBeta(v.ValueFrom) + } + + return result +} + +func convertValueTypeToAlpha(v telemetryv1beta1.ValueType) ValueType { + result := ValueType{ + Value: v.Value, + } + if v.ValueFrom != nil && v.ValueFrom.SecretKeyRef != nil { + result.ValueFrom = convertValueFromSourceToAlpha(v.ValueFrom) + } + + return result +} + +func convertValueFromSourceToBeta(v *ValueFromSource) *telemetryv1beta1.ValueFromSource { + if v == nil { + return nil + } + + return &telemetryv1beta1.ValueFromSource{ + SecretKeyRef: convertSecretKeyRefToBeta(v.SecretKeyRef), + } +} + +func convertValueFromSourceToAlpha(v *telemetryv1beta1.ValueFromSource) *ValueFromSource { + if v == nil { + return nil + } + + return &ValueFromSource{ + SecretKeyRef: convertSecretKeyRefToAlpha(v.SecretKeyRef), + } +} + +func convertSecretKeyRefToBeta(s *SecretKeyRef) *telemetryv1beta1.SecretKeyRef { + if s == nil { + return nil + } + + return &telemetryv1beta1.SecretKeyRef{ + Name: s.Name, + Namespace: s.Namespace, + Key: s.Key, + } +} + +func convertSecretKeyRefToAlpha(s *telemetryv1beta1.SecretKeyRef) *SecretKeyRef { + if s == nil { + return nil + } + + return &SecretKeyRef{ + Name: s.Name, + Namespace: s.Namespace, + Key: s.Key, + } +} + +func convertAuthenticationToBeta(a *AuthenticationOptions) *telemetryv1beta1.AuthenticationOptions { + if a == nil { + return nil + } + + return &telemetryv1beta1.AuthenticationOptions{ + Basic: convertBasicAuthToBeta(a.Basic), + } +} + +func convertAuthenticationToAlpha(a *telemetryv1beta1.AuthenticationOptions) *AuthenticationOptions { + if a == nil { + return nil + } + + return &AuthenticationOptions{ + Basic: convertBasicAuthToAlpha(a.Basic), + } +} + +func convertBasicAuthToBeta(b *BasicAuthOptions) *telemetryv1beta1.BasicAuthOptions { + if b == nil { + return nil + } + + return &telemetryv1beta1.BasicAuthOptions{ + User: convertValueTypeToBeta(b.User), + Password: convertValueTypeToBeta(b.Password), + } +} + +func convertBasicAuthToAlpha(b *telemetryv1beta1.BasicAuthOptions) *BasicAuthOptions { + if b == nil { + return nil + } + + return &BasicAuthOptions{ + User: convertValueTypeToAlpha(b.User), + Password: convertValueTypeToAlpha(b.Password), + } +} + +func convertHeadersToBeta(hs []Header) []telemetryv1beta1.Header { + var out []telemetryv1beta1.Header + for _, h := range hs { + out = append(out, telemetryv1beta1.Header{ + ValueType: convertValueTypeToBeta(h.ValueType), + Name: h.Name, + Prefix: h.Prefix, + }) + } + + return out +} + +func convertHeadersToAlpha(hs []telemetryv1beta1.Header) []Header { + var out []Header + for _, h := range hs { + out = append(out, Header{ + ValueType: convertValueTypeToAlpha(h.ValueType), + Name: h.Name, + Prefix: h.Prefix, + }) + } + + return out +} + +func convertOTLPTLSToBeta(t *OTLPTLS) *telemetryv1beta1.OutputTLS { + if t == nil { + return nil + } + + return &telemetryv1beta1.OutputTLS{ + Insecure: t.Insecure, + InsecureSkipVerify: t.InsecureSkipVerify, + CA: convertValueTypeToBetaPtr(t.CA), + Cert: convertValueTypeToBetaPtr(t.Cert), + Key: convertValueTypeToBetaPtr(t.Key), + } +} + +func convertOTLPTLSToAlpha(t *telemetryv1beta1.OutputTLS) *OTLPTLS { + if t == nil { + return nil + } + + return &OTLPTLS{ + Insecure: t.Insecure, + InsecureSkipVerify: t.InsecureSkipVerify, + CA: convertValueTypeToAlphaPtr(t.CA), + Cert: convertValueTypeToAlphaPtr(t.Cert), + Key: convertValueTypeToAlphaPtr(t.Key), + } +} + +func convertValueTypeToBetaPtr(v *ValueType) *telemetryv1beta1.ValueType { + if v == nil { + return nil + } + + vt := convertValueTypeToBeta(*v) + + return &vt +} + +func convertValueTypeToAlphaPtr(v *telemetryv1beta1.ValueType) *ValueType { + if v == nil { + return nil + } + + vt := convertValueTypeToAlpha(*v) + + return &vt +} + +func convertTransformSpecToBeta(src TransformSpec) telemetryv1beta1.TransformSpec { + var dst telemetryv1beta1.TransformSpec + + dst.Conditions = append(dst.Conditions, src.Conditions...) + + dst.Statements = append(dst.Statements, src.Statements...) + + return dst +} + +func convertTransformSpecToAlpha(src telemetryv1beta1.TransformSpec) TransformSpec { + var dst TransformSpec + + dst.Conditions = append(dst.Conditions, src.Conditions...) + + dst.Statements = append(dst.Statements, src.Statements...) + + return dst +} + +func convertFilterSpecToBeta(src FilterSpec) telemetryv1beta1.FilterSpec { + var dst telemetryv1beta1.FilterSpec + + dst.Conditions = append(dst.Conditions, src.Conditions...) + + return dst +} + +func convertFilterSpecToAlpha(src telemetryv1beta1.FilterSpec) FilterSpec { + var dst FilterSpec + + dst.Conditions = append(dst.Conditions, src.Conditions...) + + return dst +} diff --git a/apis/telemetry/v1alpha1/tracepipeline_types.go b/apis/telemetry/v1alpha1/tracepipeline_types.go index e0256e1f64..859690b8f2 100644 --- a/apis/telemetry/v1alpha1/tracepipeline_types.go +++ b/apis/telemetry/v1alpha1/tracepipeline_types.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - package v1alpha1 import ( @@ -66,7 +50,7 @@ type TracePipelineSpec struct { // +kubebuilder:validation:Optional Transforms []TransformSpec `json:"transform,omitempty"` - // Filters specifies a list of filters to apply to telemetry data. + // Filter specifies a list of filters to apply to telemetry data. // +kubebuilder:validation:Optional Filters []FilterSpec `json:"filter,omitempty"` } diff --git a/apis/telemetry/v1beta1/groupversion_info.go b/apis/telemetry/v1beta1/groupversion_info.go index 4845656b74..7429b85e23 100644 --- a/apis/telemetry/v1beta1/groupversion_info.go +++ b/apis/telemetry/v1beta1/groupversion_info.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - // Package v1beta1 contains API Schema definitions for the telemetry v1beta1 API group // +kubebuilder:object:generate=true // +groupName=telemetry.kyma-project.io diff --git a/apis/telemetry/v1beta1/logpipeline_types.go b/apis/telemetry/v1beta1/logpipeline_types.go index 0d67f9f2e9..19cc0827ac 100644 --- a/apis/telemetry/v1beta1/logpipeline_types.go +++ b/apis/telemetry/v1beta1/logpipeline_types.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - package v1beta1 import ( @@ -114,12 +98,12 @@ type LogPipelineRuntimeInput struct { // Enabled specifies if the 'runtime' input is enabled. If enabled, application logs are collected from application containers stdout/stderr. The default is `true`. // +kubebuilder:validation:Optional Enabled *bool `json:"enabled,omitempty"` - // Namespaces describes whether application logs from specific namespaces are selected. The options are mutually exclusive. System namespaces are excluded by default. Use the `system` attribute with value `true` to enable them. + // Namespaces describes whether application logs from specific namespaces are selected. The options are mutually exclusive. By default, all namespaces except the system namespaces are enabled. To enable all namespaces including system namespaces, use an empty struct notation. // +kubebuilder:validation:Optional - Namespaces LogPipelineNamespaceSelector `json:"namespaces"` + Namespaces *NamespaceSelector `json:"namespaces,omitempty"` // Containers describes whether application logs from specific containers are selected. The options are mutually exclusive. // +kubebuilder:validation:Optional - Containers LogPipelineContainerSelector `json:"containers"` + Containers *LogPipelineContainerSelector `json:"containers,omitempty"` // KeepAnnotations defines whether to keep all Kubernetes annotations. The default is `false`. Only available when using an output of type `http` and `custom`. // +kubebuilder:validation:Optional KeepAnnotations *bool `json:"keepAnnotations,omitempty"` @@ -131,24 +115,6 @@ type LogPipelineRuntimeInput struct { KeepOriginalBody *bool `json:"keepOriginalBody,omitempty"` } -// LogPipelineNamespaceSelector describes whether application logs from specific Namespaces are selected. The options are mutually exclusive. System Namespaces are excluded by default. Use the `system` attribute with value `true` to enable them. -// +kubebuilder:validation:XValidation:rule="(has(self.include) == true ? 1 : 0) + (has(self.exclude) == true ? 1 : 0) + (has(self.system) == true ? 1 : 0) <= 1",message="Only one of 'include', 'exclude' or 'system' can be defined" -type LogPipelineNamespaceSelector struct { - // Include specifies the list of namespace names to include when collecting container logs. By default, logs from all namespaces are collected, except system namespaces. You cannot specify an include list together with an exclude list. - // +kubebuilder:validation:Optional - // +kubebuilder:validation:items:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` - // +kubebuilder:validation:items:MaxLength=63 - Include []string `json:"include,omitempty"` - // Exclude specifies the list of namespace names to exclude when collecting container logs. By default, logs from all namespaces are collected, except system namespaces. You cannot specify an exclude list together with an include list. - // +kubebuilder:validation:Optional - // +kubebuilder:validation:items:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` - // +kubebuilder:validation:items:MaxLength=63 - Exclude []string `json:"exclude,omitempty"` - // System specifies whether to collect logs from system namespaces. If set to `true`, you collect logs from all namespaces including system namespaces, such as like kube-system, istio-system, and kyma-system. The default is `false`. - // +kubebuilder:validation:Optional - System bool `json:"system,omitempty"` -} - // LogPipelineContainerSelector describes whether application logs from specific containers are selected. The options are mutually exclusive. // +kubebuilder:validation:XValidation:rule="!(has(self.include) && has(self.exclude))",message="Only one of 'include' or 'exclude' can be defined" type LogPipelineContainerSelector struct { diff --git a/apis/telemetry/v1beta1/metricpipeline_conversion.go b/apis/telemetry/v1beta1/metricpipeline_conversion.go new file mode 100644 index 0000000000..89567cf491 --- /dev/null +++ b/apis/telemetry/v1beta1/metricpipeline_conversion.go @@ -0,0 +1,5 @@ +package v1beta1 + +// Hub marks this type as a conversion hub. +func (lp *MetricPipeline) Hub() { +} diff --git a/apis/telemetry/v1beta1/metricpipeline_types.go b/apis/telemetry/v1beta1/metricpipeline_types.go index 7e4cf04400..6e3b88695d 100644 --- a/apis/telemetry/v1beta1/metricpipeline_types.go +++ b/apis/telemetry/v1beta1/metricpipeline_types.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - package v1beta1 import ( @@ -75,7 +59,7 @@ type MetricPipelineSpec struct { // Filter specifies a list of filters to apply to telemetry data. // +kubebuilder:validation:Optional - Filter []FilterSpec `json:"filter,omitempty"` + Filters []FilterSpec `json:"filter,omitempty"` } // MetricPipelineInput configures additional inputs for metric collection. @@ -160,7 +144,7 @@ type MetricPipelineIstioInput struct { // Enabled specifies if the 'istio' input is enabled. If enabled, istio-proxy metrics are scraped from Pods that have the istio-proxy sidecar injected. The default is `false`. // +kubebuilder:validation:Optional Enabled *bool `json:"enabled,omitempty"` - // Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces including system namespaces are enabled. + // Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces excluding system namespaces are enabled. To enable all namespaces including system namespaces, use an empty struct notation. // +kubebuilder:validation:Optional Namespaces *NamespaceSelector `json:"namespaces,omitempty"` // DiagnosticMetrics configures collection of additional diagnostic metrics. The default is `false`. diff --git a/apis/telemetry/v1beta1/shared_types.go b/apis/telemetry/v1beta1/shared_types.go index a8aa201148..3e52ba51ea 100644 --- a/apis/telemetry/v1beta1/shared_types.go +++ b/apis/telemetry/v1beta1/shared_types.go @@ -96,12 +96,12 @@ type Header struct { // OutputTLS defines TLS options for an output. // +kubebuilder:validation:XValidation:rule="has(self.cert) == has(self.key)", message="Can define either both 'cert' and 'key', or neither" type OutputTLS struct { - // Disabled specifies if TLS is disabled or enabled. Default is `false`. + // Insecure defines whether to send requests using plaintext instead of TLS. // +kubebuilder:validation:Optional - Disabled bool `json:"disabled,omitempty"` - // If `true`, the validation of certificates is skipped. Default is `false`. + Insecure bool `json:"insecure,omitempty"` + // InsecureSkipVerify defines whether to skip server certificate verification when using TLS. // +kubebuilder:validation:Optional - SkipCertificateValidation bool `json:"skipCertificateValidation,omitempty"` + InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` // Defines an optional CA certificate for server certificate verification when using TLS. The certificate must be provided in PEM format. // +kubebuilder:validation:Optional CA *ValueType `json:"ca,omitempty"` @@ -115,10 +115,10 @@ type OutputTLS struct { // OTLPInput defines the collection of push-based metrics that use the OpenTelemetry protocol. type OTLPInput struct { - // Disabled specifies if the 'otlp' input is deactivated. If disabled, then no push-based OTLP signals are collected. The default is `false`. + // Enabled specifies if the 'otlp' input is enabled. If enabled, then push-based OTLP signals are collected. The default is `true`. // +kubebuilder:validation:Optional - Disabled bool `json:"disabled,omitempty"` - // Namespaces describes whether push-based OTLP signals from specific namespaces are selected. System namespaces are enabled by default. + Enabled *bool `json:"enabled,omitempty"` + // Namespaces describe whether push-based OTLP signals from specific namespaces are selected. By default, all namespaces excluding system namespaces are enabled. To enable all namespaces including system namespaces, use an empty struct notation. // +kubebuilder:validation:Optional Namespaces *NamespaceSelector `json:"namespaces,omitempty"` } diff --git a/apis/telemetry/v1beta1/tracepipeline_types.go b/apis/telemetry/v1beta1/tracepipeline_types.go index 619d7f1244..e4a26eb333 100644 --- a/apis/telemetry/v1beta1/tracepipeline_types.go +++ b/apis/telemetry/v1beta1/tracepipeline_types.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - package v1beta1 import ( @@ -69,7 +53,7 @@ type TracePipelineSpec struct { // Filter specifies a list of filters to apply to telemetry data. // +kubebuilder:validation:Optional - Filter []FilterSpec `json:"filter,omitempty"` + Filters []FilterSpec `json:"filter,omitempty"` } // TracePipelineOutput defines the output configuration section. diff --git a/apis/telemetry/v1beta1/zz_generated.deepcopy.go b/apis/telemetry/v1beta1/zz_generated.deepcopy.go index b0efc41973..c156e7ff10 100644 --- a/apis/telemetry/v1beta1/zz_generated.deepcopy.go +++ b/apis/telemetry/v1beta1/zz_generated.deepcopy.go @@ -284,31 +284,6 @@ func (in *LogPipelineList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LogPipelineNamespaceSelector) DeepCopyInto(out *LogPipelineNamespaceSelector) { - *out = *in - if in.Include != nil { - in, out := &in.Include, &out.Include - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Exclude != nil { - in, out := &in.Exclude, &out.Exclude - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogPipelineNamespaceSelector. -func (in *LogPipelineNamespaceSelector) DeepCopy() *LogPipelineNamespaceSelector { - if in == nil { - return nil - } - out := new(LogPipelineNamespaceSelector) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LogPipelineOutput) DeepCopyInto(out *LogPipelineOutput) { *out = *in @@ -342,8 +317,16 @@ func (in *LogPipelineRuntimeInput) DeepCopyInto(out *LogPipelineRuntimeInput) { *out = new(bool) **out = **in } - in.Namespaces.DeepCopyInto(&out.Namespaces) - in.Containers.DeepCopyInto(&out.Containers) + if in.Namespaces != nil { + in, out := &in.Namespaces, &out.Namespaces + *out = new(NamespaceSelector) + (*in).DeepCopyInto(*out) + } + if in.Containers != nil { + in, out := &in.Containers, &out.Containers + *out = new(LogPipelineContainerSelector) + (*in).DeepCopyInto(*out) + } if in.KeepAnnotations != nil { in, out := &in.KeepAnnotations, &out.KeepAnnotations *out = new(bool) @@ -778,8 +761,8 @@ func (in *MetricPipelineSpec) DeepCopyInto(out *MetricPipelineSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Filter != nil { - in, out := &in.Filter, &out.Filter + if in.Filters != nil { + in, out := &in.Filters, &out.Filters *out = make([]FilterSpec, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) @@ -847,6 +830,11 @@ func (in *NamespaceSelector) DeepCopy() *NamespaceSelector { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OTLPInput) DeepCopyInto(out *OTLPInput) { *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } if in.Namespaces != nil { in, out := &in.Namespaces, &out.Namespaces *out = new(NamespaceSelector) @@ -1032,8 +1020,8 @@ func (in *TracePipelineSpec) DeepCopyInto(out *TracePipelineSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Filter != nil { - in, out := &in.Filter, &out.Filter + if in.Filters != nil { + in, out := &in.Filters, &out.Filters *out = make([]FilterSpec, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) diff --git a/docs/user/resources/05-metricpipeline.md b/docs/user/resources/05-metricpipeline.md index 572bdb5ef7..25db0ae3fd 100644 --- a/docs/user/resources/05-metricpipeline.md +++ b/docs/user/resources/05-metricpipeline.md @@ -74,7 +74,7 @@ For details, see the [MetricPipeline specification file](https://github.com/kyma | **input.​istio.​enabled** | boolean | Enabled specifies if the 'istio' input is enabled. If enabled, istio-proxy metrics are scraped from Pods that have the istio-proxy sidecar injected. The default is `false`. | | **input.​istio.​envoyMetrics** | object | EnvoyMetrics enables the collection of additional Envoy metrics with prefix `envoy_`. The default is `false`. | | **input.​istio.​envoyMetrics.​enabled** | boolean | Enabled specifies that Envoy metrics with prefix `envoy_` are scraped additionally. The default is `false`. | -| **input.​istio.​namespaces** | object | Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces including system namespaces are enabled. | +| **input.​istio.​namespaces** | object | Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces excluding system namespaces are enabled. To enable all namespaces including system namespaces, use an empty struct notation. | | **input.​istio.​namespaces.​exclude** | \[\]string | Exclude telemetry data from the specified namespace names only. By default, all namespaces (depending on input type: except system namespaces) are collected. You cannot specify an exclude list together with an include list. | | **input.​istio.​namespaces.​include** | \[\]string | Include telemetry data from the specified namespace names only. By default, all namespaces (depending on input type: except system namespaces) are included. You cannot specify an include list together with an exclude list. | | **input.​otlp** | object | OTLP input configures the push endpoint to receive metrics from an OTLP source. | diff --git a/go.mod b/go.mod index 840b33755e..0a028d3a17 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.25.3 require ( github.com/go-logr/logr v1.4.3 github.com/go-logr/zapr v1.3.0 - github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/onsi/gomega v1.38.2 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.136.0 @@ -57,6 +56,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.7.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect diff --git a/helm/charts/default/templates/telemetry.kyma-project.io_metricpipelines.yaml b/helm/charts/default/templates/telemetry.kyma-project.io_metricpipelines.yaml index 4dec73cf13..d64db81301 100644 --- a/helm/charts/default/templates/telemetry.kyma-project.io_metricpipelines.yaml +++ b/helm/charts/default/templates/telemetry.kyma-project.io_metricpipelines.yaml @@ -88,7 +88,7 @@ spec: type: boolean type: object namespaces: - description: Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces including system namespaces are enabled. + description: Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces excluding system namespaces are enabled. To enable all namespaces including system namespaces, use an empty struct notation. properties: exclude: description: 'Exclude telemetry data from the specified namespace names only. By default, all namespaces (depending on input type: except system namespaces) are collected. You cannot specify an exclude list together with an include list.' diff --git a/helm/charts/experimental/templates/telemetry.kyma-project.io_logpipelines.yaml b/helm/charts/experimental/templates/telemetry.kyma-project.io_logpipelines.yaml index 485440b9e0..daafc51ac7 100644 --- a/helm/charts/experimental/templates/telemetry.kyma-project.io_logpipelines.yaml +++ b/helm/charts/experimental/templates/telemetry.kyma-project.io_logpipelines.yaml @@ -1255,15 +1255,16 @@ spec: description: OTLP input configures the push endpoint to receive logs from a OTLP source. properties: - disabled: - description: Disabled specifies if the 'otlp' input is deactivated. - If disabled, then no push-based OTLP signals are collected. - The default is `false`. + enabled: + description: Enabled specifies if the 'otlp' input is enabled. + If enabled, then push-based OTLP signals are collected. + The default is `true`. type: boolean namespaces: - description: Namespaces describes whether push-based OTLP - signals from specific namespaces are selected. System namespaces - are enabled by default. + description: Namespaces describe whether push-based OTLP signals + from specific namespaces are selected. By default, all namespaces + excluding system namespaces are enabled. To enable all namespaces + including system namespaces, use an empty struct notation. properties: exclude: description: 'Exclude telemetry data from the specified @@ -1344,45 +1345,36 @@ spec: namespaces: description: Namespaces describes whether application logs from specific namespaces are selected. The options are mutually - exclusive. System namespaces are excluded by default. Use - the `system` attribute with value `true` to enable them. + exclusive. By default, all namespaces except the system + namespaces are enabled. To enable all namespaces including + system namespaces, use an empty struct notation. properties: exclude: - description: Exclude specifies the list of namespace names - to exclude when collecting container logs. By default, - logs from all namespaces are collected, except system - namespaces. You cannot specify an exclude list together - with an include list. + description: 'Exclude telemetry data from the specified + namespace names only. By default, all namespaces (depending + on input type: except system namespaces) are collected. + You cannot specify an exclude list together with an + include list.' items: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string type: array include: - description: Include specifies the list of namespace names - to include when collecting container logs. By default, - logs from all namespaces are collected, except system - namespaces. You cannot specify an include list together - with an exclude list. + description: 'Include telemetry data from the specified + namespace names only. By default, all namespaces (depending + on input type: except system namespaces) are included. + You cannot specify an include list together with an + exclude list.' items: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string type: array - system: - description: System specifies whether to collect logs - from system namespaces. If set to `true`, you collect - logs from all namespaces including system namespaces, - such as like kube-system, istio-system, and kyma-system. - The default is `false`. - type: boolean type: object x-kubernetes-validations: - - message: Only one of 'include', 'exclude' or 'system' can - be defined - rule: '(has(self.include) == true ? 1 : 0) + (has(self.exclude) - == true ? 1 : 0) + (has(self.system) == true ? 1 : 0) - <= 1' + - message: Only one of 'include' or 'exclude' can be defined + rule: '!(has(self.include) && has(self.exclude))' type: object type: object output: @@ -1599,9 +1591,13 @@ spec: - message: Exactly one of 'value' or 'valueFrom' must be set rule: has(self.value) != has(self.valueFrom) - disabled: - description: Disabled specifies if TLS is disabled or - enabled. Default is `false`. + insecure: + description: Insecure defines whether to send requests + using plaintext instead of TLS. + type: boolean + insecureSkipVerify: + description: InsecureSkipVerify defines whether to skip + server certificate verification when using TLS. type: boolean key: description: Defines the client key to use when using @@ -1648,10 +1644,6 @@ spec: - message: Exactly one of 'value' or 'valueFrom' must be set rule: has(self.value) != has(self.valueFrom) - skipCertificateValidation: - description: If `true`, the validation of certificates - is skipped. Default is `false`. - type: boolean type: object x-kubernetes-validations: - message: Can define either both 'cert' and 'key', or neither @@ -2023,9 +2015,13 @@ spec: - message: Exactly one of 'value' or 'valueFrom' must be set rule: has(self.value) != has(self.valueFrom) - disabled: - description: Disabled specifies if TLS is disabled or - enabled. Default is `false`. + insecure: + description: Insecure defines whether to send requests + using plaintext instead of TLS. + type: boolean + insecureSkipVerify: + description: InsecureSkipVerify defines whether to skip + server certificate verification when using TLS. type: boolean key: description: Defines the client key to use when using @@ -2072,10 +2068,6 @@ spec: - message: Exactly one of 'value' or 'valueFrom' must be set rule: has(self.value) != has(self.valueFrom) - skipCertificateValidation: - description: If `true`, the validation of certificates - is skipped. Default is `false`. - type: boolean type: object x-kubernetes-validations: - message: Can define either both 'cert' and 'key', or neither diff --git a/helm/charts/experimental/templates/telemetry.kyma-project.io_metricpipelines.yaml b/helm/charts/experimental/templates/telemetry.kyma-project.io_metricpipelines.yaml index 448591fc05..be49be477b 100644 --- a/helm/charts/experimental/templates/telemetry.kyma-project.io_metricpipelines.yaml +++ b/helm/charts/experimental/templates/telemetry.kyma-project.io_metricpipelines.yaml @@ -65,7 +65,7 @@ spec: description: Spec defines the desired characteristics of MetricPipeline. properties: filter: - description: Filters specifies a list of filters to apply to telemetry + description: Filter specifies a list of filters to apply to telemetry data. items: description: FilterSpec defines a filter to apply to telemetry data. @@ -116,7 +116,8 @@ spec: namespaces: description: Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces - including system namespaces are enabled. + excluding system namespaces are enabled. To enable all namespaces + including system namespaces, use an empty struct notation. properties: exclude: description: 'Exclude telemetry data from the specified @@ -940,7 +941,8 @@ spec: namespaces: description: Namespaces configures the namespaces for which the collection should be activated. By default, all namespaces - including system namespaces are enabled. + excluding system namespaces are enabled. To enable all namespaces + including system namespaces, use an empty struct notation. properties: exclude: description: 'Exclude telemetry data from the specified @@ -973,15 +975,16 @@ spec: description: OTLP input configures the push endpoint to receive metrics from an OTLP source. properties: - disabled: - description: Disabled specifies if the 'otlp' input is deactivated. - If disabled, then no push-based OTLP signals are collected. - The default is `false`. + enabled: + description: Enabled specifies if the 'otlp' input is enabled. + If enabled, then push-based OTLP signals are collected. + The default is `true`. type: boolean namespaces: - description: Namespaces describes whether push-based OTLP - signals from specific namespaces are selected. System namespaces - are enabled by default. + description: Namespaces describe whether push-based OTLP signals + from specific namespaces are selected. By default, all namespaces + excluding system namespaces are enabled. To enable all namespaces + including system namespaces, use an empty struct notation. properties: exclude: description: 'Exclude telemetry data from the specified @@ -1509,9 +1512,13 @@ spec: - message: Exactly one of 'value' or 'valueFrom' must be set rule: has(self.value) != has(self.valueFrom) - disabled: - description: Disabled specifies if TLS is disabled or - enabled. Default is `false`. + insecure: + description: Insecure defines whether to send requests + using plaintext instead of TLS. + type: boolean + insecureSkipVerify: + description: InsecureSkipVerify defines whether to skip + server certificate verification when using TLS. type: boolean key: description: Defines the client key to use when using @@ -1558,10 +1565,6 @@ spec: - message: Exactly one of 'value' or 'valueFrom' must be set rule: has(self.value) != has(self.valueFrom) - skipCertificateValidation: - description: If `true`, the validation of certificates - is skipped. Default is `false`. - type: boolean type: object x-kubernetes-validations: - message: Can define either both 'cert' and 'key', or neither diff --git a/helm/charts/experimental/templates/telemetry.kyma-project.io_tracepipelines.yaml b/helm/charts/experimental/templates/telemetry.kyma-project.io_tracepipelines.yaml index 6d1cf08bce..0642bd2e90 100644 --- a/helm/charts/experimental/templates/telemetry.kyma-project.io_tracepipelines.yaml +++ b/helm/charts/experimental/templates/telemetry.kyma-project.io_tracepipelines.yaml @@ -62,7 +62,7 @@ spec: description: Spec defines the desired state of TracePipeline properties: filter: - description: Filters specifies a list of filters to apply to telemetry + description: Filter specifies a list of filters to apply to telemetry data. items: description: FilterSpec defines a filter to apply to telemetry data. @@ -939,9 +939,13 @@ spec: - message: Exactly one of 'value' or 'valueFrom' must be set rule: has(self.value) != has(self.valueFrom) - disabled: - description: Disabled specifies if TLS is disabled or - enabled. Default is `false`. + insecure: + description: Insecure defines whether to send requests + using plaintext instead of TLS. + type: boolean + insecureSkipVerify: + description: InsecureSkipVerify defines whether to skip + server certificate verification when using TLS. type: boolean key: description: Defines the client key to use when using @@ -988,10 +992,6 @@ spec: - message: Exactly one of 'value' or 'valueFrom' must be set rule: has(self.value) != has(self.valueFrom) - skipCertificateValidation: - description: If `true`, the validation of certificates - is skipped. Default is `false`. - type: boolean type: object x-kubernetes-validations: - message: Can define either both 'cert' and 'key', or neither diff --git a/internal/utils/test/log_pipeline_builder.go b/internal/utils/test/log_pipeline_builder.go index e1f056ad42..a15ed9f3c4 100644 --- a/internal/utils/test/log_pipeline_builder.go +++ b/internal/utils/test/log_pipeline_builder.go @@ -80,7 +80,7 @@ func BuildLogPipelineV1Beta1RuntimeInput() telemetryv1beta1.LogPipelineInput { input := telemetryv1beta1.LogPipelineInput{ Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ Enabled: ptr.To(true), - Namespaces: telemetryv1beta1.LogPipelineNamespaceSelector{}, + Namespaces: &telemetryv1beta1.NamespaceSelector{}, }, } @@ -93,7 +93,7 @@ func BuildLogPipelineV1Beta1OTLPInput() telemetryv1beta1.LogPipelineInput { Enabled: ptr.To(false), }, OTLP: &telemetryv1beta1.OTLPInput{ - Disabled: false, + Enabled: ptr.To(true), Namespaces: &telemetryv1beta1.NamespaceSelector{}, }, } diff --git a/internal/webhookcert/resources.go b/internal/webhookcert/resources.go index 13da1b39bc..9ac62eb488 100644 --- a/internal/webhookcert/resources.go +++ b/internal/webhookcert/resources.go @@ -17,8 +17,9 @@ 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. +// 2- Updates mutating webhook configuration with the provided CA bundle. +// 3- Updates LogPipeline CRD with conversion webhook configuration. +// 4- Updates MetricPipeline CRD with conversion webhook configuration. 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) @@ -29,10 +30,14 @@ func applyWebhookConfigResources(ctx context.Context, c client.Client, caBundle } conversionWebhookConfig := makeConversionWebhookConfig(caBundle, config) - if err := updateLogPipelineCRDWithConversionWebhookConfig(ctx, c, conversionWebhookConfig); err != nil { + if err := updatePipelineCRDWithConversionWebhookConfig(ctx, c, types.NamespacedName{Name: "logpipelines.telemetry.kyma-project.io"}, conversionWebhookConfig); err != nil { return fmt.Errorf("failed to update LogPipeline CRD with conversion webhook configuration: %w", err) } + if err := updatePipelineCRDWithConversionWebhookConfig(ctx, c, types.NamespacedName{Name: "metricpipelines.telemetry.kyma-project.io"}, conversionWebhookConfig); err != nil { + return fmt.Errorf("failed to update MetricPipeline CRD with conversion webhook configuration: %w", err) + } + return nil } @@ -67,15 +72,15 @@ func makeConversionWebhookConfig(caBundle []byte, config Config) apiextensionsv1 } } -func updateLogPipelineCRDWithConversionWebhookConfig(ctx context.Context, c client.Client, conversion apiextensionsv1.CustomResourceConversion) error { - var logPipelineCRD apiextensionsv1.CustomResourceDefinition - if err := c.Get(ctx, types.NamespacedName{Name: "logpipelines.telemetry.kyma-project.io"}, &logPipelineCRD); err != nil { - return fmt.Errorf("failed to get logpipelines CRD: %w", err) +func updatePipelineCRDWithConversionWebhookConfig(ctx context.Context, c client.Client, pipelineType types.NamespacedName, conversion apiextensionsv1.CustomResourceConversion) error { + var crd apiextensionsv1.CustomResourceDefinition + if err := c.Get(ctx, pipelineType, &crd); err != nil { + return fmt.Errorf("failed to get CRD %s: %w", pipelineType, err) } - logPipelineCRD.Spec.Conversion = &conversion + crd.Spec.Conversion = &conversion - return c.Update(ctx, &logPipelineCRD) + return c.Update(ctx, &crd) } func updateMutatingWebhookConfig(ctx context.Context, c client.Client, caBundle []byte, config Config) error { diff --git a/internal/webhookcert/webhook_cert_test.go b/internal/webhookcert/webhook_cert_test.go index 97e21fb521..8dbfb8ef51 100644 --- a/internal/webhookcert/webhook_cert_test.go +++ b/internal/webhookcert/webhook_cert_test.go @@ -50,6 +50,21 @@ var ( }, }, } + + metricPipelinesCRD = apiextensionsv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricpipelines.telemetry.kyma-project.io", + }, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Conversion: &apiextensionsv1.CustomResourceConversion{ + Strategy: apiextensionsv1.WebhookConverter, + Webhook: &apiextensionsv1.WebhookConversion{ + ClientConfig: &apiextensionsv1.WebhookClientConfig{}, + }, + }, + }, + } + labels = map[string]string{ "app.kubernetes.io/component": "telemetry", "app.kubernetes.io/instance": "telemetry-manager", @@ -224,51 +239,68 @@ var ( } ) -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, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() - - certDir := t.TempDir() - defer func(path string) { - deleteErr := os.RemoveAll(path) - require.NoError(t, deleteErr) - }(certDir) - - config := Config{ - rsaKeySize: testRsaKeySize, - CertDir: certDir, - ServiceName: webhookService, - CASecretName: caBundleSecret, - ValidatingWebhookName: validatingWebhookNamespacedName, - MutatingWebhookName: mutatingWebhookNamespacedName, +func TestUpdatePipelineWithWebhookConfig(t *testing.T) { + tests := []struct { + name string + crd *apiextensionsv1.CustomResourceDefinition + }{ + { + name: "logpipeline", + crd: &logPipelinesCRD, + }, + { + name: "metricpipeline", + crd: &metricPipelinesCRD, + }, } - err := EnsureCertificate(t.Context(), client, config) - require.NoError(t, err) + for _, tt := range tests { + t.Run(tt.name, func(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, &metricPipelinesCRD, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() + + certDir := t.TempDir() + defer func(path string) { + deleteErr := os.RemoveAll(path) + require.NoError(t, deleteErr) + }(certDir) + + config := Config{ + rsaKeySize: testRsaKeySize, + CertDir: certDir, + ServiceName: webhookService, + CASecretName: caBundleSecret, + ValidatingWebhookName: validatingWebhookNamespacedName, + MutatingWebhookName: mutatingWebhookNamespacedName, + } - serverCert, err := os.ReadFile(path.Join(certDir, "tls.crt")) - require.NoError(t, err) + err := EnsureCertificate(t.Context(), client, config) + require.NoError(t, err) - var crd apiextensionsv1.CustomResourceDefinition + serverCert, err := os.ReadFile(path.Join(certDir, "tls.crt")) + require.NoError(t, err) - require.NoError(t, client.Get(t.Context(), types.NamespacedName{Name: "logpipelines.telemetry.kyma-project.io"}, &crd)) + var crd apiextensionsv1.CustomResourceDefinition + require.NoError(t, client.Get(t.Context(), types.NamespacedName{Name: tt.crd.Name}, &crd)) - require.Equal(t, apiextensionsv1.WebhookConverter, crd.Spec.Conversion.Strategy) - require.Equal(t, webhookService.Name, crd.Spec.Conversion.Webhook.ClientConfig.Service.Name) - require.Equal(t, webhookService.Namespace, crd.Spec.Conversion.Webhook.ClientConfig.Service.Namespace) - require.Equal(t, int32(443), *crd.Spec.Conversion.Webhook.ClientConfig.Service.Port) - require.Equal(t, "/convert", *crd.Spec.Conversion.Webhook.ClientConfig.Service.Path) + require.Equal(t, apiextensionsv1.WebhookConverter, crd.Spec.Conversion.Strategy) + require.Equal(t, webhookService.Name, crd.Spec.Conversion.Webhook.ClientConfig.Service.Name) + require.Equal(t, webhookService.Namespace, crd.Spec.Conversion.Webhook.ClientConfig.Service.Namespace) + require.Equal(t, int32(443), *crd.Spec.Conversion.Webhook.ClientConfig.Service.Port) + require.Equal(t, "/convert", *crd.Spec.Conversion.Webhook.ClientConfig.Service.Path) - crdCABundle := crd.Spec.Conversion.Webhook.ClientConfig.CABundle - require.NotEmpty(t, crdCABundle) + crdCABundle := crd.Spec.Conversion.Webhook.ClientConfig.CABundle + require.NotEmpty(t, crdCABundle) - var chainChecker certChainCheckerImpl + var chainChecker certChainCheckerImpl - certValid, err := chainChecker.checkRoot(t.Context(), serverCert, crdCABundle) - require.NoError(t, err) - require.True(t, certValid) + certValid, err := chainChecker.checkRoot(t.Context(), serverCert, crdCABundle) + require.NoError(t, err) + require.True(t, certValid) + }) + } } func TestUpdateWebhookConfig(t *testing.T) { @@ -276,7 +308,7 @@ func TestUpdateWebhookConfig(t *testing.T) { require.NoError(t, clientgoscheme.AddToScheme(scheme)) require.NoError(t, apiextensionsv1.AddToScheme(scheme)) - client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &metricPipelinesCRD, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() certDir := t.TempDir() @@ -360,7 +392,7 @@ 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, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &metricPipelinesCRD, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() certDir := t.TempDir() @@ -394,7 +426,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, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&logPipelinesCRD, &metricPipelinesCRD, &validatingWebhookConfiguration, &mutatingWebhookConfiguration).Build() certDir := t.TempDir() diff --git a/main.go b/main.go index e5b744b298..6e379958f0 100644 --- a/main.go +++ b/main.go @@ -201,6 +201,10 @@ func setupControllersAndWebhooks(mgr manager.Manager) error { return fmt.Errorf("failed to enable webhook server: %w", err) } + if err := setupConversionWebhooks(mgr); err != nil { + return fmt.Errorf("failed to setup conversion webhooks: %w", err) + } + if err := setupAdmissionsWebhooks(mgr); err != nil { return fmt.Errorf("failed to setup admission webhooks: %w", err) } @@ -394,23 +398,6 @@ func getImagesFromEnv() error { } func setupLogPipelineController(mgr manager.Manager, reconcileTriggerChan <-chan event.GenericEvent) error { - if featureflags.IsEnabled(featureflags.V1Beta1) { - setupLog.Info("Registering conversion webhooks for LogPipelines") - utilruntime.Must(telemetryv1beta1.AddToScheme(scheme)) - // Register conversion webhooks for LogPipelines - if err := ctrl.NewWebhookManagedBy(mgr). - For(&telemetryv1alpha1.LogPipeline{}). - Complete(); err != nil { - return fmt.Errorf("failed to create v1alpha1 conversion webhook: %w", err) - } - - if err := ctrl.NewWebhookManagedBy(mgr). - For(&telemetryv1beta1.LogPipeline{}). - Complete(); err != nil { - return fmt.Errorf("failed to create v1beta1 conversion webhook: %w", err) - } - } - setupLog.Info("Setting up logpipeline controller") logPipelineController, err := telemetrycontrollers.NewLogPipelineController( @@ -509,6 +496,41 @@ func setupMetricPipelineController(mgr manager.Manager, reconcileTriggerChan <-c return nil } +func setupConversionWebhooks(mgr manager.Manager) error { + if featureflags.IsEnabled(featureflags.V1Beta1) { + setupLog.Info("Registering conversion webhooks for LogPipelines") + utilruntime.Must(telemetryv1beta1.AddToScheme(scheme)) + + if err := ctrl.NewWebhookManagedBy(mgr). + For(&telemetryv1alpha1.LogPipeline{}). + Complete(); err != nil { + return fmt.Errorf("failed to create v1alpha1 conversion webhook: %w", err) + } + + if err := ctrl.NewWebhookManagedBy(mgr). + For(&telemetryv1beta1.LogPipeline{}). + Complete(); err != nil { + return fmt.Errorf("failed to create v1beta1 conversion webhook: %w", err) + } + + setupLog.Info("Registering conversion webhooks for MetricPipelines") + + if err := ctrl.NewWebhookManagedBy(mgr). + For(&telemetryv1alpha1.MetricPipeline{}). + Complete(); err != nil { + return fmt.Errorf("failed to create v1alpha1 conversion webhook: %w", err) + } + + if err := ctrl.NewWebhookManagedBy(mgr). + For(&telemetryv1beta1.MetricPipeline{}). + Complete(); err != nil { + return fmt.Errorf("failed to create v1beta1 conversion webhook: %w", err) + } + } + + return nil +} + func ensureWebhookCert(mgr manager.Manager, webhookConfig telemetry.WebhookConfig) error { // Create own client since manager might not be started while using clientOptions := client.Options{ diff --git a/test/e2e/logs/misc/version_conversion_test.go b/test/e2e/logs/misc/version_conversion_test.go index 264f20383a..65d1b2f719 100644 --- a/test/e2e/logs/misc/version_conversion_test.go +++ b/test/e2e/logs/misc/version_conversion_test.go @@ -57,7 +57,7 @@ func TestVersionConversion(t *testing.T) { Port: "443", URI: "/", TLSConfig: telemetryv1beta1.OutputTLS{ - Disabled: true, + Insecure: true, }, }, }, diff --git a/test/e2e/logs/shared/single_pipeline_v1beta1_test.go b/test/e2e/logs/shared/single_pipeline_v1beta1_test.go index 7a46cc8299..71a474523d 100644 --- a/test/e2e/logs/shared/single_pipeline_v1beta1_test.go +++ b/test/e2e/logs/shared/single_pipeline_v1beta1_test.go @@ -71,8 +71,8 @@ func TestSinglePipelineV1Beta1_OTel(t *testing.T) { }, Protocol: telemetryv1beta1.OTLPProtocolGRPC, TLS: &telemetryv1beta1.OutputTLS{ - Disabled: true, - SkipCertificateValidation: true, + Insecure: true, + InsecureSkipVerify: true, }, }, }, @@ -92,6 +92,7 @@ func TestSinglePipelineV1Beta1_OTel(t *testing.T) { }) Expect(kitk8s.CreateObjects(t, resources...)).To(Succeed()) + assert.OTelLogPipelineHealthy(t, pipelineName) assert.BackendReachable(t, backend) assert.DeploymentReady(t, kitkyma.LogGatewayName) @@ -99,7 +100,6 @@ func TestSinglePipelineV1Beta1_OTel(t *testing.T) { assert.DaemonSetReady(t, kitkyma.LogAgentName) } - assert.OTelLogPipelineHealthy(t, pipelineName) assert.OTelLogsFromNamespaceDelivered(t, backend, genNs) }) } @@ -130,8 +130,8 @@ func TestSinglePipelineV1Beta1_FluentBit(t *testing.T) { Port: strconv.Itoa(int(backend.Port())), URI: "/", TLSConfig: telemetryv1beta1.OutputTLS{ - Disabled: true, - SkipCertificateValidation: true, + Insecure: true, + InsecureSkipVerify: true, }, }, }, diff --git a/test/e2e/metrics/shared/single_pipeline_v1beta1_test.go b/test/e2e/metrics/shared/single_pipeline_v1beta1_test.go index 68f69ceb4e..8b7d0fdf99 100644 --- a/test/e2e/metrics/shared/single_pipeline_v1beta1_test.go +++ b/test/e2e/metrics/shared/single_pipeline_v1beta1_test.go @@ -46,9 +46,7 @@ func TestSinglePipelineV1Beta1(t *testing.T) { { label: suite.LabelMetricGatewaySetC, input: telemetryv1beta1.MetricPipelineInput{ - OTLP: &telemetryv1beta1.OTLPInput{ - Disabled: false, - }, + OTLP: &telemetryv1beta1.OTLPInput{}, }, generatorBuilder: func(ns string) []client.Object { return []client.Object{ diff --git a/webhook/logpipeline/v1alpha1/defaulter.go b/webhook/logpipeline/v1alpha1/defaulter.go index a285d57700..5696bbf5fa 100644 --- a/webhook/logpipeline/v1alpha1/defaulter.go +++ b/webhook/logpipeline/v1alpha1/defaulter.go @@ -46,7 +46,21 @@ func (ld defaulter) applyDefaults(pipeline *telemetryv1alpha1.LogPipeline) { pipeline.Spec.Input.Application.KeepOriginalBody = &ld.ApplicationInputKeepOriginalBody } + if isOTLPPipeline(pipeline) { + if pipeline.Spec.Input.OTLP == nil { + pipeline.Spec.Input.OTLP = &telemetryv1alpha1.OTLPInput{} + } + + if pipeline.Spec.Input.OTLP.Namespaces == nil { + pipeline.Spec.Input.OTLP.Namespaces = &telemetryv1alpha1.NamespaceSelector{} + } + } + if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { pipeline.Spec.Output.OTLP.Protocol = ld.DefaultOTLPProtocol } } + +func isOTLPPipeline(pipeline *telemetryv1alpha1.LogPipeline) bool { + return pipeline.Spec.Output.OTLP != nil +} diff --git a/webhook/logpipeline/v1alpha1/defaulter_test.go b/webhook/logpipeline/v1alpha1/defaulter_test.go index a1fc277743..e149911b2d 100644 --- a/webhook/logpipeline/v1alpha1/defaulter_test.go +++ b/webhook/logpipeline/v1alpha1/defaulter_test.go @@ -26,6 +26,11 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.LogPipeline{ Spec: telemetryv1alpha1.LogPipelineSpec{ Input: telemetryv1alpha1.LogPipelineInput{}, + Output: telemetryv1alpha1.LogPipelineOutput{ + HTTP: &telemetryv1alpha1.LogPipelineHTTPOutput{ + Host: telemetryv1alpha1.ValueType{Value: "example.com"}, + }, + }, }, }, expected: &telemetryv1alpha1.LogPipeline{ @@ -36,6 +41,11 @@ func TestDefault(t *testing.T) { KeepOriginalBody: ptr.To(true), }, }, + Output: telemetryv1alpha1.LogPipelineOutput{ + HTTP: &telemetryv1alpha1.LogPipelineHTTPOutput{ + Host: telemetryv1alpha1.ValueType{Value: "example.com"}, + }, + }, }, }, }, @@ -83,6 +93,79 @@ func TestDefault(t *testing.T) { }, }, }, + { + name: "should set empty namespaces for OTLP input if not set", + input: &telemetryv1alpha1.LogPipeline{ + Spec: telemetryv1alpha1.LogPipelineSpec{ + Input: telemetryv1alpha1.LogPipelineInput{}, + Output: telemetryv1alpha1.LogPipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Endpoint: telemetryv1alpha1.ValueType{Value: "otlp.example.com:4317"}, + }, + }, + }, + }, + expected: &telemetryv1alpha1.LogPipeline{ + Spec: telemetryv1alpha1.LogPipelineSpec{ + Input: telemetryv1alpha1.LogPipelineInput{ + Application: &telemetryv1alpha1.LogPipelineApplicationInput{ + Enabled: ptr.To(true), + KeepOriginalBody: ptr.To(true), + }, + OTLP: &telemetryv1alpha1.OTLPInput{ + Disabled: false, + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, + }, + Output: telemetryv1alpha1.LogPipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Endpoint: telemetryv1alpha1.ValueType{Value: "otlp.example.com:4317"}, + Protocol: "grpc", + }, + }, + }, + }, + }, + { + name: "should not set empty namespaces for OTLP input if set", + input: &telemetryv1alpha1.LogPipeline{ + Spec: telemetryv1alpha1.LogPipelineSpec{ + Input: telemetryv1alpha1.LogPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{ + Include: []string{"custom-namespace"}, + }, + }, + }, + Output: telemetryv1alpha1.LogPipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Endpoint: telemetryv1alpha1.ValueType{Value: "otlp.example.com:4317"}, + }, + }, + }, + }, + expected: &telemetryv1alpha1.LogPipeline{ + Spec: telemetryv1alpha1.LogPipelineSpec{ + Input: telemetryv1alpha1.LogPipelineInput{ + Application: &telemetryv1alpha1.LogPipelineApplicationInput{ + Enabled: ptr.To(true), + KeepOriginalBody: ptr.To(true), + }, + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{ + Include: []string{"custom-namespace"}, + }, + }, + }, + Output: telemetryv1alpha1.LogPipelineOutput{ + OTLP: &telemetryv1alpha1.OTLPOutput{ + Endpoint: telemetryv1alpha1.ValueType{Value: "otlp.example.com:4317"}, + Protocol: "grpc", + }, + }, + }, + }, + }, { name: "should set default OTLP protocol if not set", input: &telemetryv1alpha1.LogPipeline{ @@ -99,6 +182,9 @@ func TestDefault(t *testing.T) { Enabled: ptr.To(true), KeepOriginalBody: ptr.To(true), }, + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, }, Output: telemetryv1alpha1.LogPipelineOutput{ OTLP: &telemetryv1alpha1.OTLPOutput{ diff --git a/webhook/logpipeline/v1beta1/defaulter.go b/webhook/logpipeline/v1beta1/defaulter.go index dccf234e51..11a1364f83 100644 --- a/webhook/logpipeline/v1beta1/defaulter.go +++ b/webhook/logpipeline/v1beta1/defaulter.go @@ -5,6 +5,7 @@ import ( "fmt" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/webhook" telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" @@ -14,9 +15,11 @@ import ( var _ webhook.CustomDefaulter = &defaulter{} type defaulter struct { + ExcludeNamespaces []string RuntimeInputEnabled bool RuntimeInputKeepOriginalBody bool DefaultOTLPOutputProtocol telemetryv1beta1.OTLPProtocol + OTLPInputEnabled bool } func (ld defaulter) Default(ctx context.Context, obj runtime.Object) error { @@ -31,17 +34,48 @@ func (ld defaulter) Default(ctx context.Context, obj runtime.Object) error { } func (ld defaulter) 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 == nil { + pipeline.Spec.Input.Runtime = &telemetryv1beta1.LogPipelineRuntimeInput{ + Enabled: &ld.RuntimeInputEnabled, + KeepOriginalBody: &ld.RuntimeInputKeepOriginalBody, } + } + + if pipeline.Spec.Input.Runtime.Enabled == nil { + pipeline.Spec.Input.Runtime.Enabled = &ld.RuntimeInputEnabled + } - if *pipeline.Spec.Input.Runtime.Enabled && pipeline.Spec.Input.Runtime.KeepOriginalBody == nil { - pipeline.Spec.Input.Runtime.KeepOriginalBody = &ld.RuntimeInputKeepOriginalBody + if *pipeline.Spec.Input.Runtime.Enabled && pipeline.Spec.Input.Runtime.KeepOriginalBody == nil { + pipeline.Spec.Input.Runtime.KeepOriginalBody = &ld.RuntimeInputKeepOriginalBody + } + + if *pipeline.Spec.Input.Runtime.Enabled && pipeline.Spec.Input.Runtime.Namespaces == nil { + pipeline.Spec.Input.Runtime.Namespaces = &telemetryv1beta1.NamespaceSelector{ + Exclude: ld.ExcludeNamespaces, } } if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { pipeline.Spec.Output.OTLP.Protocol = ld.DefaultOTLPOutputProtocol } + + if isOTLPPipeline(pipeline) { + if pipeline.Spec.Input.OTLP == nil { + pipeline.Spec.Input.OTLP = &telemetryv1beta1.OTLPInput{} + } + + if pipeline.Spec.Input.OTLP.Enabled == nil { + pipeline.Spec.Input.OTLP.Enabled = &ld.OTLPInputEnabled + } + + if ptr.Deref(pipeline.Spec.Input.OTLP.Enabled, false) && pipeline.Spec.Input.OTLP.Namespaces == nil { + pipeline.Spec.Input.OTLP.Namespaces = &telemetryv1beta1.NamespaceSelector{ + Exclude: ld.ExcludeNamespaces, + } + } + } +} + +func isOTLPPipeline(pipeline *telemetryv1beta1.LogPipeline) bool { + return pipeline.Spec.Output.OTLP != nil } diff --git a/webhook/logpipeline/v1beta1/defaulter_test.go b/webhook/logpipeline/v1beta1/defaulter_test.go index c34ffcde1c..5f26bdb013 100644 --- a/webhook/logpipeline/v1beta1/defaulter_test.go +++ b/webhook/logpipeline/v1beta1/defaulter_test.go @@ -7,13 +7,16 @@ import ( "k8s.io/utils/ptr" telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" + "github.com/kyma-project/telemetry-manager/internal/namespaces" ) func TestDefault(t *testing.T) { sut := defaulter{ + ExcludeNamespaces: namespaces.System(), RuntimeInputEnabled: true, RuntimeInputKeepOriginalBody: true, DefaultOTLPOutputProtocol: telemetryv1beta1.OTLPProtocolGRPC, + OTLPInputEnabled: true, } tests := []struct { @@ -28,6 +31,13 @@ func TestDefault(t *testing.T) { Input: telemetryv1beta1.LogPipelineInput{ Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{}, }, + Output: telemetryv1beta1.LogPipelineOutput{ + HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: telemetryv1beta1.ValueType{ + Value: "localhost:4317", + }, + }, + }, }, }, expected: &telemetryv1beta1.LogPipeline{ @@ -36,6 +46,16 @@ func TestDefault(t *testing.T) { Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ Enabled: ptr.To(true), KeepOriginalBody: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: namespaces.System(), + }, + }, + }, + Output: telemetryv1beta1.LogPipelineOutput{ + HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: telemetryv1beta1.ValueType{ + Value: "localhost:4317", + }, }, }, }, @@ -50,6 +70,13 @@ func TestDefault(t *testing.T) { KeepOriginalBody: ptr.To(false), }, }, + Output: telemetryv1beta1.LogPipelineOutput{ + HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: telemetryv1beta1.ValueType{ + Value: "localhost:4317", + }, + }, + }, }, }, expected: &telemetryv1beta1.LogPipeline{ @@ -58,6 +85,16 @@ func TestDefault(t *testing.T) { Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ Enabled: ptr.To(true), KeepOriginalBody: ptr.To(false), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: namespaces.System(), + }, + }, + }, + Output: telemetryv1beta1.LogPipelineOutput{ + HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: telemetryv1beta1.ValueType{ + Value: "localhost:4317", + }, }, }, }, @@ -72,6 +109,13 @@ func TestDefault(t *testing.T) { Enabled: ptr.To(false), }, }, + Output: telemetryv1beta1.LogPipelineOutput{ + HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: telemetryv1beta1.ValueType{ + Value: "localhost:4317", + }, + }, + }, }, }, expected: &telemetryv1beta1.LogPipeline{ @@ -81,11 +125,18 @@ func TestDefault(t *testing.T) { Enabled: ptr.To(false), }, }, + Output: telemetryv1beta1.LogPipelineOutput{ + HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: telemetryv1beta1.ValueType{ + Value: "localhost:4317", + }, + }, + }, }, }, }, { - name: "should set default OTLPOutput if not set", + name: "should set default OTLPOutput protocol and OTLP Input namespaces if not set", input: &telemetryv1beta1.LogPipeline{ Spec: telemetryv1beta1.LogPipelineSpec{ Output: telemetryv1beta1.LogPipelineOutput{ @@ -95,6 +146,21 @@ func TestDefault(t *testing.T) { }, expected: &telemetryv1beta1.LogPipeline{ Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Enabled: ptr.To(true), + KeepOriginalBody: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: namespaces.System(), + }, + }, + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: namespaces.System(), + }, + }, + }, Output: telemetryv1beta1.LogPipelineOutput{ OTLP: &telemetryv1beta1.OTLPOutput{ Protocol: telemetryv1beta1.OTLPProtocolGRPC, @@ -103,6 +169,88 @@ func TestDefault(t *testing.T) { }, }, }, + { + name: "should enable otlp input by default for OTLP output pipelines but do not override existing settings", + input: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Enabled: ptr.To(false), + }, + OTLP: &telemetryv1beta1.OTLPInput{ + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: []string{"custom-namespace"}, + }, + }, + }, + Output: telemetryv1beta1.LogPipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Endpoint: telemetryv1beta1.ValueType{ + Value: "localhost:4317", + }, + Protocol: telemetryv1beta1.OTLPProtocolGRPC, + }, + }, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Enabled: ptr.To(false), + }, + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: []string{"custom-namespace"}, + }, + }, + }, + Output: telemetryv1beta1.LogPipelineOutput{ + OTLP: &telemetryv1beta1.OTLPOutput{ + Endpoint: telemetryv1beta1.ValueType{ + Value: "localhost:4317", + }, + Protocol: telemetryv1beta1.OTLPProtocolGRPC, + }, + }, + }, + }, + }, + { + name: "should not activate otlp input by default for non-OTLP output pipelines, but runtime input", + input: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Output: telemetryv1beta1.LogPipelineOutput{ + HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: telemetryv1beta1.ValueType{ + Value: "localhost", + }, + }, + }, + }, + }, + expected: &telemetryv1beta1.LogPipeline{ + Spec: telemetryv1beta1.LogPipelineSpec{ + Input: telemetryv1beta1.LogPipelineInput{ + Runtime: &telemetryv1beta1.LogPipelineRuntimeInput{ + Enabled: ptr.To(true), + KeepOriginalBody: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: namespaces.System(), + }, + }, + }, + Output: telemetryv1beta1.LogPipelineOutput{ + HTTP: &telemetryv1beta1.LogPipelineHTTPOutput{ + Host: telemetryv1beta1.ValueType{ + Value: "localhost", + }, + }, + }, + }, + }, + }, } for _, tt := range tests { diff --git a/webhook/logpipeline/v1beta1/setup.go b/webhook/logpipeline/v1beta1/setup.go index 1511888999..d63cef6927 100644 --- a/webhook/logpipeline/v1beta1/setup.go +++ b/webhook/logpipeline/v1beta1/setup.go @@ -4,14 +4,17 @@ import ( ctrl "sigs.k8s.io/controller-runtime" telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" + "github.com/kyma-project/telemetry-manager/internal/namespaces" ) func SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr).For(&telemetryv1beta1.LogPipeline{}). WithDefaulter(&defaulter{ + ExcludeNamespaces: namespaces.System(), RuntimeInputEnabled: true, RuntimeInputKeepOriginalBody: true, DefaultOTLPOutputProtocol: telemetryv1beta1.OTLPProtocolGRPC, + OTLPInputEnabled: true, }). Complete() } diff --git a/webhook/metricpipeline/v1alpha1/defaulter.go b/webhook/metricpipeline/v1alpha1/defaulter.go index 1bb6308216..86d2124f7a 100644 --- a/webhook/metricpipeline/v1alpha1/defaulter.go +++ b/webhook/metricpipeline/v1alpha1/defaulter.go @@ -45,48 +45,60 @@ func (md defaulter) Default(ctx context.Context, obj runtime.Object) error { } func (md defaulter) applyDefaults(pipeline *telemetryv1alpha1.MetricPipeline) { - if metricpipelineutils.IsPrometheusInputEnabled(pipeline.Spec.Input) && pipeline.Spec.Input.Prometheus.Namespaces == nil { - pipeline.Spec.Input.Prometheus.Namespaces = &telemetryv1alpha1.NamespaceSelector{ - Exclude: md.ExcludeNamespaces, + if metricpipelineutils.IsPrometheusInputEnabled(pipeline.Spec.Input) { + if pipeline.Spec.Input.Prometheus.Namespaces == nil { + pipeline.Spec.Input.Prometheus.Namespaces = &telemetryv1alpha1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } } - } - if metricpipelineutils.IsIstioInputEnabled(pipeline.Spec.Input) && pipeline.Spec.Input.Istio.Namespaces == nil { - pipeline.Spec.Input.Istio.Namespaces = &telemetryv1alpha1.NamespaceSelector{ - Exclude: md.ExcludeNamespaces, + if pipeline.Spec.Input.Prometheus.DiagnosticMetrics == nil { + pipeline.Spec.Input.Prometheus.DiagnosticMetrics = &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: &md.DiagnosticMetricsEnabled, + } } } - if metricpipelineutils.IsRuntimeInputEnabled(pipeline.Spec.Input) && pipeline.Spec.Input.Runtime.Namespaces == nil { - pipeline.Spec.Input.Runtime.Namespaces = &telemetryv1alpha1.NamespaceSelector{ - Exclude: md.ExcludeNamespaces, + if metricpipelineutils.IsIstioInputEnabled(pipeline.Spec.Input) { + if pipeline.Spec.Input.Istio.Namespaces == nil { + pipeline.Spec.Input.Istio.Namespaces = &telemetryv1alpha1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } + } + + if pipeline.Spec.Input.Istio.DiagnosticMetrics == nil { + pipeline.Spec.Input.Istio.DiagnosticMetrics = &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: &md.DiagnosticMetricsEnabled, + } + } + + if pipeline.Spec.Input.Istio.EnvoyMetrics == nil { + pipeline.Spec.Input.Istio.EnvoyMetrics = &telemetryv1alpha1.EnvoyMetrics{ + Enabled: &md.EnvoyMetricsEnabled, + } } } if metricpipelineutils.IsRuntimeInputEnabled(pipeline.Spec.Input) { md.applyRuntimeInputResourceDefaults(pipeline) - } - if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { - pipeline.Spec.Output.OTLP.Protocol = md.DefaultOTLPOutputProtocol + if pipeline.Spec.Input.Runtime.Namespaces == nil { + pipeline.Spec.Input.Runtime.Namespaces = &telemetryv1alpha1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } + } } - if metricpipelineutils.IsIstioInputEnabled(pipeline.Spec.Input) && pipeline.Spec.Input.Istio.DiagnosticMetrics == nil { - pipeline.Spec.Input.Istio.DiagnosticMetrics = &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{ - Enabled: &md.DiagnosticMetricsEnabled, - } + if pipeline.Spec.Input.OTLP == nil { + pipeline.Spec.Input.OTLP = &telemetryv1alpha1.OTLPInput{} } - if metricpipelineutils.IsIstioInputEnabled(pipeline.Spec.Input) && pipeline.Spec.Input.Istio.EnvoyMetrics == nil { - pipeline.Spec.Input.Istio.EnvoyMetrics = &telemetryv1alpha1.EnvoyMetrics{ - Enabled: &md.EnvoyMetricsEnabled, - } + if pipeline.Spec.Input.OTLP.Namespaces == nil { + pipeline.Spec.Input.OTLP.Namespaces = &telemetryv1alpha1.NamespaceSelector{} } - if metricpipelineutils.IsPrometheusInputEnabled(pipeline.Spec.Input) && pipeline.Spec.Input.Prometheus.DiagnosticMetrics == nil { - pipeline.Spec.Input.Prometheus.DiagnosticMetrics = &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{ - Enabled: &md.DiagnosticMetricsEnabled, - } + if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { + pipeline.Spec.Output.OTLP.Protocol = md.DefaultOTLPOutputProtocol } } diff --git a/webhook/metricpipeline/v1alpha1/defaulter_test.go b/webhook/metricpipeline/v1alpha1/defaulter_test.go index d922ecd737..76212d1ae1 100644 --- a/webhook/metricpipeline/v1alpha1/defaulter_test.go +++ b/webhook/metricpipeline/v1alpha1/defaulter_test.go @@ -7,11 +7,12 @@ import ( "k8s.io/utils/ptr" telemetryv1alpha1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1alpha1" + "github.com/kyma-project/telemetry-manager/internal/namespaces" ) func TestDefault(t *testing.T) { sut := defaulter{ - ExcludeNamespaces: []string{"kyma-system", "kube-system", "istio-system"}, + ExcludeNamespaces: namespaces.System(), RuntimeInputResources: runtimeInputResourceDefaults{ Pod: true, Container: true, @@ -31,7 +32,7 @@ func TestDefault(t *testing.T) { expected *telemetryv1alpha1.MetricPipeline }{ { - name: "should set default OTLP protocol if not set", + name: "should set default OTLP protocol and OTLP Input if not set", input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Output: telemetryv1alpha1.MetricPipelineOutput{ @@ -41,6 +42,11 @@ func TestDefault(t *testing.T) { }, expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, + }, Output: telemetryv1alpha1.MetricPipelineOutput{ OTLP: &telemetryv1alpha1.OTLPOutput{ Protocol: telemetryv1alpha1.OTLPProtocolGRPC, @@ -53,6 +59,11 @@ func TestDefault(t *testing.T) { name: "should not override existing OTLP protocol", input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, + }, Output: telemetryv1alpha1.MetricPipelineOutput{ OTLP: &telemetryv1alpha1.OTLPOutput{ Protocol: telemetryv1alpha1.OTLPProtocolHTTP, @@ -62,6 +73,11 @@ func TestDefault(t *testing.T) { }, expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ + Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, + }, Output: telemetryv1alpha1.MetricPipelineOutput{ OTLP: &telemetryv1alpha1.OTLPOutput{ Protocol: telemetryv1alpha1.OTLPProtocolHTTP, @@ -75,6 +91,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), }, @@ -84,10 +103,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1alpha1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, DiagnosticMetrics: &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(false)}, }, @@ -100,6 +122,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ Enabled: ptr.To(true), }, @@ -109,10 +134,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1alpha1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, DiagnosticMetrics: &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(false)}, EnvoyMetrics: &telemetryv1alpha1.EnvoyMetrics{Enabled: ptr.To(false)}, @@ -127,6 +155,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{ Enabled: ptr.To(true), }, @@ -136,10 +167,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1alpha1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, Resources: &telemetryv1alpha1.MetricPipelineRuntimeInputResources{ Pod: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ @@ -185,6 +219,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{ Enabled: ptr.To(true), Resources: &telemetryv1alpha1.MetricPipelineRuntimeInputResources{ @@ -199,10 +236,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1alpha1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, Resources: &telemetryv1alpha1.MetricPipelineRuntimeInputResources{ Pod: &telemetryv1alpha1.MetricPipelineRuntimeInputResource{ @@ -247,6 +287,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{ Enabled: ptr.To(false), }, @@ -256,6 +299,9 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{ Enabled: ptr.To(false), }, @@ -277,6 +323,9 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ Enabled: ptr.To(false), }, @@ -289,6 +338,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{ Enabled: ptr.To(false), }, @@ -298,6 +350,9 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Runtime: &telemetryv1alpha1.MetricPipelineRuntimeInput{ Enabled: ptr.To(false), }, @@ -311,6 +366,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ Enabled: ptr.To(true), }, @@ -320,10 +378,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1alpha1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, DiagnosticMetrics: &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(false)}, EnvoyMetrics: &telemetryv1alpha1.EnvoyMetrics{Enabled: ptr.To(false)}, @@ -337,6 +398,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ Enabled: ptr.To(true), }, @@ -346,10 +410,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1alpha1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, DiagnosticMetrics: &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(false)}, EnvoyMetrics: &telemetryv1alpha1.EnvoyMetrics{Enabled: ptr.To(false)}, @@ -363,6 +430,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ Enabled: ptr.To(true), EnvoyMetrics: &telemetryv1alpha1.EnvoyMetrics{Enabled: ptr.To(true)}, @@ -373,10 +443,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Istio: &telemetryv1alpha1.MetricPipelineIstioInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1alpha1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, DiagnosticMetrics: &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(false)}, EnvoyMetrics: &telemetryv1alpha1.EnvoyMetrics{Enabled: ptr.To(true)}, @@ -390,6 +463,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), }, @@ -399,10 +475,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1alpha1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, DiagnosticMetrics: &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(false)}, }, @@ -415,6 +494,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), DiagnosticMetrics: &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(true)}, @@ -425,10 +507,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1alpha1.MetricPipeline{ Spec: telemetryv1alpha1.MetricPipelineSpec{ Input: telemetryv1alpha1.MetricPipelineInput{ + OTLP: &telemetryv1alpha1.OTLPInput{ + Namespaces: &telemetryv1alpha1.NamespaceSelector{}, + }, Prometheus: &telemetryv1alpha1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1alpha1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, DiagnosticMetrics: &telemetryv1alpha1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(true)}, }, diff --git a/webhook/metricpipeline/v1alpha1/setup.go b/webhook/metricpipeline/v1alpha1/setup.go index 54e812a475..7692f896fd 100644 --- a/webhook/metricpipeline/v1alpha1/setup.go +++ b/webhook/metricpipeline/v1alpha1/setup.go @@ -4,12 +4,13 @@ import ( ctrl "sigs.k8s.io/controller-runtime" telemetryv1alpha1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1alpha1" + "github.com/kyma-project/telemetry-manager/internal/namespaces" ) func SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr).For(&telemetryv1alpha1.MetricPipeline{}). WithDefaulter(&defaulter{ - ExcludeNamespaces: []string{"kyma-system", "kube-system", "istio-system"}, + ExcludeNamespaces: namespaces.System(), RuntimeInputResources: runtimeInputResourceDefaults{ Pod: true, Container: true, diff --git a/webhook/metricpipeline/v1beta1/defaulter.go b/webhook/metricpipeline/v1beta1/defaulter.go index cf4b7fef28..b40b843d33 100644 --- a/webhook/metricpipeline/v1beta1/defaulter.go +++ b/webhook/metricpipeline/v1beta1/defaulter.go @@ -5,6 +5,7 @@ import ( "fmt" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/webhook" telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" @@ -15,6 +16,7 @@ var _ webhook.CustomDefaulter = &defaulter{} type defaulter struct { ExcludeNamespaces []string + OTLPInputEnabled bool RuntimeInputResources runtimeInputResourceDefaults DefaultOTLPOutputProtocol telemetryv1beta1.OTLPProtocol DiagnosticMetricsEnabled bool @@ -44,48 +46,66 @@ func (md defaulter) Default(ctx context.Context, obj runtime.Object) error { } func (md defaulter) applyDefaults(pipeline *telemetryv1beta1.MetricPipeline) { - if prometheusInputEnabled(pipeline) && pipeline.Spec.Input.Prometheus.Namespaces == nil { - pipeline.Spec.Input.Prometheus.Namespaces = &telemetryv1beta1.NamespaceSelector{ - Exclude: md.ExcludeNamespaces, + if prometheusInputEnabled(pipeline) { + if pipeline.Spec.Input.Prometheus.Namespaces == nil { + pipeline.Spec.Input.Prometheus.Namespaces = &telemetryv1beta1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } } - } - if istioInputEnabled(pipeline) && pipeline.Spec.Input.Istio.Namespaces == nil { - pipeline.Spec.Input.Istio.Namespaces = &telemetryv1beta1.NamespaceSelector{ - Exclude: md.ExcludeNamespaces, + if pipeline.Spec.Input.Prometheus.DiagnosticMetrics == nil { + pipeline.Spec.Input.Prometheus.DiagnosticMetrics = &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: &md.DiagnosticMetricsEnabled, + } } } - if runtimeInputEnabled(pipeline) && pipeline.Spec.Input.Runtime.Namespaces == nil { - pipeline.Spec.Input.Runtime.Namespaces = &telemetryv1beta1.NamespaceSelector{ - Exclude: md.ExcludeNamespaces, + if istioInputEnabled(pipeline) { + if pipeline.Spec.Input.Istio.Namespaces == nil { + pipeline.Spec.Input.Istio.Namespaces = &telemetryv1beta1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, + } + } + + if pipeline.Spec.Input.Istio.EnvoyMetrics == nil { + pipeline.Spec.Input.Istio.EnvoyMetrics = &telemetryv1beta1.EnvoyMetrics{ + Enabled: &md.EnvoyMetricsEnabled, + } + } + + if pipeline.Spec.Input.Istio.DiagnosticMetrics == nil { + pipeline.Spec.Input.Istio.DiagnosticMetrics = &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{ + Enabled: &md.DiagnosticMetricsEnabled, + } } } if runtimeInputEnabled(pipeline) { md.applyRuntimeInputResourceDefaults(pipeline) + + if pipeline.Spec.Input.Runtime.Namespaces == nil { + pipeline.Spec.Input.Runtime.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.OTLP == nil { + pipeline.Spec.Input.OTLP = &telemetryv1beta1.OTLPInput{} } - if istioInputEnabled(pipeline) && pipeline.Spec.Input.Istio.EnvoyMetrics == nil { - pipeline.Spec.Input.Istio.EnvoyMetrics = &telemetryv1beta1.EnvoyMetrics{ - Enabled: &md.EnvoyMetricsEnabled, - } + if pipeline.Spec.Input.OTLP.Enabled == nil { + pipeline.Spec.Input.OTLP.Enabled = &md.OTLPInputEnabled } - if istioInputEnabled(pipeline) && pipeline.Spec.Input.Istio.DiagnosticMetrics == nil { - pipeline.Spec.Input.Istio.DiagnosticMetrics = &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{ - Enabled: &md.DiagnosticMetricsEnabled, + if ptr.Deref(pipeline.Spec.Input.OTLP.Enabled, false) && pipeline.Spec.Input.OTLP.Namespaces == nil { + pipeline.Spec.Input.OTLP.Namespaces = &telemetryv1beta1.NamespaceSelector{ + Exclude: md.ExcludeNamespaces, } } - if prometheusInputEnabled(pipeline) && pipeline.Spec.Input.Prometheus.DiagnosticMetrics == nil { - pipeline.Spec.Input.Prometheus.DiagnosticMetrics = &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{ - Enabled: &md.DiagnosticMetricsEnabled, - } + if pipeline.Spec.Output.OTLP != nil && pipeline.Spec.Output.OTLP.Protocol == "" { + pipeline.Spec.Output.OTLP.Protocol = md.DefaultOTLPOutputProtocol } } diff --git a/webhook/metricpipeline/v1beta1/defaulter_test.go b/webhook/metricpipeline/v1beta1/defaulter_test.go index 40b438de9a..34afb66792 100644 --- a/webhook/metricpipeline/v1beta1/defaulter_test.go +++ b/webhook/metricpipeline/v1beta1/defaulter_test.go @@ -7,11 +7,13 @@ import ( "k8s.io/utils/ptr" telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" + "github.com/kyma-project/telemetry-manager/internal/namespaces" ) func TestDefault(t *testing.T) { sut := defaulter{ - ExcludeNamespaces: []string{"kyma-system", "kube-system", "istio-system"}, + ExcludeNamespaces: namespaces.System(), + OTLPInputEnabled: true, RuntimeInputResources: runtimeInputResourceDefaults{ Pod: true, Container: true, @@ -31,7 +33,7 @@ func TestDefault(t *testing.T) { expected *telemetryv1beta1.MetricPipeline }{ { - name: "should set default OTLP protocol if not set", + name: "should set default OTLP protocol and otlp input if not set", input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Output: telemetryv1beta1.MetricPipelineOutput{ @@ -41,6 +43,14 @@ func TestDefault(t *testing.T) { }, expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: namespaces.System(), + }, + }, + }, Output: telemetryv1beta1.MetricPipelineOutput{ OTLP: &telemetryv1beta1.OTLPOutput{ Protocol: telemetryv1beta1.OTLPProtocolGRPC, @@ -53,6 +63,11 @@ func TestDefault(t *testing.T) { name: "should not override existing OTLP protocol", input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, + }, Output: telemetryv1beta1.MetricPipelineOutput{ OTLP: &telemetryv1beta1.OTLPOutput{ Protocol: telemetryv1beta1.OTLPProtocolHTTP, @@ -62,6 +77,11 @@ func TestDefault(t *testing.T) { }, expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, + }, Output: telemetryv1beta1.MetricPipelineOutput{ OTLP: &telemetryv1beta1.OTLPOutput{ Protocol: telemetryv1beta1.OTLPProtocolHTTP, @@ -75,6 +95,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Prometheus: &telemetryv1beta1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), }, @@ -84,10 +107,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Prometheus: &telemetryv1beta1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1beta1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, DiagnosticMetrics: &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{ Enabled: ptr.To(false), @@ -102,6 +128,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Istio: &telemetryv1beta1.MetricPipelineIstioInput{ Enabled: ptr.To(true), }, @@ -111,10 +140,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Istio: &telemetryv1beta1.MetricPipelineIstioInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1beta1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, EnvoyMetrics: &telemetryv1beta1.EnvoyMetrics{ Enabled: ptr.To(false), @@ -133,6 +165,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ Enabled: ptr.To(true), }, @@ -142,10 +177,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1beta1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, Resources: &telemetryv1beta1.MetricPipelineRuntimeInputResources{ Pod: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ @@ -191,6 +229,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ Enabled: ptr.To(true), Resources: &telemetryv1beta1.MetricPipelineRuntimeInputResources{ @@ -205,10 +246,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1beta1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, Resources: &telemetryv1beta1.MetricPipelineRuntimeInputResources{ Pod: &telemetryv1beta1.MetricPipelineRuntimeInputResource{ @@ -253,6 +297,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Prometheus: &telemetryv1beta1.MetricPipelinePrometheusInput{ Enabled: ptr.To(false), }, @@ -262,6 +309,9 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Prometheus: &telemetryv1beta1.MetricPipelinePrometheusInput{ Enabled: ptr.To(false), }, @@ -269,11 +319,30 @@ func TestDefault(t *testing.T) { }, }, }, + { + name: "should enable otlp input by default", + input: &telemetryv1beta1.MetricPipeline{}, + expected: &telemetryv1beta1.MetricPipeline{ + Spec: telemetryv1beta1.MetricPipelineSpec{ + Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(true), + Namespaces: &telemetryv1beta1.NamespaceSelector{ + Exclude: namespaces.System(), + }, + }, + }, + }, + }, + }, { name: "should not set defaults for Istio input", input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Istio: &telemetryv1beta1.MetricPipelineIstioInput{ Enabled: ptr.To(false), }, @@ -283,6 +352,9 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Istio: &telemetryv1beta1.MetricPipelineIstioInput{ Enabled: ptr.To(false), }, @@ -295,6 +367,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ Enabled: ptr.To(false), }, @@ -304,6 +379,9 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Runtime: &telemetryv1beta1.MetricPipelineRuntimeInput{ Enabled: ptr.To(false), }, @@ -316,6 +394,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Istio: &telemetryv1beta1.MetricPipelineIstioInput{ Enabled: ptr.To(true), EnvoyMetrics: &telemetryv1beta1.EnvoyMetrics{ @@ -328,10 +409,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Istio: &telemetryv1beta1.MetricPipelineIstioInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1beta1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, EnvoyMetrics: &telemetryv1beta1.EnvoyMetrics{ Enabled: ptr.To(true), @@ -349,6 +433,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Istio: &telemetryv1beta1.MetricPipelineIstioInput{ Enabled: ptr.To(true), DiagnosticMetrics: &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(true)}, @@ -359,10 +446,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Istio: &telemetryv1beta1.MetricPipelineIstioInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1beta1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, EnvoyMetrics: &telemetryv1beta1.EnvoyMetrics{ Enabled: ptr.To(false), @@ -380,6 +470,9 @@ func TestDefault(t *testing.T) { input: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Prometheus: &telemetryv1beta1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), DiagnosticMetrics: &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(true)}, @@ -390,10 +483,13 @@ func TestDefault(t *testing.T) { expected: &telemetryv1beta1.MetricPipeline{ Spec: telemetryv1beta1.MetricPipelineSpec{ Input: telemetryv1beta1.MetricPipelineInput{ + OTLP: &telemetryv1beta1.OTLPInput{ + Enabled: ptr.To(false), + }, Prometheus: &telemetryv1beta1.MetricPipelinePrometheusInput{ Enabled: ptr.To(true), Namespaces: &telemetryv1beta1.NamespaceSelector{ - Exclude: []string{"kyma-system", "kube-system", "istio-system"}, + Exclude: namespaces.System(), }, DiagnosticMetrics: &telemetryv1beta1.MetricPipelineIstioInputDiagnosticMetrics{Enabled: ptr.To(true)}, }, diff --git a/webhook/metricpipeline/v1beta1/setup.go b/webhook/metricpipeline/v1beta1/setup.go index 28eb52e1ff..6de041fd49 100644 --- a/webhook/metricpipeline/v1beta1/setup.go +++ b/webhook/metricpipeline/v1beta1/setup.go @@ -4,12 +4,13 @@ import ( ctrl "sigs.k8s.io/controller-runtime" telemetryv1beta1 "github.com/kyma-project/telemetry-manager/apis/telemetry/v1beta1" + "github.com/kyma-project/telemetry-manager/internal/namespaces" ) func SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr).For(&telemetryv1beta1.MetricPipeline{}). WithDefaulter(&defaulter{ - ExcludeNamespaces: []string{"kyma-system", "kube-system", "istio-system"}, + ExcludeNamespaces: namespaces.System(), RuntimeInputResources: runtimeInputResourceDefaults{ Pod: true, Container: true, @@ -20,6 +21,7 @@ func SetupWithManager(mgr ctrl.Manager) error { StatefulSet: true, Job: true, }, + OTLPInputEnabled: true, DefaultOTLPOutputProtocol: telemetryv1beta1.OTLPProtocolGRPC, DiagnosticMetricsEnabled: false, EnvoyMetricsEnabled: false,