Skip to content

Commit 47c2bc7

Browse files
authored
Generate catalog/subscriptions from olm bundles for openshift (#39)
* script to generate catalog from olm bundles * improved script * remove hard-coded version from catalog-source, add deploy step * fixed repo name
1 parent bb1a20c commit 47c2bc7

File tree

8 files changed

+361
-0
lines changed

8 files changed

+361
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
/.idea
2+
olm/catalog.Dockerfile
3+
olm/catalog/
4+
olm/subscriptions/
5+
olm/catalog-source.yaml

olm/README.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# OLM installation files
2+
3+
The following steps describe how to install a Stackable operator - in this, the operator for Apache Zookeeper - using the [Operator Lifecycle Manager](https://olm.operatorframework.io/) (OLM).
4+
5+
It specifically installs the version 23.1.0 of the operator. Installing additional versions in the future requires generating new bundle images and updating the catalog as described below.
6+
7+
## Usage
8+
9+
Prerequisite is of course a running OpenShift cluster.
10+
11+
First, install the operator using OLM:
12+
13+
kubectl apply -f catalog-source.yaml \
14+
-f operator-group.yaml \
15+
-f subscription.yaml
16+
17+
Then, install the operator dependencies with Helm:
18+
19+
helm install secret-operator stackable/secret-operator
20+
helm install commons-operator stackable/commons-operator
21+
22+
And finally, create an Apache Zookeeper cluster:
23+
24+
kubectl create -f examples/simple-zookeeper-cluster.yaml
25+
26+
NOTE: The `kuttl` tests don't work because they themselves require SCCs which are not available.
27+
28+
## OLM packaging requirements
29+
30+
- An [OpenShift](https://developers.redhat.com/products/openshift-local/overview) cluster.
31+
- [opm](https://github.com/operator-framework/operator-registry/)
32+
- docker and kubectl
33+
- `kubeadmin` access
34+
35+
It was tested with:
36+
37+
$ crc version
38+
WARN A new version (2.5.1) has been published on https://developers.redhat.com/content-gateway/file/pub/openshift-v4/clients/crc/2.5.1/crc-linux-amd64.tar.xz
39+
CRC version: 2.4.1+b877358
40+
OpenShift version: 4.10.14
41+
Podman version: 4.0.2
42+
43+
$ oc version
44+
Client Version: 4.10.14
45+
Server Version: 4.10.14
46+
Kubernetes Version: v1.23.5+b463d71
47+
48+
$ opm version
49+
Version: version.Version{OpmVersion:"v1.23.2", GitCommit:"82505333", BuildDate:"2022-07-04T13:45:39Z", GoOs:"linux", GoArch:"amd64"}
50+
51+
## Open questions
52+
53+
- OLM [doesn't support DaemonSet(s)](https://github.com/operator-framework/operator-lifecycle-manager/issues/1022) and we need them for the secret-operator. Currently we can deploy the secret-operator using Helm but this means we cannot configure the [required](https://olm.operatorframework.io/docs/tasks/creating-operator-manifests/#required-apis) apis of the Zookeeper bundle. What are the consequences for publishing and certification ?
54+
- Here we create a catalog for a single operator. We probably want a catalog for all Stackable operators in the future but this will get large very quickly. Figure out how to handle this. Especially figure out what happens with new versions of the same operator.
55+
- OLM cannot create SecurityContextConstraints objects. The Zookeeper cluster (not the operator) cannot run with the default `restricted` SCC. The current solution is to use the `hostmount-anyuid` SCC for the `zookeeper-clusterrole`. Will this pass the certification process ?
56+
- Everything (catalog, subscription, etc) is installed in the `stackable-operators` namespace. Is this a good idea ?
57+
- The Subscription object uses `installPlanApproval: Automatic` which means the operator is updated automatically for every new version. Is this a good idea?
58+
59+
See the [OLM documentation](https://olm.operatorframework.io/docs/tasks/) for details.
60+
61+
## Build and publish operator bundle image
62+
63+
Each catalog can contain several operator packages, and each operator package can contain multiple channels, each with its own bundles of different versions of the operator.
64+
65+
### Generate operator bundle (this is operator-specific)
66+
67+
opm alpha bundle generate --directory manifests --package zookeeper-operator-package --output-dir bundle --channels stable --default stable
68+
69+
### Build bundle image
70+
71+
docker build -t docker.stackable.tech/stackable/zookeeper-operator-bundle:23.1.0 -f bundle.Dockerfile .
72+
docker push docker.stackable.tech/stackable/zookeeper-operator-bundle:23.1.0
73+
74+
### Validate bundle image
75+
76+
opm alpha bundle validate --tag docker.stackable.tech/stackable/zookeeper-operator-bundle:23.1.0 --image-builder docker
77+
78+
## Create catalog
79+
80+
mkdir catalog
81+
opm generate dockerfile catalog
82+
83+
## Create a package for each operator
84+
85+
opm init zookeeper-operator-package \
86+
--default-channel=stable \
87+
--description=./README.md \
88+
--output yaml > catalog/zookeeper-operator-package.yaml
89+
90+
{
91+
echo "---"
92+
echo "schema: olm.channel"
93+
echo "package: zookeeper-operator-package"
94+
echo "name: stable"
95+
echo "entries:"
96+
echo "- name: zookeeper-operator.v23.1.0"
97+
} >> catalog/zookeeper-operator-package.yaml
98+
99+
NOTE: with the command below we can add the Stackable logo as icon.
100+
101+
# add for each operator...
102+
opm render docker.stackable.tech/stackable/zookeeper-operator-bundle:23.1.0 --output=yaml >> catalog/zookeeper-operator-package.yaml
103+
104+
# ...and then validate the entire catalog
105+
opm validate catalog
106+
107+
The catalog is correct if the command above returns successfully without any message. If the catalog doesn't validate, the operator will not install. Now build a catalog image and push it to the repository:
108+
109+
docker build . -f catalog.Dockerfile -t docker.stackable.tech/stackable/zookeeper-operator-catalog:latest
110+
docker push docker.stackable.tech/stackable/zookeeper-operator-catalog:latest
111+
112+
## Install catalog and the operator group
113+
114+
kubectl apply -f catalog-source.yaml
115+
kubectl apply -f operator-group.yaml
116+
117+
## List available operators
118+
119+
kubectl get packagemanifest -n stackable-operators
120+
121+
## Install operator
122+
123+
kubectl apply -f subscription.yaml

olm/build-catalog.sh

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#!/usr/bin/env bash
2+
# Usage:
3+
# ./olm/build-catalog.sh <release as x.y.z> [-n] [-d] [-s]
4+
# -r <release>: the release number (mandatory). This must be a semver-compatible value to patch-level e.g. 23.1.0.
5+
# -n: create namespace stackable-operators (optional, default is "false").
6+
# -d: deploy catalog and group (optional, default is "false").
7+
# -s: deploy subscriptions (optional, default is "false").
8+
9+
set -euo pipefail
10+
set -x
11+
12+
13+
parse_inputs() {
14+
VERSION=""
15+
NAMESPACE=false
16+
SUBSCRIPTIONS=false
17+
DEPLOY=false
18+
19+
while [[ "$#" -gt 0 ]]; do
20+
case $1 in
21+
-r|--release) VERSION="$2"; shift ;;
22+
-n|--namespace) NAMESPACE=true ;;
23+
-d|--deploy) DEPLOY=true ;;
24+
-s|--subscriptions) SUBSCRIPTIONS=true ;;
25+
*) echo "Unknown parameter passed: $1"; exit 1 ;;
26+
esac
27+
shift
28+
done
29+
}
30+
31+
setup() {
32+
if [ -d "catalog" ]; then
33+
rm -rf catalog
34+
fi
35+
if [ -d "subscriptions" ]; then
36+
rm -rf subscriptions
37+
fi
38+
39+
mkdir -p catalog
40+
mkdir -p subscriptions
41+
rm -f catalog.Dockerfile
42+
rm -f catalog-source.yaml
43+
}
44+
45+
prerequisites() {
46+
echo "Deploy custom scc..."
47+
kubectl apply -f scc.yaml
48+
49+
if $NAMESPACE; then
50+
echo "Creating namespace..."
51+
kubectl apply -f namespace.yaml
52+
fi
53+
}
54+
55+
catalog() {
56+
opm generate dockerfile catalog
57+
58+
# iterate over operators
59+
while IFS="" read -r operator || [ -n "$operator" ]
60+
do
61+
echo "Initiating package: ${operator}"
62+
opm init "${operator}-operator-package" \
63+
--default-channel=stable \
64+
--description=./README.md \
65+
--output yaml > "catalog/${operator}-operator-package.yaml"
66+
echo "Add operator to package: ${operator}"
67+
{
68+
echo "---"
69+
echo "schema: olm.channel"
70+
echo "package: ${operator}-operator-package"
71+
echo "name: stable"
72+
echo "entries:"
73+
echo "- name: ${operator}-operator.v${VERSION}"
74+
} >> "catalog/${operator}-operator-package.yaml"
75+
echo "Render operator: ${operator}"
76+
opm render "docker.stackable.tech/stackable/${operator}-operator-bundle:${VERSION}" --output=yaml >> "catalog/${operator}-operator-package.yaml"
77+
done < <(yq '... comments="" | .operators[] ' config.yaml)
78+
79+
echo "Validating catalog..."
80+
opm validate catalog
81+
82+
echo "Build and push catalog for all operators..."
83+
docker build . -f catalog.Dockerfile -t "docker.stackable.tech/stackable/stackable-operators-catalog:${VERSION}"
84+
docker push "docker.stackable.tech/stackable/stackable-operators-catalog:${VERSION}"
85+
}
86+
87+
subscriptions() {
88+
# iterate over operator list to deploy
89+
while IFS="" read -r operator || [ -n "$operator" ]
90+
do
91+
echo "Deploy subscription: ${operator}"
92+
{
93+
echo "---"
94+
echo "apiVersion: operators.coreos.com/v1alpha1"
95+
echo "kind: Subscription"
96+
echo "metadata:"
97+
echo " name: $operator-operator-subscription"
98+
echo " namespace: stackable-operators"
99+
echo "spec:"
100+
echo " channel: stable"
101+
echo " name: $operator-operator-package"
102+
echo " source: stackable-operators-catalog"
103+
echo " sourceNamespace: stackable-operators"
104+
echo " installPlanApproval: Automatic"
105+
} >> "subscriptions/$operator-subscription.yaml"
106+
if $SUBSCRIPTIONS; then
107+
kubectl apply -f "subscriptions/$operator-subscription.yaml"
108+
fi
109+
done < <(yq '... comments="" | .operators[] ' config.yaml)
110+
}
111+
112+
deploy() {
113+
if $DEPLOY; then
114+
{
115+
echo "---"
116+
echo "apiVersion: operators.coreos.com/v1alpha1"
117+
echo "kind: CatalogSource"
118+
echo "metadata:"
119+
echo " name: stackable-operators-catalog"
120+
echo " namespace: stackable-operators"
121+
echo "spec:"
122+
echo " sourceType: grpc"
123+
echo " image: docker.stackable.tech/stackable/stackable-operators-catalog:${VERSION}"
124+
echo " displayName: Stackable Catalog"
125+
echo " publisher: Stackable GmbH"
126+
echo " updateStrategy:"
127+
echo " registryPoll:"
128+
echo " interval: 10m"
129+
} >> catalog-source.yaml
130+
131+
kubectl apply -f catalog-source.yaml
132+
kubectl apply -f operator-group.yaml
133+
fi
134+
}
135+
136+
main() {
137+
parse_inputs "$@"
138+
if [ -z "${VERSION}" ]; then
139+
echo "Usage: build-catalog.sh -r <release>"
140+
exit 1
141+
fi
142+
143+
pushd olm
144+
145+
setup
146+
prerequisites
147+
catalog
148+
deploy
149+
subscriptions
150+
151+
popd
152+
echo "Deployment successful!"
153+
}
154+
155+
main "$@"

olm/catalog-source.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
apiVersion: operators.coreos.com/v1alpha1
3+
kind: CatalogSource
4+
metadata:
5+
name: stackable-operators-catalog
6+
namespace: stackable-operators
7+
spec:
8+
sourceType: grpc
9+
image: docker.stackable.tech/sandbox/test/stackable-operators-catalog:23.1.0
10+
displayName: Stackable Catalog
11+
publisher: Stackable GmbH
12+
updateStrategy:
13+
registryPoll:
14+
interval: 10m

olm/config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
operators:
3+
- commons
4+
- zookeeper

olm/namespace.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
kind: Namespace
3+
apiVersion: v1
4+
metadata:
5+
name: stackable-operators
6+
labels:
7+
name: stackable-operators
8+

olm/operator-group.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
apiVersion: operators.coreos.com/v1
3+
kind: OperatorGroup
4+
metadata:
5+
name: stackable-operators-group
6+
namespace: stackable-operators
7+
spec:
8+
targetNamespaces:
9+
- stackable-operators

olm/scc.yaml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
apiVersion: security.openshift.io/v1
3+
kind: SecurityContextConstraints
4+
metadata:
5+
name: stackable-platform-scc
6+
annotations:
7+
kubernetes.io/description: |-
8+
stackable-platform-scc is derived from hostmount-anyuid. It provides all the features of the
9+
restricted SCC but allows host mounts and any UID by a pod. This is primarily
10+
used by the persistent volume recycler. WARNING: this SCC allows host file
11+
system access as any UID, including UID 0. Grant with caution.
12+
release.openshift.io/create-only: "true"
13+
allowHostDirVolumePlugin: true
14+
allowHostIPC: false
15+
allowHostNetwork: false
16+
allowHostPID: false
17+
allowHostPorts: false
18+
allowPrivilegeEscalation: true
19+
allowPrivilegedContainer: false
20+
allowedCapabilities: null
21+
defaultAddCapabilities: null
22+
fsGroup:
23+
type: RunAsAny
24+
groups: []
25+
priority: null
26+
readOnlyRootFilesystem: false
27+
requiredDropCapabilities:
28+
- MKNOD
29+
runAsUser:
30+
type: RunAsAny
31+
seLinuxContext:
32+
type: MustRunAs
33+
supplementalGroups:
34+
type: RunAsAny
35+
volumes:
36+
- configMap
37+
- downwardAPI
38+
- emptyDir
39+
- hostPath
40+
- nfs
41+
- persistentVolumeClaim
42+
- projected
43+
- secret
44+
- ephemeral

0 commit comments

Comments
 (0)