Skip to content

Commit

Permalink
propogate labels from limitador to deployment template
Browse files Browse the repository at this point in the history
Signed-off-by: Laura Fitzgerald <[email protected]>
  • Loading branch information
laurafitzgerald committed Feb 13, 2025
1 parent 48cb256 commit 10cf420
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 13 deletions.
3 changes: 2 additions & 1 deletion controllers/limitador_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ func (r *LimitadorReconciler) reconcileDeployment(ctx context.Context, limitador
reconcilers.DeploymentPortsMutator,
reconcilers.DeploymentLivenessProbeMutator,
reconcilers.DeploymentReadinessProbeMutator,
reconcilers.DeploymentTemplateLabelMutator,
)

// reconcile imagepullsecrets only when set in limitador CR
Expand All @@ -238,7 +239,7 @@ func (r *LimitadorReconciler) reconcileDeployment(ctx context.Context, limitador
deploymentMutators = append(deploymentMutators, reconcilers.DeploymentImagePullSecretsMutator)
}

deployment := limitador.Deployment(limitadorObj, deploymentOptions)
deployment := limitador.Deployment(limitadorObj, deploymentOptions, logger)
// controller reference
if err := r.SetOwnerReference(limitadorObj, deployment); err != nil {
return err
Expand Down
16 changes: 16 additions & 0 deletions pkg/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,19 @@ func IsObjectTaggedToDelete(obj client.Object) bool {
annotation, ok := annotations[DeleteTagAnnotation]
return ok && annotation == "true"
}

func MergeMapStringString(modified *bool, existing map[string]string, desired *map[string]string) {
if existing == nil {
existing = map[string]string{}
}

// for each desired key value set, e.g. labels
// check if it's present in existing. if not add it to existing.
// e.g. preserving existing labels while adding those that are in the desired set.
for desiredKey, desiredValue := range *desired {
if existingValue, exists := (existing)[desiredKey]; !exists || existingValue != desiredValue {
(*desired)[desiredKey] = existingValue
*modified = true
}
}
}
21 changes: 17 additions & 4 deletions pkg/limitador/k8s_objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package limitador

import (
"fmt"
"github.com/go-logr/logr"

appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -52,7 +53,7 @@ func Service(limitador *limitadorv1alpha1.Limitador) *v1.Service {
}
}

func Deployment(limitador *limitadorv1alpha1.Limitador, deploymentOptions DeploymentOptions) *appsv1.Deployment {
func Deployment(limitador *limitadorv1alpha1.Limitador, deploymentOptions DeploymentOptions, logger logr.Logger) *appsv1.Deployment {
replicas := limitador.GetReplicas()

image := GetLimitadorImage()
Expand All @@ -66,6 +67,18 @@ func Deployment(limitador *limitadorv1alpha1.Limitador, deploymentOptions Deploy
image = *limitador.Spec.Image
}

// setting the desired labels, the hardcoded ones and the limitador ones.
mutableLabels := Labels(limitador)
if limitador.ObjectMeta.Labels != nil {
for key, value := range limitador.ObjectMeta.Labels {
if key == "limitador-resource" || key == "app" {
logger.V(1).Info("skipping limitador labels with keys \"app\" and \"limitador-resource\" as these are reserved for use by the operator")
continue
}
mutableLabels[key] = value
}
}
immutableLabels := Labels(limitador)
return &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
Kind: "Deployment",
Expand All @@ -74,17 +87,17 @@ func Deployment(limitador *limitadorv1alpha1.Limitador, deploymentOptions Deploy
ObjectMeta: metav1.ObjectMeta{
Name: DeploymentName(limitador),
Namespace: limitador.ObjectMeta.Namespace, // TODO: revisit later. For now assume same.
Labels: Labels(limitador),
Labels: mutableLabels,
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Strategy: deploymentOptions.DeploymentStrategy,
Selector: &metav1.LabelSelector{
MatchLabels: Labels(limitador),
MatchLabels: immutableLabels,
},
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: Labels(limitador),
Labels: mutableLabels,
},
Spec: v1.PodSpec{
Affinity: limitador.Spec.Affinity,
Expand Down
71 changes: 63 additions & 8 deletions pkg/limitador/k8s_objects_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package limitador

import (
"github.com/go-logr/logr"
"testing"

"gotest.tools/assert"
Expand Down Expand Up @@ -66,34 +67,88 @@ func TestServiceName(t *testing.T) {
}

func TestDeployment(t *testing.T) {
logger := logr.Discard()
t.Run("default replicas", func(subT *testing.T) {
limObj := newTestLimitadorObj("some-name", "some-ns", nil)
limObj.Spec.Replicas = nil
deployment := Deployment(limObj, DeploymentOptions{})
deployment := Deployment(limObj, DeploymentOptions{}, logger)
assert.Assert(subT, deployment.Spec.Replicas != nil)
assert.Assert(subT, *deployment.Spec.Replicas == 1)
})

t.Run("replicas", func(subT *testing.T) {
limObj := newTestLimitadorObj("some-name", "some-ns", nil)
limObj.Spec.Replicas = ptr.To(2)
deployment := Deployment(limObj, DeploymentOptions{})
deployment := Deployment(limObj, DeploymentOptions{}, logger)
assert.Assert(subT, deployment.Spec.Replicas != nil)
assert.Assert(subT, *deployment.Spec.Replicas == 2)
})

t.Run("labels", func(subT *testing.T) {
limObjLabels := newTestLimitadorObj("some-name", "some-ns", nil)
limObjLabels.Labels = map[string]string{
"test-label-key": "test-label-value",
}
deployment := Deployment(limObjLabels, DeploymentOptions{}, logger)
assert.DeepEqual(subT, deployment.Labels,
map[string]string{
"app": "limitador",
"limitador-resource": "some-name",
"test-label-key": "test-label-value",
})
assert.DeepEqual(subT, deployment.Spec.Template.Labels,
map[string]string{
"app": "limitador",
"limitador-resource": "some-name",
"test-label-key": "test-label-value",
})
assert.DeepEqual(subT, deployment.Spec.Selector.MatchLabels,
map[string]string{
"app": "limitador",
"limitador-resource": "some-name",
})
limObj := newTestLimitadorObj("some-name", "some-ns", nil)
deployment := Deployment(limObj, DeploymentOptions{})
deployment = Deployment(limObj, DeploymentOptions{}, logger)
assert.DeepEqual(subT, deployment.Labels,
map[string]string{
"app": "limitador",
"limitador-resource": "some-name",
})
assert.DeepEqual(subT, deployment.Spec.Template.Labels,
map[string]string{
"app": "limitador",
"limitador-resource": "some-name",
})
assert.DeepEqual(subT, deployment.Spec.Selector.MatchLabels,
map[string]string{
"app": "limitador",
"limitador-resource": "some-name",
})

limObjInvalidLabels := newTestLimitadorObj("some-name", "some-ns", nil)
limObjInvalidLabels.Labels = map[string]string{
"app": "some-other-non-system-app-value",
}
deployment = Deployment(limObjInvalidLabels, DeploymentOptions{}, logger)
assert.DeepEqual(subT, deployment.Labels,
map[string]string{
"app": "limitador",
"limitador-resource": "some-name",
})
assert.DeepEqual(subT, deployment.Spec.Template.Labels,
map[string]string{
"app": "limitador",
"limitador-resource": "some-name",
})
assert.DeepEqual(subT, deployment.Spec.Selector.MatchLabels,
map[string]string{
"app": "limitador",
"limitador-resource": "some-name",
})
})
t.Run("selector", func(subT *testing.T) {
limObj := newTestLimitadorObj("some-name", "some-ns", nil)
deployment := Deployment(limObj, DeploymentOptions{})
deployment := Deployment(limObj, DeploymentOptions{}, logger)
assert.DeepEqual(subT, deployment.Spec.Selector.MatchLabels,
map[string]string{
"app": "limitador",
Expand All @@ -105,7 +160,7 @@ func TestDeployment(t *testing.T) {
limObj := newTestLimitadorObj("some-name", "some-ns", nil)
deployment := Deployment(limObj, DeploymentOptions{
Command: []string{"a", "b", "c"},
})
}, logger)
assert.Assert(subT, len(deployment.Spec.Template.Spec.Containers) == 1)
assert.DeepEqual(subT, deployment.Spec.Template.Spec.Containers[0].Command,
[]string{"a", "b", "c"},
Expand All @@ -125,7 +180,7 @@ func TestDeployment(t *testing.T) {
MountPath: "/path/B",
},
},
})
}, logger)
assert.Assert(subT, len(deployment.Spec.Template.Spec.Containers) == 1)
assert.DeepEqual(subT, deployment.Spec.Template.Spec.Containers[0].VolumeMounts,
[]corev1.VolumeMount{
Expand Down Expand Up @@ -166,7 +221,7 @@ func TestDeployment(t *testing.T) {
},
},
},
})
}, logger)
assert.DeepEqual(subT, deployment.Spec.Template.Spec.Volumes,
[]corev1.Volume{
{
Expand Down Expand Up @@ -197,7 +252,7 @@ func TestDeployment(t *testing.T) {
limObj := newTestLimitadorObj("some-name", "some-ns", nil)
deployment := Deployment(limObj, DeploymentOptions{
ImagePullSecrets: []corev1.LocalObjectReference{{Name: "regcred"}},
})
}, logger)

assert.DeepEqual(subT, deployment.Spec.Template.Spec.ImagePullSecrets,
[]corev1.LocalObjectReference{{Name: "regcred"}},
Expand Down
8 changes: 8 additions & 0 deletions pkg/reconcilers/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package reconcilers

import (
"fmt"
"github.com/kuadrant/limitador-operator/pkg/helpers"
"reflect"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -37,6 +38,13 @@ func DeploymentMutator(opts ...DeploymentMutateFn) MutateFn {
}
}

func DeploymentTemplateLabelMutator(desired, existing *appsv1.Deployment) bool {
update := false
helpers.MergeMapStringString(&update, existing.Spec.Template.Labels, &desired.Spec.Template.Labels)
helpers.MergeMapStringString(&update, existing.Labels, &desired.Labels)
return update
}

func DeploymentAffinityMutator(desired, existing *appsv1.Deployment) bool {
update := false
if !reflect.DeepEqual(existing.Spec.Template.Spec.Affinity, desired.Spec.Template.Spec.Affinity) {
Expand Down

0 comments on commit 10cf420

Please sign in to comment.