From d8d16a62ac1ceb284061235e16751a43f8486a1d Mon Sep 17 00:00:00 2001
From: Pavol Loffay
Date: Tue, 5 Mar 2024 16:45:08 +0100
Subject: [PATCH] Add conversion from v1beta1 to v1alpha1 (#2706)
* Add conversion from v1beta1 to v1alpha1
Signed-off-by: Pavol Loffay
* Fix
Signed-off-by: Pavol Loffay
* Fix
Signed-off-by: Pavol Loffay
* Fix
Signed-off-by: Pavol Loffay
---------
Signed-off-by: Pavol Loffay
---
apis/v1alpha1/convert.go | 184 ++++++++++++++++++++-
apis/v1alpha1/convert_test.go | 297 ++++++++++++++++++++++++++++------
2 files changed, 432 insertions(+), 49 deletions(-)
diff --git a/apis/v1alpha1/convert.go b/apis/v1alpha1/convert.go
index 6428f12619..ea4d6913c3 100644
--- a/apis/v1alpha1/convert.go
+++ b/apis/v1alpha1/convert.go
@@ -35,7 +35,7 @@ func Tov1beta1(in OpenTelemetryCollector) (v1beta1.OpenTelemetryCollector, error
StatusReplicas: in.Status.Scale.StatusReplicas,
},
Version: in.Status.Version,
- Image: in.Spec.Image,
+ Image: in.Status.Image,
},
}
@@ -108,7 +108,7 @@ func Tov1beta1(in OpenTelemetryCollector) (v1beta1.OpenTelemetryCollector, error
out.Spec.OpenTelemetryCommonFields.InitContainers = copy.Spec.InitContainers
out.Spec.OpenTelemetryCommonFields.AdditionalContainers = copy.Spec.AdditionalContainers
- out.Spec.TargetAllocator = TargetAllocatorEmbedded(copy.Spec.TargetAllocator)
+ out.Spec.TargetAllocator = tov1beta1TA(copy.Spec.TargetAllocator)
out.Spec.Mode = v1beta1.Mode(copy.Spec.Mode)
out.Spec.UpgradeStrategy = v1beta1.UpgradeStrategy(copy.Spec.UpgradeStrategy)
@@ -132,6 +132,7 @@ func Tov1beta1(in OpenTelemetryCollector) (v1beta1.OpenTelemetryCollector, error
}
out.Spec.Observability.Metrics.EnableMetrics = copy.Spec.Observability.Metrics.EnableMetrics
+ out.Spec.Observability.Metrics.DisablePrometheusAnnotations = copy.Spec.Observability.Metrics.DisablePrometheusAnnotations
for _, cm := range copy.Spec.ConfigMaps {
out.Spec.ConfigMaps = append(out.Spec.ConfigMaps, v1beta1.ConfigMapsSpec{
@@ -146,7 +147,7 @@ func Tov1beta1(in OpenTelemetryCollector) (v1beta1.OpenTelemetryCollector, error
return out, nil
}
-func TargetAllocatorEmbedded(in OpenTelemetryTargetAllocator) v1beta1.TargetAllocatorEmbedded {
+func tov1beta1TA(in OpenTelemetryTargetAllocator) v1beta1.TargetAllocatorEmbedded {
out := v1beta1.TargetAllocatorEmbedded{}
out.Replicas = in.Replicas
out.NodeSelector = in.NodeSelector
@@ -184,3 +185,180 @@ func TargetAllocatorEmbedded(in OpenTelemetryTargetAllocator) v1beta1.TargetAllo
}
return out
}
+
+func tov1alpha1(in v1beta1.OpenTelemetryCollector) (*OpenTelemetryCollector, error) {
+ copy := in.DeepCopy()
+ configYaml, err := in.Spec.Config.Yaml()
+ if err != nil {
+ return nil, err
+ }
+
+ return &OpenTelemetryCollector{
+ ObjectMeta: copy.ObjectMeta,
+ Status: OpenTelemetryCollectorStatus{
+ Scale: ScaleSubresourceStatus{
+ Selector: in.Status.Scale.Selector,
+ Replicas: in.Status.Scale.Replicas,
+ StatusReplicas: in.Status.Scale.StatusReplicas,
+ },
+ Version: in.Status.Version,
+ Image: in.Status.Image,
+ },
+
+ Spec: OpenTelemetryCollectorSpec{
+ ManagementState: ManagementStateType(copy.Spec.ManagementState),
+ Resources: copy.Spec.Resources,
+ NodeSelector: copy.Spec.NodeSelector,
+ Args: copy.Spec.Args,
+ Replicas: copy.Spec.Replicas,
+ Autoscaler: tov1alpha1Autoscaler(copy.Spec.Autoscaler),
+ PodDisruptionBudget: tov1alpha1PodDisruptionBudget(copy.Spec.PodDisruptionBudget),
+ SecurityContext: copy.Spec.SecurityContext,
+ PodSecurityContext: copy.Spec.PodSecurityContext,
+ PodAnnotations: copy.Spec.PodAnnotations,
+ TargetAllocator: tov1alpha1TA(in.Spec.TargetAllocator),
+ Mode: Mode(copy.Spec.Mode),
+ ServiceAccount: copy.Spec.ServiceAccount,
+ Image: copy.Spec.Image,
+ UpgradeStrategy: UpgradeStrategy(copy.Spec.UpgradeStrategy),
+ ImagePullPolicy: copy.Spec.ImagePullPolicy,
+ Config: configYaml,
+ VolumeMounts: copy.Spec.VolumeMounts,
+ Ports: copy.Spec.Ports,
+ Env: copy.Spec.Env,
+ EnvFrom: copy.Spec.EnvFrom,
+ VolumeClaimTemplates: copy.Spec.VolumeClaimTemplates,
+ Tolerations: copy.Spec.Tolerations,
+ Volumes: copy.Spec.Volumes,
+ Ingress: Ingress{
+ Type: IngressType(copy.Spec.Ingress.Type),
+ RuleType: IngressRuleType(copy.Spec.Ingress.RuleType),
+ Hostname: copy.Spec.Ingress.Hostname,
+ Annotations: copy.Spec.Ingress.Annotations,
+ TLS: copy.Spec.Ingress.TLS,
+ IngressClassName: copy.Spec.Ingress.IngressClassName,
+ Route: OpenShiftRoute{
+ Termination: TLSRouteTerminationType(copy.Spec.Ingress.Route.Termination),
+ },
+ },
+ HostNetwork: copy.Spec.HostNetwork,
+ ShareProcessNamespace: copy.Spec.ShareProcessNamespace,
+ PriorityClassName: copy.Spec.PriorityClassName,
+ Affinity: copy.Spec.Affinity,
+ Lifecycle: copy.Spec.Lifecycle,
+ TerminationGracePeriodSeconds: copy.Spec.TerminationGracePeriodSeconds,
+ LivenessProbe: tov1alpha1Probe(copy.Spec.LivenessProbe),
+ InitContainers: copy.Spec.InitContainers,
+ AdditionalContainers: copy.Spec.AdditionalContainers,
+ Observability: ObservabilitySpec{
+ Metrics: MetricsConfigSpec{
+ EnableMetrics: copy.Spec.Observability.Metrics.EnableMetrics,
+ DisablePrometheusAnnotations: copy.Spec.Observability.Metrics.DisablePrometheusAnnotations,
+ },
+ },
+ TopologySpreadConstraints: copy.Spec.TopologySpreadConstraints,
+ ConfigMaps: tov1alpha1ConfigMaps(copy.Spec.ConfigMaps),
+ UpdateStrategy: copy.Spec.DaemonSetUpdateStrategy,
+ DeploymentUpdateStrategy: copy.Spec.DeploymentUpdateStrategy,
+ },
+ }, nil
+}
+
+func tov1alpha1PodDisruptionBudget(in *v1beta1.PodDisruptionBudgetSpec) *PodDisruptionBudgetSpec {
+ if in == nil {
+ return nil
+ }
+ return &PodDisruptionBudgetSpec{
+ MinAvailable: in.MinAvailable,
+ MaxUnavailable: in.MaxUnavailable,
+ }
+}
+
+func tov1alpha1Probe(in *v1beta1.Probe) *Probe {
+ if in == nil {
+ return nil
+ }
+ return &Probe{
+ InitialDelaySeconds: in.InitialDelaySeconds,
+ TimeoutSeconds: in.TimeoutSeconds,
+ PeriodSeconds: in.PeriodSeconds,
+ SuccessThreshold: in.SuccessThreshold,
+ FailureThreshold: in.FailureThreshold,
+ TerminationGracePeriodSeconds: in.TerminationGracePeriodSeconds,
+ }
+}
+
+func tov1alpha1Autoscaler(in *v1beta1.AutoscalerSpec) *AutoscalerSpec {
+ if in == nil {
+ return nil
+ }
+
+ var metrics []MetricSpec
+ for _, m := range in.Metrics {
+ metrics = append(metrics, MetricSpec{
+ Type: m.Type,
+ Pods: m.Pods,
+ })
+ }
+
+ return &AutoscalerSpec{
+ MinReplicas: in.MinReplicas,
+ MaxReplicas: in.MaxReplicas,
+ Behavior: in.Behavior,
+ Metrics: metrics,
+ TargetCPUUtilization: in.TargetCPUUtilization,
+ TargetMemoryUtilization: in.TargetMemoryUtilization,
+ }
+}
+
+func tov1alpha1ConfigMaps(in []v1beta1.ConfigMapsSpec) []ConfigMapsSpec {
+ var mapsSpecs []ConfigMapsSpec
+ for _, m := range in {
+ mapsSpecs = append(mapsSpecs, ConfigMapsSpec{
+ Name: m.Name,
+ MountPath: m.MountPath,
+ })
+ }
+ return mapsSpecs
+}
+
+func tov1alpha1TA(in v1beta1.TargetAllocatorEmbedded) OpenTelemetryTargetAllocator {
+ var podMonitorSelector map[string]string
+ if in.PrometheusCR.PodMonitorSelector != nil {
+ podMonitorSelector = in.PrometheusCR.PodMonitorSelector.MatchLabels
+ }
+ var serviceMonitorSelector map[string]string
+ if in.PrometheusCR.ServiceMonitorSelector != nil {
+ serviceMonitorSelector = in.PrometheusCR.ServiceMonitorSelector.MatchLabels
+ }
+
+ return OpenTelemetryTargetAllocator{
+ Replicas: in.Replicas,
+ NodeSelector: in.NodeSelector,
+ Resources: in.Resources,
+ AllocationStrategy: OpenTelemetryTargetAllocatorAllocationStrategy(in.AllocationStrategy),
+ FilterStrategy: string(in.FilterStrategy),
+ ServiceAccount: in.ServiceAccount,
+ Image: in.Image,
+ Enabled: in.Enabled,
+ Affinity: in.Affinity,
+ PrometheusCR: OpenTelemetryTargetAllocatorPrometheusCR{
+ Enabled: in.PrometheusCR.Enabled,
+ ScrapeInterval: in.PrometheusCR.ScrapeInterval,
+ PodMonitorSelector: podMonitorSelector,
+ ServiceMonitorSelector: serviceMonitorSelector,
+ },
+ SecurityContext: in.SecurityContext,
+ PodSecurityContext: in.PodSecurityContext,
+ TopologySpreadConstraints: in.TopologySpreadConstraints,
+ Tolerations: in.Tolerations,
+ Env: in.Env,
+ Observability: ObservabilitySpec{
+ Metrics: MetricsConfigSpec{
+ EnableMetrics: in.Observability.Metrics.EnableMetrics,
+ DisablePrometheusAnnotations: in.Observability.Metrics.DisablePrometheusAnnotations,
+ },
+ },
+ PodDisruptionBudget: tov1alpha1PodDisruptionBudget(in.PodDisruptionBudget),
+ }
+}
diff --git a/apis/v1alpha1/convert_test.go b/apis/v1alpha1/convert_test.go
index a63a32f79a..ad248d278b 100644
--- a/apis/v1alpha1/convert_test.go
+++ b/apis/v1alpha1/convert_test.go
@@ -19,8 +19,12 @@ import (
"time"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
+ appsv1 "k8s.io/api/apps/v1"
+ autoscalingv2 "k8s.io/api/autoscaling/v2"
v1 "k8s.io/api/core/v1"
+ networkingv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
@@ -28,9 +32,7 @@ import (
"github.com/open-telemetry/opentelemetry-operator/apis/v1beta1"
)
-func Test_V1Alpha1to2(t *testing.T) {
- t.Run("valid config", func(t *testing.T) {
- config := `---
+const collectorCfg = `---
receivers:
otlp:
protocols:
@@ -48,9 +50,12 @@ service:
processors: [resourcedetection]
exporters: [otlp]
`
+
+func Test_tov1beta1_config(t *testing.T) {
+ t.Run("valid config", func(t *testing.T) {
cfgV1 := OpenTelemetryCollector{
Spec: OpenTelemetryCollectorSpec{
- Config: config,
+ Config: collectorCfg,
Args: map[string]string{
"test": "something",
},
@@ -64,7 +69,7 @@ service:
yamlCfg, err := yaml.Marshal(&cfgV2.Spec.Config)
assert.Nil(t, err)
- assert.YAMLEq(t, config, string(yamlCfg))
+ assert.YAMLEq(t, collectorCfg, string(yamlCfg))
})
t.Run("invalid config", func(t *testing.T) {
config := `!!!`
@@ -79,13 +84,252 @@ service:
})
}
-func Test_TargetAllocator(t *testing.T) {
+func Test_tov1alpha1_config(t *testing.T) {
+ cfg := v1beta1.Config{}
+ err := yaml.Unmarshal([]byte(collectorCfg), &cfg)
+ require.NoError(t, err)
+
+ beta1Col := v1beta1.OpenTelemetryCollector{
+ Spec: v1beta1.OpenTelemetryCollectorSpec{
+ Config: cfg,
+ },
+ }
+ alpha1Col, err := tov1alpha1(beta1Col)
+ require.NoError(t, err)
+ assert.YAMLEq(t, collectorCfg, alpha1Col.Spec.Config)
+}
+
+func Test_tov1beta1AndBack(t *testing.T) {
+ one := int32(1)
+ two := int64(2)
+ intstrAAA := intstr.FromString("aaa")
+ boolTrue := true
+ ingressClass := "someClass"
+ colalpha1 := &OpenTelemetryCollector{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "otel",
+ Namespace: "observability",
+ Labels: map[string]string{"foo": "bar"},
+ Annotations: map[string]string{"bax": "foo"},
+ },
+ Spec: OpenTelemetryCollectorSpec{
+ ManagementState: ManagementStateManaged,
+ Resources: v1.ResourceRequirements{
+ Limits: v1.ResourceList{
+ v1.ResourceCPU: resource.MustParse("500m"),
+ v1.ResourceMemory: resource.MustParse("128Mi"),
+ },
+ Requests: v1.ResourceList{
+ v1.ResourceCPU: resource.MustParse("500m"),
+ v1.ResourceMemory: resource.MustParse("128Mi"),
+ },
+ },
+ NodeSelector: map[string]string{"aaa": "ccc"},
+ Args: map[string]string{"foo": "bar"},
+ Replicas: &one,
+ Autoscaler: &AutoscalerSpec{
+ MinReplicas: &one,
+ MaxReplicas: &one,
+ Behavior: &autoscalingv2.HorizontalPodAutoscalerBehavior{
+ ScaleUp: &autoscalingv2.HPAScalingRules{
+ Policies: []autoscalingv2.HPAScalingPolicy{
+ {
+ Type: "aaa",
+ Value: 2,
+ PeriodSeconds: 4,
+ },
+ },
+ },
+ },
+ Metrics: []MetricSpec{
+ {
+ Type: autoscalingv2.ContainerResourceMetricSourceType,
+ Pods: &autoscalingv2.PodsMetricSource{
+ Metric: autoscalingv2.MetricIdentifier{
+ Name: "rrrrt",
+ },
+ },
+ },
+ },
+ TargetCPUUtilization: &one,
+ TargetMemoryUtilization: &one,
+ },
+ PodDisruptionBudget: &PodDisruptionBudgetSpec{
+ MinAvailable: &intstrAAA,
+ MaxUnavailable: &intstrAAA,
+ },
+ SecurityContext: &v1.SecurityContext{
+ RunAsUser: &two,
+ },
+ PodSecurityContext: &v1.PodSecurityContext{
+ RunAsNonRoot: &boolTrue,
+ },
+ PodAnnotations: map[string]string{"foo": "bar"},
+ TargetAllocator: createTA(),
+ Mode: ModeDeployment,
+ ServiceAccount: "foo",
+ Image: "baz/bar:1.0",
+ UpgradeStrategy: UpgradeStrategyAutomatic,
+ ImagePullPolicy: v1.PullAlways,
+ Config: collectorCfg,
+ VolumeMounts: []v1.VolumeMount{
+ {
+ Name: "aaa",
+ },
+ },
+ Ports: []v1.ServicePort{
+ {
+ Name: "otlp",
+ },
+ },
+ Env: []v1.EnvVar{
+ {
+ Name: "foo",
+ Value: "bar",
+ ValueFrom: &v1.EnvVarSource{
+ ResourceFieldRef: &v1.ResourceFieldSelector{
+ ContainerName: "bbb",
+ Resource: "aaa",
+ Divisor: resource.Quantity{},
+ },
+ },
+ },
+ },
+ EnvFrom: []v1.EnvFromSource{
+ {
+ Prefix: "aa",
+ ConfigMapRef: &v1.ConfigMapEnvSource{
+ LocalObjectReference: v1.LocalObjectReference{
+ Name: "bbb",
+ },
+ },
+ },
+ },
+ VolumeClaimTemplates: []v1.PersistentVolumeClaim{
+ {
+ TypeMeta: metav1.TypeMeta{},
+ ObjectMeta: metav1.ObjectMeta{},
+ Spec: v1.PersistentVolumeClaimSpec{
+ VolumeName: "aaaa",
+ },
+ },
+ },
+ Tolerations: []v1.Toleration{
+ {
+ Key: "11",
+ Operator: "33",
+ Value: "44",
+ Effect: "55",
+ },
+ },
+ Volumes: []v1.Volume{
+ {
+ Name: "cfg",
+ VolumeSource: v1.VolumeSource{},
+ },
+ },
+ Ingress: Ingress{
+ Type: IngressTypeRoute,
+ RuleType: IngressRuleTypePath,
+ Hostname: "foo.com",
+ Annotations: map[string]string{"aa": "bb"},
+ TLS: []networkingv1.IngressTLS{
+ {
+ Hosts: []string{"foo"},
+ SecretName: "bar",
+ },
+ },
+ IngressClassName: &ingressClass,
+ Route: OpenShiftRoute{
+ Termination: TLSRouteTerminationTypeEdge,
+ },
+ },
+ HostNetwork: true,
+ ShareProcessNamespace: true,
+ PriorityClassName: "foobar",
+ Affinity: &v1.Affinity{
+ NodeAffinity: &v1.NodeAffinity{
+ PreferredDuringSchedulingIgnoredDuringExecution: []v1.PreferredSchedulingTerm{{
+ Weight: 444,
+ }},
+ },
+ },
+ Lifecycle: &v1.Lifecycle{
+ PostStart: &v1.LifecycleHandler{
+ Exec: &v1.ExecAction{
+ Command: []string{"/bin"},
+ },
+ },
+ },
+ TerminationGracePeriodSeconds: &two,
+ LivenessProbe: &Probe{
+ PeriodSeconds: &one,
+ },
+ InitContainers: []v1.Container{
+ {
+ Name: "init",
+ },
+ },
+ AdditionalContainers: []v1.Container{
+ {
+ Name: "some",
+ },
+ },
+ Observability: ObservabilitySpec{
+ Metrics: MetricsConfigSpec{
+ EnableMetrics: true,
+ DisablePrometheusAnnotations: true,
+ },
+ },
+ TopologySpreadConstraints: []v1.TopologySpreadConstraint{
+ {
+ TopologyKey: "key",
+ },
+ },
+ ConfigMaps: []ConfigMapsSpec{
+ {
+ Name: "aaa",
+ MountPath: "bbb",
+ },
+ },
+ UpdateStrategy: appsv1.DaemonSetUpdateStrategy{
+ Type: appsv1.RollingUpdateDaemonSetStrategyType,
+ },
+ DeploymentUpdateStrategy: appsv1.DeploymentStrategy{
+ Type: appsv1.RecreateDeploymentStrategyType,
+ },
+ },
+ Status: OpenTelemetryCollectorStatus{
+ Scale: ScaleSubresourceStatus{
+ Selector: "bar",
+ Replicas: 1,
+ StatusReplicas: "foo",
+ },
+ Version: "1.0",
+ Image: "foo/bar:1.0",
+ },
+ }
+
+ colbeta1, err := Tov1beta1(*colalpha1)
+ require.NoError(t, err)
+ colalpha1Converted, err := tov1alpha1(colbeta1)
+ require.NoError(t, err)
+
+ assert.YAMLEq(t, colalpha1.Spec.Config, colalpha1Converted.Spec.Config)
+
+ // empty the config to enable assertion on the entire objects
+ colalpha1.Spec.Config = ""
+ colalpha1Converted.Spec.Config = ""
+ assert.Equal(t, colalpha1, colalpha1Converted)
+}
+
+func createTA() OpenTelemetryTargetAllocator {
replicas := int32(2)
runAsNonRoot := true
privileged := true
runAsUser := int64(1337)
runasGroup := int64(1338)
- input := OpenTelemetryTargetAllocator{
+ return OpenTelemetryTargetAllocator{
Replicas: &replicas,
NodeSelector: map[string]string{"key": "value"},
Resources: v1.ResourceRequirements{
@@ -176,43 +420,4 @@ func Test_TargetAllocator(t *testing.T) {
},
},
}
-
- expected := v1beta1.TargetAllocatorEmbedded{
- Replicas: input.Replicas,
- NodeSelector: input.NodeSelector,
- Resources: input.Resources,
- AllocationStrategy: v1beta1.TargetAllocatorAllocationStrategyConsistentHashing,
- FilterStrategy: v1beta1.TargetAllocatorFilterStrategyRelabelConfig,
- ServiceAccount: input.ServiceAccount,
- Image: input.Image,
- Enabled: input.Enabled,
- Affinity: input.Affinity,
- PrometheusCR: v1beta1.TargetAllocatorPrometheusCR{
- Enabled: input.PrometheusCR.Enabled,
- ScrapeInterval: input.PrometheusCR.ScrapeInterval,
- PodMonitorSelector: &metav1.LabelSelector{
- MatchLabels: input.PrometheusCR.PodMonitorSelector,
- },
- ServiceMonitorSelector: &metav1.LabelSelector{
- MatchLabels: input.PrometheusCR.ServiceMonitorSelector,
- },
- },
- SecurityContext: input.SecurityContext,
- PodSecurityContext: input.PodSecurityContext,
- TopologySpreadConstraints: input.TopologySpreadConstraints,
- Tolerations: input.Tolerations,
- Env: input.Env,
- Observability: v1beta1.ObservabilitySpec{
- Metrics: v1beta1.MetricsConfigSpec{
- EnableMetrics: input.Observability.Metrics.EnableMetrics,
- DisablePrometheusAnnotations: input.Observability.Metrics.DisablePrometheusAnnotations,
- },
- },
- PodDisruptionBudget: &v1beta1.PodDisruptionBudgetSpec{
- MinAvailable: input.PodDisruptionBudget.MinAvailable,
- MaxUnavailable: input.PodDisruptionBudget.MaxUnavailable,
- },
- }
-
- assert.Equal(t, expected, TargetAllocatorEmbedded(input))
}