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
7 changes: 7 additions & 0 deletions api/policies/v1/policyserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ type PolicyServerSpec struct {
// +optional
Annotations map[string]string `json:"annotations,omitempty"`

// Labels is a map of custom labels to be applied to the Deployment created by the
// PolicyServer and to the Pods managed by that Deployment. System labels set by
// the controller always take precedence over user-defined labels with the same key.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
// +optional
Labels map[string]string `json:"labels,omitempty"`

// List of environment variables to set in the container.
// +optional
Env []corev1.EnvVar `json:"env,omitempty"`
Expand Down
7 changes: 7 additions & 0 deletions api/policies/v1/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 @@ -1145,6 +1145,15 @@ spec:
items:
type: string
type: array
labels:
additionalProperties:
type: string
description: |-
Labels is a map of custom labels to be applied to the Deployment created by the
PolicyServer and to the Pods managed by that Deployment. System labels set by
the controller always take precedence over user-defined labels with the same key.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
type: object
limits:
additionalProperties:
anyOf:
Expand Down
11 changes: 10 additions & 1 deletion config/crd/bases/policies.kubewarden.io_policyservers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,15 @@ spec:
items:
type: string
type: array
labels:
additionalProperties:
type: string
description: |-
Labels is a map of custom labels to be applied to the Deployment created by the
PolicyServer and to the Pods managed by that Deployment. System labels set by
the controller always take precedence over user-defined labels with the same key.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
type: object
limits:
additionalProperties:
anyOf:
Expand Down Expand Up @@ -1721,7 +1730,7 @@ spec:
Name of VerificationConfig configmap in the kubewarden namespace (same
namespace as the controller deployment), containing Sigstore verification
configuration. The configuration must be under a key named
verification-config in the Configmap.
verification-config in the ConfigMap.
type: string
required:
- image
Expand Down
5 changes: 5 additions & 0 deletions docs/crds/CRD-docs-for-docs-repo.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,11 @@ set by external tools to store and retrieve arbitrary metadata. They are not +
queryable and should be preserved when modifying objects. +
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + | | Optional: \{} +

| *`labels`* __object (keys:string, values:string)__ | Labels is a map of custom labels to be applied to the Deployment created by the +
PolicyServer and to the Pods managed by that Deployment. System labels set by +
the controller always take precedence over user-defined labels with the same key. +
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + | | Optional: \{} +

| *`env`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envvar-v1-core[$$EnvVar$$] array__ | List of environment variables to set in the container. + | | Optional: \{} +

| *`serviceAccountName`* __string__ | Name of the service account associated with the policy server. +
Expand Down
1 change: 1 addition & 0 deletions docs/crds/CRD-docs-for-docs-repo.md
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ _Appears in:_
| `minAvailable` _[IntOrString](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#intorstring-intstr-util)_ | Number of policy server replicas that must be still available after the<br />eviction. The value can be an absolute number or a percentage. Only one of<br />MinAvailable or Max MaxUnavailable can be set. | | |
| `maxUnavailable` _[IntOrString](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#intorstring-intstr-util)_ | Number of policy server replicas that can be unavailable after the<br />eviction. The value can be an absolute number or a percentage. Only one of<br />MinAvailable or Max MaxUnavailable can be set. | | |
| `annotations` _object (keys:string, values:string)_ | Annotations is an unstructured key value map stored with a resource that may be<br />set by external tools to store and retrieve arbitrary metadata. They are not<br />queryable and should be preserved when modifying objects.<br />More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ | | Optional: \{\} <br /> |
| `labels` _object (keys:string, values:string)_ | Labels is a map of custom labels to be applied to the Deployment created by the<br />PolicyServer and to the Pods managed by that Deployment. System labels set by<br />the controller always take precedence over user-defined labels with the same key.<br />More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ | | Optional: \{\} <br /> |
| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envvar-v1-core) array_ | List of environment variables to set in the container. | | Optional: \{\} <br /> |
| `serviceAccountName` _string_ | Name of the service account associated with the policy server.<br />Namespace service account will be used if not specified. | | Optional: \{\} <br /> |
| `imagePullSecret` _string_ | Name of ImagePullSecret secret in the same namespace, used for pulling<br />policies from repositories. | | Optional: \{\} <br /> |
Expand Down
14 changes: 14 additions & 0 deletions internal/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ const (

OptelInjectAnnotation = "sidecar.opentelemetry.io/inject"

// PolicyServerDeploymentManagedAnnotationKeysAnnotation is the annotation used to track
// which annotation keys on a Deployment/Pod template are managed by the controller (i.e.,
// came from spec.annotations). On each reconcile the controller removes keys that were
// previously managed but are no longer present in the spec, without touching annotations
// set by Kubernetes itself or other tooling.
PolicyServerDeploymentManagedAnnotationKeysAnnotation = "kubewarden.io/managed-annotation-keys"

// PolicyServerDeploymentManagedLabelKeysAnnotation is the annotation used to track
// which label keys on a Deployment/Pod template are managed by the controller (i.e.,
// came from spec.labels). On each reconcile the controller removes keys that were
// previously managed but are no longer present in the spec, without touching labels
// set by Kubernetes itself or other tooling.
PolicyServerDeploymentManagedLabelKeysAnnotation = "kubewarden.io/managed-label-keys"

WebhookConfigurationPolicyNameAnnotationKey = "kubewardenPolicyName"
WebhookConfigurationPolicyNamespaceAnnotationKey = "kubewardenPolicyNamespace"

Expand Down
67 changes: 60 additions & 7 deletions internal/controller/policyserver_controller_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import (
"context"
"errors"
"fmt"
"maps"
"os"
"path/filepath"
"slices"
"strconv"
"strings"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -326,17 +329,64 @@ func configuresInsecureSources(policyServer *policiesv1.PolicyServer, admissionC
}
}

// applyManagedKeys removes keys that were previously managed (recorded in the tracking
// annotation/label) but are no longer present in the desired user-defined map, then applies
// the new desired keys and records the current managed set in the tracking annotation.
//
// Parameters:
// - existing: the current annotation/label map on the object (mutated in-place).
// - desired: the user-defined map from spec (may be nil).
// - trackingAnnotations: the annotation map where the tracking key is stored (may differ from
// existing when we track label keys inside the annotation map).
// - trackingKey: the annotation key used to store the comma-separated list of managed keys.
func applyManagedKeys(existing map[string]string, desired map[string]string, trackingAnnotations map[string]string, trackingKey string) {
// Remove keys that were managed last time but are no longer desired.
if prev, found := trackingAnnotations[trackingKey]; found && prev != "" {
for _, key := range strings.Split(prev, ",") {
if _, stillDesired := desired[key]; !stillDesired {
delete(existing, key)
}
}
}

// Apply desired keys (user-defined values first; system values will overwrite after this call).
for key, value := range desired {
existing[key] = value
}

// Record the current set of managed keys.
trackingAnnotations[trackingKey] = strings.Join(slices.Collect(maps.Keys(desired)), ",")
}

func configureLabelsAndAnnotations(policyServerDeployment *appsv1.Deployment, policyServer *policiesv1.PolicyServer, configMapVersion string) {
// --- Annotations ---
if policyServerDeployment.ObjectMeta.Annotations == nil {
policyServerDeployment.ObjectMeta.Annotations = make(map[string]string)
}
// The tracking annotation lives in ObjectMeta.Annotations itself.
applyManagedKeys(
policyServerDeployment.ObjectMeta.Annotations,
policyServer.Spec.Annotations,
policyServerDeployment.ObjectMeta.Annotations,
constants.PolicyServerDeploymentManagedAnnotationKeysAnnotation,
)
// System annotation always wins.
policyServerDeployment.ObjectMeta.Annotations[constants.PolicyServerDeploymentConfigVersionAnnotation] = configMapVersion

// --- Labels ---
if policyServerDeployment.Labels == nil {
policyServerDeployment.Labels = make(map[string]string)
}
// The tracking annotation for labels is stored in the annotation map so that we don't
// pollute the labels map with a non-label value.
applyManagedKeys(
policyServerDeployment.Labels,
policyServer.Spec.Labels,
policyServerDeployment.ObjectMeta.Annotations,
constants.PolicyServerDeploymentManagedLabelKeysAnnotation,
)
// System labels always win.
policyServerDeployment.Labels[constants.PolicyServerLabelKey] = policyServer.Name

for key, value := range policyServer.CommonLabels() {
policyServerDeployment.Labels[key] = value
}
Expand Down Expand Up @@ -417,12 +467,15 @@ func buildPolicyServerDeploymentSpec(
podSecurityContext *corev1.PodSecurityContext,
imagePullSecrets []corev1.LocalObjectReference,
) appsv1.DeploymentSpec {
templateLabels := map[string]string{
//nolint:staticcheck // this label will remove soon when policy lifecycle is revisited
constants.AppLabelKey: policyServer.AppLabel(),
constants.PolicyServerDeploymentPodSpecConfigVersionLabel: configMapVersion,
constants.PolicyServerLabelKey: policyServer.Name,
}
// Apply user-defined labels first, then system labels overwrite any conflicts.
templateLabels := maps.Clone(policyServer.Spec.Labels)
if templateLabels == nil {
templateLabels = make(map[string]string)
Comment thread
flavio marked this conversation as resolved.
}
//nolint:staticcheck // this label will remove soon when policy lifecycle is revisited
templateLabels[constants.AppLabelKey] = policyServer.AppLabel()
templateLabels[constants.PolicyServerDeploymentPodSpecConfigVersionLabel] = configMapVersion
templateLabels[constants.PolicyServerLabelKey] = policyServer.Name
for key, value := range policyServer.CommonLabels() {
templateLabels[key] = value
}
Expand Down
Loading