k8s: Enable administrator to limit the watched namespace scope

It's desirable to limit the scope of namespaces watched by the
operator to avoid having us poke where we're not wanted.  This also
makes it easier to deploy test instances of the operator without
conflicting with other running instances.

Change-Id: I8800ab036d1936a575f0010615536a5fb58ecb6a
This commit is contained in:
Michael Kelly 2022-11-02 21:29:45 -07:00
parent f8037aaa46
commit 44e0c33a7e
No known key found for this signature in database
GPG Key ID: 77F7FE93040ECF3E
4 changed files with 54 additions and 8 deletions

View File

@ -0,0 +1,13 @@
{{- if .Values.watchNamespaces }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "zuul-operator.fullname" . }}
labels:
{{- include "zuul-operator.labels" . | nindent 4 }}
data:
namespaces: |
{{- range .Values.watchNamespaces }}
{{ . }}
{{- end }}
{{- end }}

View File

@ -48,6 +48,21 @@ spec:
- name: ZUUL_INSTALL_PXC
value: "0"
{{- end }}
{{- if .Values.watchNamespaces }}
- name: ZUUL_NAMESPACE_WATCH_LIST
value: /etc/config/namespaces
{{- end }}
{{- if .Values.watchNamespaces }}
volumeMounts:
- name: config-volume
mountPath: /etc/config
{{- end }}
{{- if .Values.watchNamespaces }}
volumes:
- name: config-volume
configMap:
name: {{ include "zuul-operator.fullname" . }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}

View File

@ -74,4 +74,6 @@ pxc-operator:
enabled: false
# cert manager should be managed by the operator
operatorManaged: false
operatorManaged: false
watchNamespaces: []

View File

@ -64,8 +64,15 @@ def startup(memo, logger, **kwargs):
os.environ.get('ZUUL_INSTALL_CERT_MANAGER', '1')),
'install_pxc': distutils.util.strtobool(
os.environ.get('ZUUL_INSTALL_PXC', '1')),
'ns_watch_list': frozenset(),
}
ns_watch_list_path = os.environ.get('ZUUL_NAMESPACE_WATCH_LIST')
if ns_watch_list_path and os.path.exists(ns_watch_list_path):
with open(ns_watch_list_path) as f:
memo.operator_config['ns_watch_list'] = frozenset(
line.strip() for line in f.readlines())
# Operator handlers (like this one) get a single global memo
# object; resource handlers (like update) get a memo object for
# that specific resource with items shallow-copied from the global
@ -73,6 +80,7 @@ def startup(memo, logger, **kwargs):
#
# Initialize a dictionary here that we will mutate (but never
# overwrite) in all the handlers.
logger.info("Loading config resources")
memo.config_resources = {}
memoize_secrets(memo, logger)
@ -80,11 +88,13 @@ def startup(memo, logger, **kwargs):
def when_update_secret(name, namespace, memo, logger, **_):
logger.info(f"Checking update predicate for {namespace}/{name}")
for resources in memo.config_resources.values():
for resource in resources:
if (resource.namespace == namespace or
resource.resource_name == name):
return True
watch_list = memo.operator_config['ns_watch_list']
if not watch_list or namespace in watch_list:
for resources in memo.config_resources.values():
for resource in resources:
if (resource.namespace == namespace or
resource.resource_name == name):
return True
return False
@ -111,7 +121,13 @@ def update_secret(name, namespace, logger, memo, **kwargs):
zuul.create_nodepool()
@kopf.on.create('zuuls', backoff=10)
def when_update_zuul(name, namespace, memo, logger, **_):
logger.info(f"Checking zuul update predicate for {namespace}/{name}")
watch_list = memo.operator_config['ns_watch_list']
return not watch_list or namespace in watch_list
@kopf.on.create('zuuls', when=when_update_zuul, backoff=10)
def create_fn(spec, name, namespace, logger, memo, **kwargs):
logger.info(f"Create zuul {namespace}/{name}")
@ -138,7 +154,7 @@ def create_fn(spec, name, namespace, logger, memo, **kwargs):
# return {'message': 'hello world'}
@kopf.on.update('zuuls', backoff=10)
@kopf.on.update('zuuls', when=when_update_zuul, backoff=10)
def update_fn(name, namespace, logger, old, new, memo, **kwargs):
logger.info(f"Update zuul {namespace}/{name}")