Skip to content

Commit

Permalink
Implement the configuration of labels and annotations for the namespa…
Browse files Browse the repository at this point in the history
…ce (knative#1899)

* Implement the configuration for labels and annotations

* Change the schema of the CRDs

* Change the test cases
  • Loading branch information
houshengbo authored Oct 10, 2024
1 parent 6dce5ef commit 36698cc
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 0 deletions.
14 changes: 14 additions & 0 deletions config/crd/bases/operator.knative.dev_knativeeventings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,20 @@ spec:
type: object
type: object
type: array
namespace:
description: A field of namespace name to override the labels and annotations
type: object
properties:
labels:
additionalProperties:
type: string
description: Labels overrides labels for the namespace and its template.
type: object
annotations:
additionalProperties:
type: string
description: Annotations overrides labels for the namespace and its template.
type: object
deployments:
description: A mapping of deployment name to override
type: array
Expand Down
14 changes: 14 additions & 0 deletions config/crd/bases/operator.knative.dev_knativeservings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,20 @@ spec:
type: object
type: object
type: array
namespace:
description: A field of namespace name to override the labels and annotations
type: object
properties:
labels:
additionalProperties:
type: string
description: Labels overrides labels for the namespace and its template.
type: object
annotations:
additionalProperties:
type: string
description: Annotations overrides labels for the namespace and its template.
type: object
deployments:
description: A mapping of deployment name to override
type: array
Expand Down
23 changes: 23 additions & 0 deletions pkg/apis/operator/base/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ type KComponentSpec interface {
// GetAdditionalManifests gets the list of additional manifests, which should be installed
GetAdditionalManifests() []Manifest

// GetNamespaceConfiguration gets the labels and annotations for the namespace
GetNamespaceConfiguration() *NamespaceConfiguration

// GetHighAvailability returns means to set the number of desired replicas
GetHighAvailability() *HighAvailability

Expand Down Expand Up @@ -142,6 +145,10 @@ type CommonSpec struct {
// +optional
DeploymentOverride []WorkloadOverride `json:"deployments,omitempty"`

// NamespaceConfiguration overrides namespace configurations such as labels and annotations.
// +optional
NamespaceConfiguration *NamespaceConfiguration `json:"namespace,omitempty"`

// Workloads overrides workloads configurations such as resources and replicas.
// +optional
Workloads []WorkloadOverride `json:"workloads,omitempty"`
Expand Down Expand Up @@ -191,6 +198,11 @@ func (c *CommonSpec) GetVersion() string {
return c.Version
}

// GetNamespaceConfiguration implements KComponentSpec.
func (c *CommonSpec) GetNamespaceConfiguration() *NamespaceConfiguration {
return c.NamespaceConfiguration
}

// GetManifests implements KComponentSpec.
func (c *CommonSpec) GetManifests() []Manifest {
return c.Manifests
Expand Down Expand Up @@ -247,6 +259,17 @@ type Registry struct {
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
}

// NamespaceConfiguration defines the configurations of namespaces to override.
type NamespaceConfiguration struct {
// Labels overrides labels for the namespace and its template.
// +optional
Labels map[string]string `json:"labels,omitempty"`

// Annotations overrides labels for the namespace and its template.
// +optional
Annotations map[string]string `json:"annotations,omitempty"`
}

// WorkloadOverride defines the configurations of deployments to override.
type WorkloadOverride struct {
// Name is the name of the deployment to override.
Expand Down
65 changes: 65 additions & 0 deletions pkg/reconciler/common/namespace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
Copyright 2024 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package common

import (
mf "github.com/manifestival/manifestival"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/kubernetes/scheme"

"knative.dev/operator/pkg/apis/operator/base"
)

// NamespaceConfigurationTransform mutates the only namespace available for knative serving or eventing
// by changing the labels and annotations.
func NamespaceConfigurationTransform(namespaceConfiguration *base.NamespaceConfiguration) mf.Transformer {
return func(u *unstructured.Unstructured) error {
if u.GetKind() != "Namespace" || namespaceConfiguration == nil {
return nil
}
namespace := &corev1.Namespace{}
err := scheme.Scheme.Convert(u, namespace, nil)
if err != nil {
return err
}

// Override the labels for the namespace
if namespace.GetLabels() == nil {
namespace.Labels = map[string]string{}
}

for key, val := range namespaceConfiguration.Labels {
namespace.Labels[key] = val
}

// Override the annotations for the namespace
if namespace.GetAnnotations() == nil {
namespace.Annotations = map[string]string{}
}

for key, val := range namespaceConfiguration.Annotations {
namespace.Annotations[key] = val
}

err = scheme.Scheme.Convert(namespace, u, nil)
if err != nil {
return err
}
return nil
}
}
121 changes: 121 additions & 0 deletions pkg/reconciler/common/namespace_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
Copyright 2024 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package common

import (
"testing"

"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/kubernetes/scheme"

"knative.dev/operator/pkg/apis/operator/base"
)

func TestNamespaceConfigurationTransform(t *testing.T) {
tests := []struct {
name string
namespace *corev1.Namespace
override *base.NamespaceConfiguration
expLabels map[string]string
expAnnotations map[string]string
}{{
name: "Label override",
namespace: &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "knative-serving",
Labels: map[string]string{
"istio-injection": "enabled",
"serving.knative.dev/release": "v0.13.0",
},
},
},
override: &base.NamespaceConfiguration{
Labels: map[string]string{"a": "b"},
},
expLabels: map[string]string{"a": "b", "istio-injection": "enabled", "serving.knative.dev/release": "v0.13.0"},
expAnnotations: nil,
}, {
name: "Annotation override",
namespace: &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "knative-serving",
Labels: map[string]string{
"istio-injection": "enabled",
"serving.knative.dev/release": "v0.13.0",
},
},
},
override: &base.NamespaceConfiguration{
Annotations: map[string]string{"c": "d"},
},
expLabels: map[string]string{"istio-injection": "enabled", "serving.knative.dev/release": "v0.13.0"},
expAnnotations: map[string]string{"c": "d"},
}, {
name: "No override",
namespace: &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "knative-serving",
Labels: map[string]string{
"istio-injection": "enabled",
"serving.knative.dev/release": "v0.13.0",
},
},
},
override: nil,
expLabels: map[string]string{"serving.knative.dev/release": "v0.13.0", "istio-injection": "enabled"},
expAnnotations: nil,
}, {
name: "Override both labels and annotations",
namespace: &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "knative-serving",
},
},
override: &base.NamespaceConfiguration{
Labels: map[string]string{"c1": "d1", "j": "k"},
Annotations: map[string]string{"c": "d", "x": "y"},
},
expLabels: map[string]string{"j": "k", "c1": "d1"},
expAnnotations: map[string]string{"x": "y", "c": "d"},
}}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
u := &unstructured.Unstructured{}
err := scheme.Scheme.Convert(test.namespace, u, nil)
if err != nil {
t.Fatalf("Failed to convert namespace to unstructured: %v", err)
}
NamespaceConfigurationTransform(test.override)(u)
got := &corev1.Namespace{}
if err = scheme.Scheme.Convert(u, got, nil); err != nil {
t.Fatalf("Failed to convert unstructured to namespace: %v", err)
}

if diff := cmp.Diff(got.GetLabels(), test.expLabels); diff != "" {
t.Fatalf("Unexpected labels: %v", diff)
}

if diff := cmp.Diff(got.GetAnnotations(), test.expAnnotations); diff != "" {
t.Fatalf("Unexpected annotations: %v", diff)
}
})
}
}
1 change: 1 addition & 0 deletions pkg/reconciler/common/transformers.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func transformers(ctx context.Context, obj base.KComponent) []mf.Transformer {
return []mf.Transformer{
injectOwner(obj),
mf.InjectNamespace(obj.GetNamespace()),
NamespaceConfigurationTransform(obj.GetSpec().GetNamespaceConfiguration()),
HighAvailabilityTransform(obj),
ImageTransform(obj.GetSpec().GetRegistry(), logger),
JobTransform(obj),
Expand Down

0 comments on commit 36698cc

Please sign in to comment.