nuvolaris/kopf_util.py (73 lines of code) (raw):
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
import json, logging
import nuvolaris.config as cfg
def normalize(item:tuple):
"""
Takes a kopf diff tuple and normalize it by concatenating the modified element into a path attribute
>>> item = ('change', ('spec','component','tls'), 'true', 'false')
>>> print(normalize(item))
{'path': 'spec.component.tls', 'action': 'change', 'old': 'true', 'new': 'false'}
"""
res = {}
path = ""
for path_element in item[1]:
path = f"{path}{path_element}."
res['path']=path[:-1]
res['action']=item[0]
res['old']=item[2]
res['new']=item[3]
return res
def endpoint(response: dict, item: dict):
"""
Forces an update of the apihost endpoint if any of these two attributes has been changed/added
"""
if(item['path']=='spec.components.tls' or item['path']=='spec.nuvolaris.apihost'):
response["endpoint"]="update"
# if we update the endpoint we need to be sure that we update also the static if still active
if cfg.get('components.static'):
response["static"]="update"
def openwhisk(response: dict, item: dict):
"""
Forces an update of Openwhisk if a change in the global spec.config has been detected.
This will force the redeploy of the Openwhisk controller/invoker where supported
"""
if item['path'].find('spec.configs') >= 0:
response["openwhisk"]="update"
def check_component(response: dict, item: dict, cmp_spec, cmp_key):
"""
Check if the componet identified by cmp_spec has been enabled or disabled
"""
if item['path'].find(cmp_spec) > -1:
if(item['new']):
response[cmp_key]="create"
else:
response[cmp_key]="delete"
def check_minio_ingresses(response: dict, item: dict):
"""
Forces an update of minio-ingresses if needed
"""
if(item['path']=='spec.minio.ingress.s3-enabled' or item['path']=='spec.minio.ingress.console-enabled'):
if(item['new']):
response["minio-ingresses"]="update"
def evaluate_differences(response: dict, differences: list):
"""
Iterate over the difference list to find which components the
nuvolaris operator need to deploy/undeploy
"""
for d in differences:
check_component(response, d,"spec.components.couchdb","couchdb")
check_component(response, d,"spec.components.mongodb","mongodb")
check_component(response, d,"spec.components.kafka","kafka")
check_component(response, d,"spec.components.zookeeper","zookeeper")
check_component(response, d,"spec.components.redis","redis")
check_component(response, d,"spec.components.cron","cron")
check_component(response, d,"spec.components.minio","minio")
check_component(response, d,"spec.components.static","static")
check_component(response, d,"spec.components.postgres","postgres")
check_component(response, d,"spec.components.quota","quota")
check_component(response, d,"spec.components.etcd","etcd")
check_component(response, d,"spec.components.milvus","milvus")
openwhisk(response, d)
endpoint(response, d)
check_minio_ingresses(response, d)
def detect_component_changes(kopf_diff):
"""
Analyze a kopf diff object and attempt to establish which component must be added/removed/updated by the operator.
Typically a kopf diff object has a structure like ((action, n-tuple of object or field path, old, new),)
Will return a list of items reporting the specific action to be done on any nuvolaris operator managed component
>>> data = (('change',('spec','components','mongodb'), True, False),('change',('spec','components','tls'), True, False),('change', ('spec','configs','limits','actions','sequence-maxLength'), 10, 20))
>>> what_to_do = detect_component_changes(data)
>>> print(what_to_do['endpoint'])
update
>>> print(what_to_do['openwhisk'])
update
>>> print(what_to_do['mongodb'])
delete
"""
differences = list()
for t in kopf_diff:
logging.info(f"*** processing difference {t}")
differences.append(normalize(t))
response = {}
evaluate_differences(response, differences)
return response
def check_spec_update(response: dict, item: dict, cmp_spec, cmp_key):
"""
Check if the spec identified by cmp_spec has been changed or not
"""
if item['path'].find(cmp_spec) > -1:
response[cmp_key]="update"
def evaluate_wsku_differences(response: dict, differences: list):
"""
Iterate over the difference list to find which part of the wsku resources the
nuvolaris operator wsku handler needs to patch.
"""
for d in differences:
check_spec_update(response, d,"spec.password","password")
check_spec_update(response, d,"spec.redis.quota","quota")
check_spec_update(response, d,"spec.object-storage.quota","quota")
check_spec_update(response, d,"spec.mongodb.quota","quota")
check_spec_update(response, d,"spec.postgres.quota","quota")
def detect_wsku_changes(kopf_diff):
"""
Analyze a kopf diff object and attempt to establish which component must be added/removed/updated by the operator.
Typically a kopf diff object has a structure like ((action, n-tuple of object or field path, old, new),)
Will return a list of items reporting the specific action to be done on any nuvolaris operator managed component
>>> data = (('change',('spec','components','mongodb'), True, False),('change',('spec','components','tls'), True, False),('change', ('spec','configs','limits','actions','sequence-maxLength'), 10, 20))
>>> what_to_do = detect_component_changes(data)
>>> print(what_to_do['endpoint'])
update
>>> print(what_to_do['openwhisk'])
update
>>> print(what_to_do['mongodb'])
delete
"""
differences = list()
for t in kopf_diff:
logging.info(f"*** processing difference {t}")
differences.append(normalize(t))
response = {}
evaluate_wsku_differences(response, differences)
return response