Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep multiple versions of Collector Config #2946

Merged
merged 20 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apis/v1beta1/opentelemetrycollector_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ type OpenTelemetryCollectorSpec struct {
// +required
// +kubebuilder:pruning:PreserveUnknownFields
Config Config `json:"config"`
// ConfigVersions defines the number versions to keep for the collector config. Each config version is stored in a separate ConfigMap.
// Defaults to 3. The minimum value is 1.
// +optional
// +kubebuilder:default:=3
matthagenbuch marked this conversation as resolved.
Show resolved Hide resolved
ConfigVersions *int32 `json:"configVersions,omitempty"`
swiatekm marked this conversation as resolved.
Show resolved Hide resolved
// Ingress is used to specify how OpenTelemetry Collector is exposed. This
// functionality is only available if one of the valid modes is set.
// Valid modes are: deployment, daemonset and statefulset.
Expand Down
5 changes: 5 additions & 0 deletions apis/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5555,6 +5555,10 @@ spec:
- service
type: object
x-kubernetes-preserve-unknown-fields: true
configVersions:
format: int32
type: integer
default: 3
configmaps:
items:
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5541,6 +5541,10 @@ spec:
- service
type: object
x-kubernetes-preserve-unknown-fields: true
configVersions:
default: 3
format: int32
type: integer
configmaps:
items:
properties:
Expand Down
39 changes: 24 additions & 15 deletions controllers/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/open-telemetry/opentelemetry-operator/internal/config"
"github.com/open-telemetry/opentelemetry-operator/internal/manifests"
"github.com/open-telemetry/opentelemetry-operator/internal/manifests/collector"
"github.com/open-telemetry/opentelemetry-operator/internal/manifests/manifestutils"
"github.com/open-telemetry/opentelemetry-operator/pkg/featuregate"
)

Expand Down Expand Up @@ -86,6 +87,10 @@ service:
goodConfig := v1beta1.Config{}
err := go_yaml.Unmarshal([]byte(goodConfigYaml), &goodConfig)
require.NoError(t, err)

goodConfigHash, _ := manifestutils.GetConfigMapSHA(goodConfig)
goodConfigHash = goodConfigHash[:8]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. These tests were always a pain to update because of this.


one := int32(1)
type args struct {
instance v1beta1.OpenTelemetryCollector
Expand Down Expand Up @@ -164,7 +169,7 @@ service:
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
},
Items: []corev1.KeyToPath{
{
Expand Down Expand Up @@ -223,13 +228,13 @@ service:
},
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
Namespace: "test",
Labels: map[string]string{
"app.kubernetes.io/component": "opentelemetry-collector",
"app.kubernetes.io/instance": "test.test",
"app.kubernetes.io/managed-by": "opentelemetry-operator",
"app.kubernetes.io/name": "test-collector",
"app.kubernetes.io/name": "test-collector-" + goodConfigHash,
matthagenbuch marked this conversation as resolved.
Show resolved Hide resolved
"app.kubernetes.io/part-of": "opentelemetry",
"app.kubernetes.io/version": "latest",
},
Expand Down Expand Up @@ -411,7 +416,7 @@ service:
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
},
Items: []corev1.KeyToPath{
{
Expand Down Expand Up @@ -470,13 +475,13 @@ service:
},
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
Namespace: "test",
Labels: map[string]string{
"app.kubernetes.io/component": "opentelemetry-collector",
"app.kubernetes.io/instance": "test.test",
"app.kubernetes.io/managed-by": "opentelemetry-operator",
"app.kubernetes.io/name": "test-collector",
"app.kubernetes.io/name": "test-collector-" + goodConfigHash,
"app.kubernetes.io/part-of": "opentelemetry",
"app.kubernetes.io/version": "latest",
},
Expand Down Expand Up @@ -694,7 +699,7 @@ service:
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
},
Items: []corev1.KeyToPath{
{
Expand Down Expand Up @@ -753,13 +758,13 @@ service:
},
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
Namespace: "test",
Labels: map[string]string{
"app.kubernetes.io/component": "opentelemetry-collector",
"app.kubernetes.io/instance": "test.test",
"app.kubernetes.io/managed-by": "opentelemetry-operator",
"app.kubernetes.io/name": "test-collector",
"app.kubernetes.io/name": "test-collector-" + goodConfigHash,
"app.kubernetes.io/part-of": "opentelemetry",
"app.kubernetes.io/version": "latest",
},
Expand Down Expand Up @@ -1129,6 +1134,10 @@ service:
goodConfig := v1beta1.Config{}
err := go_yaml.Unmarshal([]byte(goodConfigYaml), &goodConfig)
require.NoError(t, err)

goodConfigHash, _ := manifestutils.GetConfigMapSHA(goodConfig)
goodConfigHash = goodConfigHash[:8]

one := int32(1)
type args struct {
instance v1beta1.OpenTelemetryCollector
Expand Down Expand Up @@ -1216,7 +1225,7 @@ service:
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
},
Items: []corev1.KeyToPath{
{
Expand Down Expand Up @@ -1275,13 +1284,13 @@ service:
},
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
Namespace: "test",
Labels: map[string]string{
"app.kubernetes.io/component": "opentelemetry-collector",
"app.kubernetes.io/instance": "test.test",
"app.kubernetes.io/managed-by": "opentelemetry-operator",
"app.kubernetes.io/name": "test-collector",
"app.kubernetes.io/name": "test-collector-" + goodConfigHash,
"app.kubernetes.io/part-of": "opentelemetry",
"app.kubernetes.io/version": "latest",
},
Expand Down Expand Up @@ -1610,7 +1619,7 @@ prometheus_cr:
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
},
Items: []corev1.KeyToPath{
{
Expand Down Expand Up @@ -1669,13 +1678,13 @@ prometheus_cr:
},
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-collector",
Name: "test-collector-" + goodConfigHash,
Namespace: "test",
Labels: map[string]string{
"app.kubernetes.io/component": "opentelemetry-collector",
"app.kubernetes.io/instance": "test.test",
"app.kubernetes.io/managed-by": "opentelemetry-operator",
"app.kubernetes.io/name": "test-collector",
"app.kubernetes.io/name": "test-collector-" + goodConfigHash,
"app.kubernetes.io/part-of": "opentelemetry",
"app.kubernetes.io/version": "latest",
},
Expand Down
25 changes: 25 additions & 0 deletions controllers/opentelemetrycollector_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package controllers
import (
"context"
"fmt"
"sort"

"github.com/go-logr/logr"
routev1 "github.com/openshift/api/route/v1"
Expand Down Expand Up @@ -128,6 +129,30 @@ func (r *OpenTelemetryCollectorReconciler) findOtelOwnedObjects(ctx context.Cont
ownedObjects[pdbList.Items[i].GetUID()] = &pdbList.Items[i]
}

configMapList := &corev1.ConfigMapList{}
err = r.List(ctx, configMapList, listOps)
if err != nil {
return nil, fmt.Errorf("error listing ConfigMaps: %w", err)
}

// only return collector ConfigMaps older than spec.ConfigVersions
sort.Slice(configMapList.Items, func(i, j int) bool {
iTime := configMapList.Items[i].GetCreationTimestamp().Time
jTime := configMapList.Items[j].GetCreationTimestamp().Time
// sort the ConfigMaps newest to oldest
return iTime.After(jTime)
})
configVersionsToKeep := 3
if params.OtelCol.Spec.ConfigVersions != nil {
configVersionsToKeep = max(1, int(*params.OtelCol.Spec.ConfigVersions))
}

for i := range configMapList.Items {
if i > configVersionsToKeep {
ownedObjects[configMapList.Items[i].GetUID()] = &configMapList.Items[i]
}
}

swiatekm marked this conversation as resolved.
Show resolved Hide resolved
return ownedObjects, nil
}

Expand Down
12 changes: 9 additions & 3 deletions controllers/reconcile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,9 @@ func TestOpenTelemetryCollectorReconciler_Reconcile(t *testing.T) {
result: controllerruntime.Result{},
checks: []check[v1alpha1.OpenTelemetryCollector]{
func(t *testing.T, params v1alpha1.OpenTelemetryCollector) {
exists, err := populateObjectIfExists(t, &v1.ConfigMap{}, namespacedObjectName(naming.Collector(params.Name), params.Namespace))
configHash, _ := getConfigMapSHAFromString(params.Spec.Config)
configHash = configHash[:8]
exists, err := populateObjectIfExists(t, &v1.ConfigMap{}, namespacedObjectName(naming.ConfigMap(params.Name, configHash), params.Namespace))
assert.NoError(t, err)
assert.True(t, exists)
exists, err = populateObjectIfExists(t, &appsv1.StatefulSet{}, namespacedObjectName(naming.Collector(params.Name), params.Namespace))
Expand All @@ -450,7 +452,9 @@ func TestOpenTelemetryCollectorReconciler_Reconcile(t *testing.T) {
result: controllerruntime.Result{},
checks: []check[v1alpha1.OpenTelemetryCollector]{
func(t *testing.T, params v1alpha1.OpenTelemetryCollector) {
exists, err := populateObjectIfExists(t, &v1.ConfigMap{}, namespacedObjectName(naming.Collector(params.Name), params.Namespace))
configHash, _ := getConfigMapSHAFromString(params.Spec.Config)
configHash = configHash[:8]
exists, err := populateObjectIfExists(t, &v1.ConfigMap{}, namespacedObjectName(naming.ConfigMap(params.Name, configHash), params.Namespace))
assert.NoError(t, err)
assert.True(t, exists)
actual := v1.ConfigMap{}
Expand Down Expand Up @@ -495,7 +499,9 @@ func TestOpenTelemetryCollectorReconciler_Reconcile(t *testing.T) {
result: controllerruntime.Result{},
checks: []check[v1alpha1.OpenTelemetryCollector]{
func(t *testing.T, params v1alpha1.OpenTelemetryCollector) {
exists, err := populateObjectIfExists(t, &v1.ConfigMap{}, namespacedObjectName(naming.Collector(params.Name), params.Namespace))
configHash, _ := getConfigMapSHAFromString(params.Spec.Config)
matthagenbuch marked this conversation as resolved.
Show resolved Hide resolved
configHash = configHash[:8]
exists, err := populateObjectIfExists(t, &v1.ConfigMap{}, namespacedObjectName(naming.ConfigMap(params.Name, configHash), params.Namespace))
assert.NoError(t, err)
assert.True(t, exists)
actual := v1.ConfigMap{}
Expand Down
11 changes: 11 additions & 0 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/yaml"

"github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1"
"github.com/open-telemetry/opentelemetry-operator/apis/v1beta1"
Expand All @@ -60,6 +61,7 @@ import (
"github.com/open-telemetry/opentelemetry-operator/internal/config"
"github.com/open-telemetry/opentelemetry-operator/internal/manifests"
"github.com/open-telemetry/opentelemetry-operator/internal/manifests/collector/testdata"
"github.com/open-telemetry/opentelemetry-operator/internal/manifests/manifestutils"
"github.com/open-telemetry/opentelemetry-operator/internal/rbac"
// +kubebuilder:scaffold:imports
)
Expand Down Expand Up @@ -480,3 +482,12 @@ func populateObjectIfExists(t testing.TB, object client.Object, namespacedName t
}
return true, nil
}

func getConfigMapSHAFromString(configStr string) (string, error) {
var config v1beta1.Config
err := yaml.Unmarshal([]byte(configStr), &config)
if err != nil {
return "", err
}
return manifestutils.GetConfigMapSHA(config)
}
6 changes: 5 additions & 1 deletion internal/manifests/collector/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ import (
)

func ConfigMap(params manifests.Params) (*corev1.ConfigMap, error) {
name := naming.ConfigMap(params.OtelCol.Name)
hash, err := manifestutils.GetConfigMapSHA(params.OtelCol.Spec.Config)
if err != nil {
return nil, err
}
name := naming.ConfigMap(params.OtelCol.Name, hash)
labels := manifestutils.Labels(params.OtelCol.ObjectMeta, name, params.OtelCol.Spec.Image, ComponentOpenTelemetryCollector, []string{})

replacedConf, err := ReplaceConfig(params.OtelCol)
Expand Down
28 changes: 19 additions & 9 deletions internal/manifests/collector/configmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package collector
import (
"testing"

"github.com/open-telemetry/opentelemetry-operator/internal/manifests/manifestutils"
"github.com/open-telemetry/opentelemetry-operator/internal/naming"
matthagenbuch marked this conversation as resolved.
Show resolved Hide resolved
"github.com/stretchr/testify/assert"
)

Expand All @@ -29,9 +31,6 @@ func TestDesiredConfigMap(t *testing.T) {
}

t.Run("should return expected collector config map", func(t *testing.T) {
expectedLables["app.kubernetes.io/component"] = "opentelemetry-collector"
expectedLables["app.kubernetes.io/name"] = "test-collector"
expectedLables["app.kubernetes.io/version"] = "0.47.0"

expectedData := map[string]string{
"collector.yaml": `receivers:
Expand All @@ -58,10 +57,17 @@ service:
}

param := deploymentParams()
hash, _ := manifestutils.GetConfigMapSHA(param.OtelCol.Spec.Config)
expectedName := naming.ConfigMap("test", hash)

expectedLables["app.kubernetes.io/component"] = "opentelemetry-collector"
expectedLables["app.kubernetes.io/name"] = expectedName
expectedLables["app.kubernetes.io/version"] = "0.47.0"

actual, err := ConfigMap(param)

assert.NoError(t, err)
assert.Equal(t, "test-collector", actual.Name)
assert.Equal(t, expectedName, actual.Name)
assert.Equal(t, expectedLables, actual.Labels)
assert.Equal(t, len(expectedData), len(actual.Data))
for k, expected := range expectedData {
Expand All @@ -70,10 +76,6 @@ service:
})

t.Run("should return expected escaped collector config map with target_allocator config block", func(t *testing.T) {
expectedLables["app.kubernetes.io/component"] = "opentelemetry-collector"
expectedLables["app.kubernetes.io/name"] = "test-collector"
expectedLables["app.kubernetes.io/version"] = "latest"

expectedData := map[string]string{
"collector.yaml": `exporters:
debug:
Expand All @@ -97,11 +99,19 @@ service:

param, err := newParams("test/test-img", "testdata/http_sd_config_servicemonitor_test.yaml")
assert.NoError(t, err)

hash, _ := manifestutils.GetConfigMapSHA(param.OtelCol.Spec.Config)
expectedName := naming.ConfigMap("test", hash)

expectedLables["app.kubernetes.io/component"] = "opentelemetry-collector"
expectedLables["app.kubernetes.io/name"] = expectedName
expectedLables["app.kubernetes.io/version"] = "latest"

param.OtelCol.Spec.TargetAllocator.Enabled = true
actual, err := ConfigMap(param)

assert.NoError(t, err)
assert.Equal(t, "test-collector", actual.Name)
assert.Equal(t, expectedName, actual.Name)
assert.Equal(t, expectedLables, actual.Labels)
assert.Equal(t, len(expectedData), len(actual.Data))
for k, expected := range expectedData {
Expand Down
Loading
Loading