The operator is built with kopf
. It is basically a server that will react to events coming from Kubernetes. The main evento to react to is the deployment of a Custom Resource Definition that configures OpenWhisk and all the related components.
All the code is in the package nuvolaris
. Events are handled in main.py
.
Each event handlers uses utility functions you can find the various service specific files like openwhisk
or couchdb
.
In generale the operator react to events and execute kustomizations. To develop,
- you start and test writing a base YAML configuration in code.
- you can then modify this base configuration in code using
kustomize
(wrapped in python) - finally you apply the configuration with
kubectl
(wapped in python)
A good example of how to build a configuration is the following
You start creating a basic definition under deploy
for example couchdb
. All the utils searches set of deployments under some folder under deploy
.
Then you can do this (obvious details omitted)
1 kust = kus.secretLiteral("couchdb-auth", user, pasw)
2 kust += kus.patchTemplate("couchdb", "set-attach.yaml", data)
3 spec = kus.kustom_list("couchdb", kust, templates=["couchdb-init.yaml"], data=data)
4 kube.apply(spec)
In 1
you create a customization to create a secret.
In 2
there is a customization to create a patch
for it. There are a few utility functions for that in the nuvolaris.kustomize
package. Some of them are actually templatized (have Template name) so the actual file is generated expanding a template. All the templates are under nuvolaris/templates
. A templatized configuration uses Jinja2
. When you use templates you also have to provide the data
dictionary for the templates.
-
Once you finisced you generate a configuration to be applied. Usually it is better to be a series of configuration, hence you invoke
kustom_list
. Note that kustom list, in addition to customize a configuration, can also add more configuration in the form of templates. Specificy the templates to use astemplates=templates
and do not forget to providedata=data
to provide data -
Finally you apply the configuration with
kube.apply
- there are more utility functions runningkubectl
in a pythonic way.
There are multiple level of testings
- you first test algorithm with unit tests (
task utest
- I use a lot doctest) - you then test with integration tests without starting the operator (
task itest
) - tests uses ipython and assertions - you can run the operator locally without deploying it (with
task run
) and run taskdeploy
to deploy a test CRD. - you can then deploy in local kind with
task build-and-load
without having to publish it, then execute tests (see the TaskfileTest.yml) - finally you test built the image and publish it with
task image-tag ; git push --tags
, wait it builds and test against real kubernetes, using the Taskfle