Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions pkg/controller/ippool/pool_controller_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2023-2025 Tigera, Inc. All rights reserved.
// Copyright (c) 2023-2026 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -258,7 +258,7 @@ var _ = Describe("IP Pool controller tests", func() {
}
for _, pool := range instance.Spec.CalicoNetwork.IPPools {
Expect(poolsByCIDR).To(HaveKey(pool.CIDR))
Expect(poolsByCIDR[pool.CIDR].Labels).To(Equal(map[string]string{"app.kubernetes.io/managed-by": "tigera-operator"}))
Expect(poolsByCIDR[pool.CIDR].Labels).To(HaveKeyWithValue("app.kubernetes.io/managed-by", "tigera-operator"))
}
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022-2024 Tigera, Inc. All rights reserved.
// Copyright (c) 2022-2026 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/logstorage/secrets/secret_controller.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2023-2024 Tigera, Inc. All rights reserved.
// Copyright (c) 2023-2026 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/logstorage/users/users_controller.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2023-2024 Tigera, Inc. All rights reserved.
// Copyright (c) 2023-2026 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
11 changes: 9 additions & 2 deletions pkg/controller/monitor/monitor_controller_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021-2024 Tigera, Inc. All rights reserved.
// Copyright (c) 2021-2026 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -259,7 +259,14 @@ var _ = Describe("Monitor controller tests", func() {

Expect(serviceMonitor.Spec.Endpoints).To(HaveLen(1))
// Verify that the default settings are propagated.
Expect(serviceMonitor.Labels).To(Equal(map[string]string{render.AppLabelName: monitor.TigeraExternalPrometheus}))
Expect(serviceMonitor.Labels).To(Equal(map[string]string{
render.AppLabelName: monitor.TigeraExternalPrometheus,
"app.kubernetes.io/instance": "tigera-secure",
"app.kubernetes.io/managed-by": "tigera-operator",
"app.kubernetes.io/name": "tigera-external-prometheus",
"app.kubernetes.io/part-of": "Calico",
"app.kubernetes.io/component": "Monitor.operator.tigera.io",
}))
Expect(serviceMonitor.Spec.Endpoints[0]).To(Equal(monitoringv1.Endpoint{
Params: map[string][]string{"match[]": {"{__name__=~\".+\"}"}},
Port: "web",
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/secrets/cluster_ca_controller.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2023-2024 Tigera, Inc. All rights reserved.
// Copyright (c) 2023-2026 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/secrets/tenant_controller.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2023-2024 Tigera, Inc. All rights reserved.
// Copyright (c) 2023-2026 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
112 changes: 104 additions & 8 deletions pkg/controller/utils/component.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2025 Tigera, Inc. All rights reserved.
// Copyright (c) 2020-2026 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@ import (
"context"
"fmt"
"reflect"
"regexp"
"slices"
"strings"
"sync"
Expand Down Expand Up @@ -235,7 +236,7 @@ func (c *componentHandler) createOrUpdateObject(ctx context.Context, obj client.
setProbeTimeouts(obj)

// Make sure we have our standard selector and pod labels
setStandardSelectorAndLabels(obj)
setStandardSelectorAndLabels(obj, c.cr)

if err := ensureTLSCiphers(ctx, obj, c.client); err != nil {
return fmt.Errorf("failed to set TLS Ciphers: %w", err)
Expand Down Expand Up @@ -951,16 +952,31 @@ func setProbeTimeouts(obj client.Object) {
}
}

// setStandardSelectorAndLabels will set the k8s-app and app.kubernetes.io/name Labels on the podTemplates
// setStandardSelectorAndLabels will set the recommended labels found at
// https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
// It will also set the k8s-app and app.kubernetes.io/name Labels on the podTemplates
// for Deployments and Daemonsets. If there is no Selector specified a selector will also be added
// that selects the k8s-app label.
func setStandardSelectorAndLabels(obj client.Object) {
func setStandardSelectorAndLabels(obj client.Object, customResource metav1.Object) {
if obj.GetLabels() == nil {
obj.SetLabels(make(map[string]string))
}
if customResource != nil {
// We do not want to set these labels on objects without a CR. They are usually deliberately not getting an
// owner ref and are not controlled by our operator.
addNameLabel(obj, obj.GetName())
addInstanceLabel(obj, customResource)
addComponentLabel(obj, customResource)
addPartOfLabel(obj)
addManagedByLabel(obj)
}

var podTemplate *v1.PodTemplateSpec
var name string
switch obj := obj.(type) {
case *apps.Deployment:
d := obj
name = d.Name
name = sanitizeLabel(d.Name)
if d.Labels == nil {
d.Labels = make(map[string]string)
}
Expand All @@ -976,7 +992,7 @@ func setStandardSelectorAndLabels(obj client.Object) {
podTemplate = &d.Spec.Template
case *apps.DaemonSet:
d := obj
name = d.Name
name = sanitizeLabel(d.Name)
if d.Spec.Selector == nil {
d.Spec.Selector = &metav1.LabelSelector{
MatchLabels: map[string]string{
Expand All @@ -985,6 +1001,22 @@ func setStandardSelectorAndLabels(obj client.Object) {
}
}
podTemplate = &d.Spec.Template
case *monitoringv1.Prometheus:
d := obj
if d.Spec.PodMetadata == nil {
d.Spec.PodMetadata = &monitoringv1.EmbeddedObjectMetadata{}
}
for k, v := range d.Labels {
d.Spec.PodMetadata.Labels[k] = v
}
case *monitoringv1.Alertmanager:
d := obj
if d.Spec.PodMetadata == nil {
d.Spec.PodMetadata = &monitoringv1.EmbeddedObjectMetadata{}
}
for k, v := range d.Labels {
d.Spec.PodMetadata.Labels[k] = v
}
default:
return
}
Expand All @@ -995,8 +1027,72 @@ func setStandardSelectorAndLabels(obj client.Object) {
if podTemplate.Labels["k8s-app"] == "" {
podTemplate.Labels["k8s-app"] = name
}
if podTemplate.Labels["app.kubernetes.io/name"] == "" {
podTemplate.Labels["app.kubernetes.io/name"] = name
if customResource != nil {
// We do not want to set these labels on objects without a CR. They are usually deliberately not getting an
// owner ref and are not controlled by our operator.
addNameLabel(podTemplate, obj.GetName())
addInstanceLabel(podTemplate, customResource)
addComponentLabel(podTemplate, customResource)
addPartOfLabel(podTemplate)
addManagedByLabel(podTemplate)
}

}

// sanitizeLabel cleans an input string to conform to the validation for labels. A valid label must be an empty string
// or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character and it
// is validated with regex '(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?'.
func sanitizeLabel(input string) string {
sanitized := regexp.MustCompile(`[^a-zA-Z0-9_.-]`).ReplaceAllString(input, "_")
return strings.Trim(sanitized, "-_.")
}

// addNameLabel sets the name of the application.
// For more on recommended labels see: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
func addNameLabel(obj metav1.Object, name string) {
if obj.GetLabels()["app.kubernetes.io/name"] == "" {
obj.GetLabels()["app.kubernetes.io/name"] = sanitizeLabel(name)
}
if obj.GetLabels()["k8s-app"] == "" {
obj.GetLabels()["k8s-app"] = sanitizeLabel(name)
}
}

// addInstanceLabel sets a unique name identifying the instance of an application. We use the name of the custom resource
// that owns this object.
// For more on recommended labels see: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
func addInstanceLabel(obj metav1.Object, cr metav1.Object) {
if obj.GetLabels()["app.kubernetes.io/instance"] == "" && cr != nil {
obj.GetLabels()["app.kubernetes.io/instance"] = sanitizeLabel(cr.GetName())
}
}

// addComponentLabel sets the component within the architecture. We use the kind of the custom resource that owns this
// object.
// For more on recommended labels see: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
func addComponentLabel(obj metav1.Object, cr metav1.Object) {
if obj.GetLabels()["app.kubernetes.io/component"] == "" && cr != nil {
owner, ok := cr.(runtime.Object)
if ok && owner.GetObjectKind() != nil && owner.GetObjectKind() != nil {
obj.GetLabels()["app.kubernetes.io/component"] = sanitizeLabel(owner.GetObjectKind().GroupVersionKind().GroupKind().String())

}
}
}

// addPartOfLabel sets the name of a higher level application this one is part of. We use the product variant.
// For more on recommended labels see: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
func addPartOfLabel(obj metav1.Object) {
if obj.GetLabels()["app.kubernetes.io/part-of"] == "" {
obj.GetLabels()["app.kubernetes.io/part-of"] = "Calico"
}
}

// addManagedByLabel sets the tool being used to manage the operation of an application.
// For more on recommended labels see: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
func addManagedByLabel(obj metav1.Object) {
if obj.GetLabels()["app.kubernetes.io/managed-by"] == "" {
obj.GetLabels()["app.kubernetes.io/managed-by"] = sanitizeLabel(common.OperatorName())
}
}

Expand Down
Loading
Loading