Skip to content

Commit 4cdd0f9

Browse files
authored
internal/generate: set WATCH_NAMESPACE on namespaced operator CSV's (#3128)
1 parent 87132ce commit 4cdd0f9

File tree

4 files changed

+77
-85
lines changed

4 files changed

+77
-85
lines changed

internal/generate/clusterserviceversion/clusterserviceversion_updaters.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"github.com/operator-framework/operator-registry/pkg/registry"
2727
log "github.com/sirupsen/logrus"
2828
admissionregv1 "k8s.io/api/admissionregistration/v1"
29+
appsv1 "k8s.io/api/apps/v1"
30+
corev1 "k8s.io/api/core/v1"
2931
"k8s.io/apimachinery/pkg/version"
3032

3133
"github.com/operator-framework/operator-sdk/internal/generate/collector"
@@ -39,6 +41,10 @@ func ApplyTo(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersio
3941
return fmt.Errorf("error updating ClusterServiceVersion: %v", err)
4042
}
4143

44+
// Set fields required by namespaced operators. This is a no-op for cluster-
45+
// scoped operators.
46+
setNamespacedFields(csv)
47+
4248
// Sort all updated fields.
4349
sortUpdates(csv)
4450

@@ -111,6 +117,47 @@ func applyDeployments(c *collector.Manifests, strategy *operatorsv1alpha1.Strate
111117
strategy.DeploymentSpecs = depSpecs
112118
}
113119

120+
const (
121+
// WatchNamespaceEnv is a constant for internal use.
122+
WatchNamespaceEnv = "WATCH_NAMESPACE"
123+
// TargetNamespacesRef references the target namespaces a CSV is installed in.
124+
// This is required by legacy project Deployments.
125+
TargetNamespacesRef = "metadata.annotations['olm.targetNamespaces']"
126+
)
127+
128+
// setNamespacedFields sets static fields in a CSV required by namespaced
129+
// operators.
130+
func setNamespacedFields(csv *operatorsv1alpha1.ClusterServiceVersion) {
131+
for _, dep := range csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {
132+
// Set WATCH_NAMESPACE if it exists in a deployment spec..
133+
envVar := newFieldRefEnvVar(WatchNamespaceEnv, TargetNamespacesRef)
134+
setContainerEnvVarIfExists(&dep.Spec, envVar)
135+
}
136+
}
137+
138+
// setContainerEnvVarIfExists overwrites all references to ev.Name with ev.
139+
func setContainerEnvVarIfExists(spec *appsv1.DeploymentSpec, ev corev1.EnvVar) {
140+
for _, c := range spec.Template.Spec.Containers {
141+
for i := 0; i < len(c.Env); i++ {
142+
if c.Env[i].Name == ev.Name {
143+
c.Env[i] = ev
144+
}
145+
}
146+
}
147+
}
148+
149+
// newFieldRefEnvVar creates a new environment variable referencing fieldPath.
150+
func newFieldRefEnvVar(name, fieldPath string) corev1.EnvVar {
151+
return corev1.EnvVar{
152+
Name: name,
153+
ValueFrom: &corev1.EnvVarSource{
154+
FieldRef: &corev1.ObjectFieldSelector{
155+
FieldPath: fieldPath,
156+
},
157+
},
158+
}
159+
}
160+
114161
// applyCustomResourceDefinitions updates csv's customresourcedefinitions.owned
115162
// with CustomResourceDefinitions in the collector.
116163
// customresourcedefinitions.required are left as-is, since they are

internal/generate/olm-catalog/csv.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package olmcatalog
1616

1717
import (
18+
"bytes"
1819
"errors"
1920
"fmt"
2021
"io/ioutil"
@@ -393,7 +394,34 @@ func (g BundleGenerator) updateCSVFromManifests(csv *olmapiv1alpha1.ClusterServi
393394
return fmt.Errorf("error building CSV: %v", err)
394395
}
395396

396-
handleWatchNamespaces(csv)
397+
// Ensure WATCH_NAMESPACE is set.
398+
if err = checkWatchNamespaces(csv); err != nil {
399+
return fmt.Errorf("error checking for WATCH_NAMESPACE: %v", err)
400+
}
401+
402+
return nil
403+
}
397404

405+
// OLM places the set of target namespaces for the operator in
406+
// "metadata.annotations['olm.targetNamespaces']". This value should be
407+
// referenced in either:
408+
// - The DeploymentSpec's pod spec WATCH_NAMESPACE env variable.
409+
// - Some other DeploymentSpec pod spec field.
410+
func checkWatchNamespaces(csv *olmapiv1alpha1.ClusterServiceVersion) error {
411+
envVarValue := clusterserviceversion.TargetNamespacesRef
412+
for _, dep := range csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {
413+
// Make sure "olm.targetNamespaces" is referenced somewhere in dep,
414+
// and emit a warning of not.
415+
b, err := dep.Spec.Template.Marshal()
416+
if err != nil {
417+
return err
418+
}
419+
if !bytes.Contains(b, []byte(envVarValue)) {
420+
log.Warnf("No WATCH_NAMESPACE environment variable nor reference to %q "+
421+
"detected in operator Deployment %s. For compatibility between OLM and a "+
422+
"namespaced operator, your operator must watch namespaces defined in %q",
423+
envVarValue, dep.Name, envVarValue)
424+
}
425+
}
398426
return nil
399427
}

internal/generate/olm-catalog/csv_updaters.go

Lines changed: 0 additions & 83 deletions
This file was deleted.

internal/generate/testdata/clusterserviceversions/newlayout/manifests/memcached-operator.clusterserviceversion.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ spec:
6464
- name: WATCH_NAMESPACE
6565
valueFrom:
6666
fieldRef:
67-
fieldPath: metadata.namespace
67+
fieldPath: metadata.annotations['olm.targetNamespaces']
6868
- name: POD_NAME
6969
valueFrom:
7070
fieldRef:

0 commit comments

Comments
 (0)