Skip to content

Commit 40ba65c

Browse files
authored
Apply Subscription.Spec.Config.Annotations to Deployments, Pods, ApiServices (#3169)
* Apply Subscription.Spec.Config.Annotations to deployments Signed-off-by: Jacob Floyd <[email protected]> * Apply Subscription.Spec.Config.Annotations to Deployment Pods Signed-off-by: Jacob Floyd <[email protected]> * Apply Subscription.Spec.Config.Annotations to ApiServices Signed-off-by: Jacob Floyd <[email protected]> * Refactor and Test InjectAnnotationsIntoDeployment Signed-off-by: Jacob Floyd <[email protected]> --------- Signed-off-by: Jacob Floyd <[email protected]>
1 parent 6243cd1 commit 40ba65c

File tree

14 files changed

+294
-16
lines changed

14 files changed

+294
-16
lines changed

deploy/chart/crds/0000_50_olm_00-subscriptions.crd.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,11 @@ spec:
524524
topologyKey:
525525
description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed.
526526
type: string
527+
annotations:
528+
description: Annotations is an unstructured key value map stored with each Deployment, Pod, APIService in the Operator. Typically, annotations may be set by external tools to store and retrieve arbitrary metadata. Use this field to pre-define annotations that OLM should add to each of the Subscription's deployments, pods, and apiservices.
529+
type: object
530+
additionalProperties:
531+
type: string
527532
env:
528533
description: Env is a list of environment variables to set in the container. Cannot be updated.
529534
type: array

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ require (
2424
github.com/onsi/gomega v1.29.0
2525
github.com/openshift/api v3.9.0+incompatible
2626
github.com/openshift/client-go v0.0.0-20220525160904-9e1acff93e4a
27-
github.com/operator-framework/api v0.21.0
27+
github.com/operator-framework/api v0.22.0
2828
github.com/operator-framework/operator-registry v1.35.0
2929
github.com/otiai10/copy v1.14.0
3030
github.com/pkg/errors v0.9.1

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -672,8 +672,8 @@ github.com/openshift/api v0.0.0-20221021112143-4226c2167e40 h1:PxjGCA72RtsdHWToZ
672672
github.com/openshift/api v0.0.0-20221021112143-4226c2167e40/go.mod h1:aQ6LDasvHMvHZXqLHnX2GRmnfTWCF/iIwz8EMTTIE9A=
673673
github.com/openshift/client-go v0.0.0-20221019143426-16aed247da5c h1:CV76yFOTXmq9VciBR3Bve5ZWzSxdft7gaMVB3kS0rwg=
674674
github.com/openshift/client-go v0.0.0-20221019143426-16aed247da5c/go.mod h1:lFMO8mLHXWFzSdYvGNo8ivF9SfF6zInA8ZGw4phRnUE=
675-
github.com/operator-framework/api v0.21.0 h1:89LhqGTLskxpPR4siEaorkF9PY3KLI51S5mFxP6q1G8=
676-
github.com/operator-framework/api v0.21.0/go.mod h1:3tsDLxXChMY1KgxO5v1CZQogHNQCIMy14YXkXqA5lT4=
675+
github.com/operator-framework/api v0.22.0 h1:UZSn+iaQih4rCReezOnWTTJkMyawwV5iLnIItaOzytY=
676+
github.com/operator-framework/api v0.22.0/go.mod h1:p/7YDbr+n4fmESfZ47yLAV1SvkfE6NU2aX8KhcfI0GA=
677677
github.com/operator-framework/operator-registry v1.35.0 h1:BvytqLwhgb0QiAkEODEKXq3vc2vWiHQq0IlofvFA+OI=
678678
github.com/operator-framework/operator-registry v1.35.0/go.mod h1:foC+NO1V9JuDIOk3pjjlrPE0KVkq09m8oDVRz/a/nFA=
679679
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=

pkg/controller/install/apiservice.go

+32-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
log "github.com/sirupsen/logrus"
99
apierrors "k8s.io/apimachinery/pkg/api/errors"
1010
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/apimachinery/pkg/labels"
1112
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
1213

1314
"github.com/operator-framework/api/pkg/operators/v1alpha1"
@@ -40,6 +41,16 @@ func (i *StrategyDeploymentInstaller) createOrUpdateAPIService(caPEM []byte, des
4041
},
4142
}
4243
apiService.SetName(apiServiceName)
44+
45+
ownerSubscription, err := i.findOwnerSubscription()
46+
if err != nil {
47+
return err
48+
} else if ownerSubscription == nil {
49+
// This is not an error. For example, the PackageServer CSV in OLM is created without a Subscription.
50+
logger.Debugf("failed to get the owner subscription csv=%s", i.owner.GetName())
51+
} else if ownerSubscription.Spec.Config != nil {
52+
apiService.SetAnnotations(ownerSubscription.Spec.Config.Annotations)
53+
}
4354
} else {
4455
apiService = apiService.DeepCopy()
4556
csv, ok := i.owner.(*v1alpha1.ClusterServiceVersion)
@@ -101,10 +112,10 @@ func IsAPIServiceAdoptable(opLister operatorlister.OperatorLister, target *v1alp
101112
return
102113
}
103114

104-
labels := apiService.GetLabels()
105-
ownerKind := labels[ownerutil.OwnerKind]
106-
ownerName := labels[ownerutil.OwnerKey]
107-
ownerNamespace := labels[ownerutil.OwnerNamespaceKey]
115+
apiServiceLabels := apiService.GetLabels()
116+
ownerKind := apiServiceLabels[ownerutil.OwnerKind]
117+
ownerName := apiServiceLabels[ownerutil.OwnerKey]
118+
ownerNamespace := apiServiceLabels[ownerutil.OwnerNamespaceKey]
108119

109120
if ownerKind == "" || ownerNamespace == "" || ownerName == "" {
110121
return
@@ -285,3 +296,20 @@ func legacyAPIServiceNameToServiceName(apiServiceName string) string {
285296
// Replace all '.'s with "-"s to convert to a DNS-1035 label
286297
return strings.Replace(apiServiceName, ".", "-", -1)
287298
}
299+
300+
func (i *StrategyDeploymentInstaller) findOwnerSubscription() (*v1alpha1.Subscription, error) {
301+
list, listErr := i.strategyClient.GetOpLister().OperatorsV1alpha1().SubscriptionLister().Subscriptions(i.owner.GetNamespace()).List(labels.Everything())
302+
if listErr != nil {
303+
err := fmt.Errorf("failed to list subscription namespace=%s - %v", i.owner.GetNamespace(), listErr)
304+
return nil, err
305+
}
306+
307+
for idx := range list {
308+
sub := list[idx]
309+
if sub.Status.InstalledCSV == i.owner.GetName() {
310+
return sub, nil
311+
}
312+
}
313+
314+
return nil, nil
315+
}

pkg/controller/install/deployment.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func (i *StrategyDeploymentInstaller) deploymentForSpec(name string, spec appsv1
144144
for k, v := range dep.Spec.Template.GetAnnotations() {
145145
annotations[k] = v
146146
}
147-
for k, v := range i.templateAnnotations {
147+
for k, v := range i.templateAnnotations { // templateAnnotations comes from CSV.Annotations
148148
annotations[k] = v
149149
}
150150
dep.Spec.Template.SetAnnotations(annotations)
@@ -159,6 +159,7 @@ func (i *StrategyDeploymentInstaller) deploymentForSpec(name string, spec appsv1
159159
ownerutil.AddNonBlockingOwner(dep, i.owner)
160160
ownerutil.AddOwnerLabelsForKind(dep, i.owner, v1alpha1.ClusterServiceVersionKind)
161161

162+
// Any admin-provided config (Subscription.Spec.Config) gets injected here.
162163
if applyErr := i.initializers.Apply(dep); applyErr != nil {
163164
err = applyErr
164165
return

pkg/controller/operators/olm/overrides/config.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type operatorConfig struct {
1616
logger *logrus.Logger
1717
}
1818

19-
func (o *operatorConfig) GetConfigOverrides(ownerCSV ownerutil.Owner) (envVarOverrides []corev1.EnvVar, volumeOverrides []corev1.Volume, volumeMountOverrides []corev1.VolumeMount, tolerationOverrides []corev1.Toleration, resourcesOverride *corev1.ResourceRequirements, nodeSelectorOverride map[string]string, affinity *corev1.Affinity, err error) {
19+
func (o *operatorConfig) GetConfigOverrides(ownerCSV ownerutil.Owner) (envVarOverrides []corev1.EnvVar, volumeOverrides []corev1.Volume, volumeMountOverrides []corev1.VolumeMount, tolerationOverrides []corev1.Toleration, resourcesOverride *corev1.ResourceRequirements, nodeSelectorOverride map[string]string, affinity *corev1.Affinity, annotations map[string]string, err error) {
2020
list, listErr := o.lister.OperatorsV1alpha1().SubscriptionLister().Subscriptions(ownerCSV.GetNamespace()).List(labels.Everything())
2121
if listErr != nil {
2222
err = fmt.Errorf("failed to list subscription namespace=%s - %v", ownerCSV.GetNamespace(), listErr)
@@ -41,6 +41,7 @@ func (o *operatorConfig) GetConfigOverrides(ownerCSV ownerutil.Owner) (envVarOve
4141
resourcesOverride = owner.Spec.Config.Resources
4242
nodeSelectorOverride = owner.Spec.Config.NodeSelector
4343
affinity = owner.Spec.Config.Affinity
44+
annotations = owner.Spec.Config.Annotations
4445

4546
return
4647
}

pkg/controller/operators/olm/overrides/initializer.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (d *DeploymentInitializer) initialize(ownerCSV ownerutil.Owner, deployment
4545
var envVarOverrides, proxyEnvVar, merged []corev1.EnvVar
4646
var err error
4747

48-
envVarOverrides, volumeOverrides, volumeMountOverrides, tolerationOverrides, resourcesOverride, nodeSelectorOverride, affinity, err := d.config.GetConfigOverrides(ownerCSV)
48+
envVarOverrides, volumeOverrides, volumeMountOverrides, tolerationOverrides, resourcesOverride, nodeSelectorOverride, affinity, annotations, err := d.config.GetConfigOverrides(ownerCSV)
4949
if err != nil {
5050
err = fmt.Errorf("failed to get subscription pod configuration - %v", err)
5151
return err
@@ -96,6 +96,10 @@ func (d *DeploymentInitializer) initialize(ownerCSV ownerutil.Owner, deployment
9696
return fmt.Errorf("failed to inject affinity into deployment spec name=%s - %s", deployment.Name, err)
9797
}
9898

99+
if err = inject.InjectAnnotationsIntoDeployment(deployment, annotations); err != nil {
100+
return fmt.Errorf("failed to inject annotations into deployment spec name=%s - %s", deployment.Name, err)
101+
}
102+
99103
return nil
100104
}
101105

pkg/controller/operators/olm/overrides/inject/inject.go

+40-3
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import (
44
"errors"
55
"reflect"
66

7+
appsv1 "k8s.io/api/apps/v1"
78
corev1 "k8s.io/api/core/v1"
89
)
910

1011
// InjectEnvIntoDeployment injects the proxy env variables specified in
1112
// proxyEnvVar into the container(s) of the given PodSpec.
1213
//
1314
// If any Container in PodSpec already defines an env variable of the same name
14-
// as any of the proxy env variables then it
15+
// as any of the proxy env variables then it will be overwritten.
1516
func InjectEnvIntoDeployment(podSpec *corev1.PodSpec, envVars []corev1.EnvVar) error {
1617
if podSpec == nil {
1718
return errors.New("no pod spec provided")
@@ -217,8 +218,7 @@ func InjectResourcesIntoDeployment(podSpec *corev1.PodSpec, resources *corev1.Re
217218
// InjectNodeSelectorIntoDeployment injects the provided NodeSelector
218219
// into the container(s) of the given PodSpec.
219220
//
220-
// If any Container in PodSpec already defines a NodeSelector it will
221-
// be overwritten.
221+
// If the PodSpec already defines a NodeSelector it will be overwritten.
222222
func InjectNodeSelectorIntoDeployment(podSpec *corev1.PodSpec, nodeSelector map[string]string) error {
223223
if podSpec == nil {
224224
return errors.New("no pod spec provided")
@@ -300,3 +300,40 @@ func OverrideDeploymentAffinity(podSpec *corev1.PodSpec, affinity *corev1.Affini
300300

301301
return nil
302302
}
303+
304+
// InjectAnnotationsIntoDeployment injects the provided Annotations
305+
// into the container(s) of the given PodSpec.
306+
//
307+
// If the Deployment already defines any Annotations they will NOT be overwritten.
308+
func InjectAnnotationsIntoDeployment(deployment *appsv1.Deployment, newAnnotations map[string]string) error {
309+
if deployment == nil {
310+
return errors.New("no deployment provided")
311+
}
312+
313+
// do not override existing annotations
314+
if newAnnotations != nil {
315+
mergedDeploymentAnnotations := map[string]string{}
316+
mergedPodAnnotations := map[string]string{}
317+
318+
// add newAnnotations first to prevent them from overwriting the defaults
319+
for k, v := range newAnnotations {
320+
mergedDeploymentAnnotations[k] = v
321+
mergedPodAnnotations[k] = v
322+
}
323+
324+
// then replace any duplicate annotations with the default annotation
325+
for k, v := range deployment.Annotations {
326+
mergedDeploymentAnnotations[k] = v
327+
}
328+
for k, v := range deployment.Spec.Template.GetAnnotations() {
329+
mergedPodAnnotations[k] = v
330+
}
331+
332+
// Inject Into Deployment
333+
deployment.SetAnnotations(mergedDeploymentAnnotations)
334+
// Inject Into Pod Spec
335+
deployment.Spec.Template.SetAnnotations(mergedPodAnnotations)
336+
}
337+
338+
return nil
339+
}

0 commit comments

Comments
 (0)