Skip to content

Commit 7fd8f2a

Browse files
committed
Add CRC startup and deployment automation
Signed-off-by: perdasilva <[email protected]>
1 parent d5f87aa commit 7fd8f2a

11 files changed

+503
-4
lines changed

Makefile

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ OPM := $(addprefix bin/, opm)
2727
OLM_CMDS := $(shell go list -mod=vendor $(OLM_PKG)/cmd/...)
2828
PSM_CMD := $(addprefix bin/, psm)
2929
REGISTRY_CMDS := $(addprefix bin/, $(shell ls staging/operator-registry/cmd | grep -v opm))
30+
31+
# Default image tag for build/olm-container and build/registry-container
32+
IMG ?= test:test
33+
3034
# Phony prerequisite for targets that rely on the go build cache to determine staleness.
3135
.PHONY: FORCE
3236
FORCE:
@@ -84,10 +88,10 @@ ifeq ($(shell go env GOARCH),amd64)
8488
endif
8589

8690
build/olm-container:
87-
$(CONTAINER_ENGINE) build -f operator-lifecycle-manager.Dockerfile -t test:test .
91+
$(CONTAINER_ENGINE) build -f operator-lifecycle-manager.Dockerfile -t ${IMG} .
8892

8993
build/registry-container:
90-
$(CONTAINER_ENGINE) build -f operator-registry.Dockerfile -t test:test .
94+
$(CONTAINER_ENGINE) build -f operator-registry.Dockerfile -t ${IMG} .
9195

9296
bin/kubebuilder:
9397
$(ROOT_DIR)/scripts/install_kubebuilder.sh
@@ -162,6 +166,27 @@ verify:
162166
echo "Checking commit integrity"
163167
$(MAKE) verify-commits
164168

169+
.PHONY: crc-start
170+
crc-start:
171+
echo "Starting CRC"
172+
./scripts/crc-start.sh
173+
174+
.PHONY: crc-build
175+
crc-build:
176+
echo "Building olm image"
177+
IMG="olm:test" $(MAKE) build/olm-container
178+
echo "Building opm image"
179+
rm -rf bin
180+
IMG="opm:test" $(MAKE) build/registry-container
181+
182+
.PHONY: crc-deploy
183+
crc-deploy:
184+
echo "Deploying OLM"
185+
./scripts/crc-deploy.sh
186+
187+
.PHONY: crc
188+
crc: crc-start crc-build crc-deploy
189+
165190
.PHONY: help
166191
help: ## Display this help.
167192
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

docs/downstream-ci.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Downstream CI
2+
3+
The CI configuration for each release branch can be found [here](https://github.com/openshift/release/tree/master/ci-operator/config/openshift/operator-framework-olm).
4+
From `4.11` (`master` as of this writing) we've updated the configuration to able to influence CI on a PR basis. An overview of the `ci-operator` (the system used for ci)
5+
can be found [here](https://docs.ci.openshift.org/docs/architecture/ci-operator/).
6+
7+
### Structure
8+
9+
* `.ci-operator.yaml` defines the `build_root_image`. To be ART compliant, the image should come from the [ocp-build-data](https://github.com/openshift/ocp-build-data/) repo
10+
* [openshift-operator-framework-olm-master.yaml](https://github.com/openshift/release/blob/master/ci-operator/config/openshift/operator-framework-olm/openshift-operator-framework-olm-master.yaml) defines the images that are used by ci, produced by ci, and the ci jobs the get executed.
11+
* `base.Dockerfile` defines the image used by ci to execute the ci jobs
12+
13+
From [openshift-operator-framework-olm-master.yaml](https://github.com/openshift/release/blob/master/ci-operator/config/openshift/operator-framework-olm/openshift-operator-framework-olm-master.yaml), we see under the `images` stanza the `ci-image` definition.
14+
It goes from `src` (the `build_root_image`) to `ci-image` by building `base.Dockerfile` with `src` as the base image.
15+
16+
```
17+
- dockerfile_path: base.Dockerfile
18+
from: src
19+
to: ci-image
20+
```
21+
22+
The image is excluded from promotion, to never be posted up anywhere:
23+
24+
```
25+
promotion:
26+
excluded_images:
27+
- ci-image
28+
```
29+
30+
and each `test` references `ci-image` as the image to be used to the test, e.g.:
31+
32+
```
33+
tests:
34+
- as: verify
35+
commands: make verify
36+
container:
37+
from: ci-image
38+
```
39+
40+
### Updating go versions
41+
42+
All we need to do is update the `build_root_image` referenced in `.ci-operator.yaml` and we may also need to update the `base_images` in [openshift-operator-framework-olm-master.yaml](https://github.com/openshift/release/blob/master/ci-operator/config/openshift/operator-framework-olm/openshift-operator-framework-olm-master.yaml).
43+
44+
**NOTE**: I believe there is some automation that updates the base images, though I don't know. I'll leave this as a questions to the reviewer, and if no one knows, I'll go after it.
45+
46+
### Downstream sync
47+
48+
The complete information about the downstreaming process can be found [here](https://docs.google.com/document/d/139yXeOqAJbV1ndC7Q4NbaOtzbSdNpcuJan0iemORd3g/edit).
49+
50+
TL;DR;
51+
52+
We sync three upstream repositories ([api](https://github.com/operator-framework/api), [registry](https://github.com/operator-framework/operator-registry), [olm](https://github.com/operator-framework/operator-lifecycle-manager)) to the downstream [olm mono-repo](https://github.com/openshift/operator-framework-olm). Commits from the upstream repositories are cherry-picked to the appropriate `staging` directory in the downstream repository. Because this is a monorepo in the `Openshift` GitHub organization, two things need to be remembered:
53+
- we don't pull in upstream `vendor` folder changes
54+
- we don't pull in changes to `OWNERS` files
55+
- after each cherry-pick we execute: `make vendor` and `make manifest` to ensure a) the downstream dependencies are updated b) to ensure any manifest changes are picked up downstream
56+
57+
While manual changes to the `staging` directory should be avoided, there could be instances where there drift between the downstream `staging` directory and the corresponding upstream repository. This can happen due to applying commits out-of-order, e.g. due to feature freeze, etc.
58+
59+
Therefore, after a sync, it is important to manually verify the diff of `staging` and the upstream. Please note, though, that some downstream changes are downstream only. These are, however, few and far between and there are comments to indicate that a block of code is downstream only.
60+
61+
The downstream sync process is facilitated by two scripts: `scripts/sync_get_candidates.sh` and `scripts/sync_pop_candidate.sh`, which compare the upstream remote with the appropriate `staging` directory and gets a stack of commits to sync, and cherry-pick those commits in reverse order. What does this look like in practice:
62+
63+
```bash
64+
# Clone downstream
65+
git clone [email protected]:openshift/operator-framework-olm.git && cd operator-framework-olm
66+
67+
# Add and fetch upstream remotes
68+
git remote add api [email protected]:operator-framework/api.git && git fetch api
69+
git remote add operator-registry [email protected]:operator-framework/operator-registry.git && git fetch operator-registry
70+
git remote add operator-lifecycle-manager [email protected]:operator-framework/operator-lifecycle-manager.git && git fetch operator-lifecycle-manager
71+
72+
# Get upstream commit candidates: ./scripts/sync_get_candidates.sh <api|operator-registry|operator-lifecycle-manager> <branch>
73+
# The shas will be found in ./<api|operator-registry|operator-lifecycle-manager>.cherrypick
74+
./scripts/sync_get_candidates.sh api master
75+
./scripts/sync_get_candidates.sh operator-registry master
76+
./scripts/sync_get_candidates.sh operator-lifecycle-manager master
77+
78+
# Sync upstream commits: ./scripts/sync_pop_candidate.sh <api|operator-registry|operator-lifecycle-manager> [-a]
79+
# Without -a, you'll proceed one commit at a time. With -a the process will conclude once there are no more commits.
80+
# When a cherry pick encounters a conflict the script will stop so you can manually fix it.
81+
sync_pop_candidate.sh operator-lifecycle-manager -a
82+
83+
# When finished
84+
sync_pop_candidate.sh api -a
85+
86+
# When finished
87+
sync_pop_candidate.sh operator-registry -a
88+
89+
# Depending on the changes being pulled in, the order of repos you sync _could_ matter and _could_ leave a commit in an unbuildable state
90+
```
91+
92+
Example:
93+
94+
```bash
95+
$ sync_pop_candidate.sh operator-lifecycle-manager -a
96+
97+
.github/workflows: Enable workflow_dispatch event triggers (#2464)
98+
Author: Tim Flannagan <[email protected]>
99+
Date: Mon Dec 20 15:13:33 2021 -0500
100+
9 files changed, 9 insertions(+), 1 deletion(-)
101+
66 picks remaining (pop_all=true)
102+
popping: 4daeb114ccd56cee7132883325da68c80ba70bed
103+
Auto-merging staging/operator-lifecycle-manager/go.mod
104+
CONFLICT (content): Merge conflict in staging/operator-lifecycle-manager/go.mod
105+
Auto-merging staging/operator-lifecycle-manager/go.sum
106+
CONFLICT (content): Merge conflict in staging/operator-lifecycle-manager/go.sum
107+
CONFLICT (modify/delete): staging/operator-lifecycle-manager/vendor/github.com/operator-framework/api/pkg/validation/doc.go deleted in HEAD and modified in 4daeb114c (chore(api): Vendor the new version of api repo (#2525)). Version 4daeb114c (chore(api): Vendor the new version of api repo (#2525)) of staging/operator-lifecycle-manager/vendor/github.com/operator-framework/api/pkg/validation/doc.go left in tree.
108+
CONFLICT (modify/delete): staging/operator-lifecycle-manager/vendor/modules.txt deleted in HEAD and modified in 4daeb114c (chore(api): Vendor the new version of api repo (#2525)). Version 4daeb114c (chore(api): Vendor the new version of api repo (#2525)) of staging/operator-lifecycle-manager/vendor/modules.txt left in tree.
109+
error: could not apply 4daeb114c... chore(api): Vendor the new version of api repo (#2525)
110+
hint: After resolving the conflicts, mark them with
111+
hint: "git add/rm <pathspec>", then run
112+
hint: "git cherry-pick --continue".
113+
hint: You can instead skip this commit with "git cherry-pick --skip".
114+
hint: To abort and get back to the state before "git cherry-pick",
115+
hint: run "git cherry-pick --abort".
116+
117+
$ rm -rf staging/operator-lifecycle-manager/vendor
118+
119+
# make sure there are no conflics in
120+
# staging/operator-lifecycle-manager/go.mod and go.sum
121+
$ cd staging/operator-lifecycle-manager
122+
$ go mod tidy
123+
$ cd ../../
124+
125+
# now that the conflict is fixed, advance again
126+
$ sync_pop_candidate.sh operator-lifecycle-manager -a
127+
```
128+
129+
### Troubleshooting
130+
131+
#### Running console test locally
132+
133+
The [console](https://github.com/openshift/console) repository contains all instructions you need to execute the console tests locally. The olm console tests can be found [here](https://github.com/openshift/console/tree/master/frontend/packages/operator-lifecycle-manager)

docs/local-testing-with-crc.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Local testing with CRC
2+
3+
We can use CRC as an Openshift-like environment within which to test downstream OLM. [CRC](https://developers.redhat.com/products/codeready-containers/overview)
4+
is a tool for deploying a local Openshift cluster on your laptop.
5+
6+
TL;DR
7+
8+
1. Install [CRC](https://developers.redhat.com/products/codeready-containers/overview)
9+
2. `make crc` to provision a CRC cluster, build OLM, and deploy it on the cluster
10+
3. `make e2e/olm`, i.e., execute e2e tests as you normally would.
11+
12+
#### Gosh darn it, how does it work?
13+
14+
`./scripts/crc-start.sh` is used to provision a crc cluster. `./scripts/crc-deploy.sh` pushes the `olm:test` and `opm:test` to
15+
`image-registry.openshift-image-registry.svc:5000/openshift/olm:test` and `image-registry.openshift-image-registry.svc:5000/openshift/opm:test`
16+
images to the crc image registry under the global project `openshift`. Images in the global project are pullable anywhere in the clusters.
17+
It also generates the olm manifests by applying the `values-crc-e2e.yaml` and other patches (`scripts/*.crc.e2e.patch.yaml`). The manifests are
18+
deleted (in reverse lexical order, i.e. from deployments, to namespaces, to crds) then recreated (in lexical order). Finally, all olm namespaces
19+
pods are killed and the script waits until the olm deployments are available.
20+
21+
All deployments were patched to make `ImagePullPolicy: Always`. This way new image tags don't need to be generated and changes can be applied
22+
by simply killing the pod.
23+
24+
25+
#### Make targets
26+
27+
1. `make crc-start`: provision a crc cluster, if necessary
28+
1. `FORCE_CLEAN=1 make crc-start`: nuke any current installation including cache and current cluster instance
29+
2. `make crc-build`: build olm images with the right tags
30+
3. `make crc-deploy`: generate manifests, upload olm images, deploy olm
31+
1. `SKIP_MANIFESTS=1 make crc-deploy`: skip manifest generation and deployment (only update images)
32+
2. `SKIP_WAIT_READY=1 make crc-deploy`: skip waiting for olm deployments to be available at the end
33+
4. `make crc`: the same as `make crc-start crc-build crc-deploy`
34+
35+
#### Manipulating Resources
36+
37+
If new resources are introduced that require being updated for local deployment (e.g. updating the pod spec image), either
38+
update the e2e-values.yaml at the root, or introduce a yaml patch, e.g. `scripts/psm-operator-deployment.crc.e2e.patch.yaml`
39+
then update `scripts/generate_crd_manifests.sh` to apply it if the `CRC_E2E` environment variable is set.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- command: update
2+
path: spec.jobTemplate.spec.template.spec.containers[0].image
3+
value: image-registry.openshift-image-registry.svc:5000/openshift/olm:test
4+
- command: update
5+
path: spec.jobTemplate.spec.template.spec.containers[0].imagePullPolicy
6+
value: Always

scripts/crc-deploy.sh

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
# This script manages the deployment of downstream olm on a local CRC cluster
6+
# It will deploy the local images: olm:test and opm:test
7+
# Both built with make build/olm-container and build/registry-container respectively
8+
9+
echo "Deploying OLM to CRC"
10+
11+
# push_images opens a kubectl port-forward session to the crc registry service
12+
# appropriately tags the locally build olm images
13+
# and pushes them to the global registry "openshift"
14+
function push_images {
15+
# local images
16+
LOCAL_OLM_IMAGE=${1-olm:test}
17+
LOCAL_OPM_IMAGE=${2-opm:test}
18+
19+
# push images to the global crc registry "openshift"
20+
# so that they can be pulled from any other namespace in the cluster
21+
CRC_GLOBAL_REGISTRY="openshift"
22+
23+
# CRC destined images
24+
CRC_OLM_IMAGE="localhost:5000/${CRC_GLOBAL_REGISTRY}/olm:test"
25+
CRC_OPM_IMAGE="localhost:5000/${CRC_GLOBAL_REGISTRY}/opm:test"
26+
27+
# CRC registry coordinates
28+
OPENSHIFT_REGISTRY_NAMESPACE="openshift-image-registry"
29+
OLM_NAMESPACE="openshift-operator-lifecycle-manager"
30+
IMAGE_REGISTRY_SVC="image-registry"
31+
IMAGE_REGISTRY_PORT=5000
32+
33+
# Create port-forward to CRC registry
34+
kubectl port-forward -n ${OPENSHIFT_REGISTRY_NAMESPACE} svc/${IMAGE_REGISTRY_SVC} ${IMAGE_REGISTRY_PORT}:${IMAGE_REGISTRY_PORT} > /dev/null 2>&1 &
35+
PORT_FWD_PID=$!
36+
37+
# Remember to close the port-forward
38+
trap 'kill "${PORT_FWD_PID}"' EXIT
39+
40+
# give port-forward a second
41+
# I found that without this docker login would not work
42+
# as if it couldn't reach the docker server
43+
sleep 1
44+
45+
# Login to the CRC registry
46+
oc whoami -t | docker login localhost:5000 --username user --password-stdin
47+
48+
# Tag and push olm image
49+
echo "Pushing olm image"
50+
docker tag "${LOCAL_OLM_IMAGE}" "${CRC_OLM_IMAGE}"
51+
docker push "${CRC_OLM_IMAGE}"
52+
53+
# Tag and push registry image
54+
echo "Pushing registry image"
55+
docker tag "${LOCAL_OPM_IMAGE}" "${CRC_OPM_IMAGE}"
56+
docker push "${CRC_OPM_IMAGE}"
57+
}
58+
59+
# Set kubeconfig to CRC if necessary
60+
export KUBECONFIG=${KUBECONFIG:-${HOME}/.crc/machines/crc/kubeconfig}
61+
KUBE_ADMIN_LOGIN=$(crc console --credentials -o json | jq -r .clusterConfig.adminCredentials.username)
62+
KUBE_ADMIN_PASSWORD=$(crc console --credentials -o json | jq -r .clusterConfig.adminCredentials.password)
63+
64+
# login to crc
65+
echo "Logging in as kubeadmin"
66+
oc login -u "${KUBE_ADMIN_LOGIN}" -p "${KUBE_ADMIN_PASSWORD}" > /dev/null
67+
68+
# Scale down CVO to stop changes from returning to stock configuration
69+
echo "Scaling down CVO"
70+
oc scale --replicas 0 -n openshift-cluster-version deployments/cluster-version-operator
71+
72+
# push olm images to crc global repository
73+
push_images olm:test opm:test
74+
75+
SKIP_MANIFESTS=${SKIP_MANIFESTS:-0}
76+
if [ "${SKIP_MANIFESTS}" = 0 ]; then
77+
# Build e2e manifests
78+
echo "Generating manifests"
79+
CRC_E2E=1 ./scripts/generate_crds_manifests.sh
80+
81+
# Use the numbered ordering in the manifest file names to delete and deploy the manifests in order
82+
# First in reverse with sort -r to delete then in order to recreate
83+
echo "Deploying OLM"
84+
find_flags=(-regex ".*\.yaml" -not -regex ".*\.removed\.yaml" -not -regex ".*\.ibm-cloud-managed\.yaml")
85+
86+
echo "Replacing manifests"
87+
find manifests "${find_flags[@]}" | while read -r manifest; do
88+
echo "Deleting ${manifest}"
89+
set +e
90+
kubectl replace -f "${manifest}"
91+
set -e
92+
done
93+
fi
94+
95+
# Restart olm pods
96+
# This is required because the images were pushed after the olm resources were applied
97+
# So we need to ensure the new images are picked up by the deployments
98+
echo "Restarting OLM pods"
99+
for POD in $(oc get pods --no-headers=true -n "${OLM_NAMESPACE}" | awk '{ print $1 }'); do
100+
oc delete pod --ignore-not-found=true -n ${OLM_NAMESPACE} "${POD}"
101+
done
102+
103+
# Wait for deployments to be available
104+
SKIP_WAIT_READY=${SKIP_WAIT_READY:-0}
105+
if [ "${SKIP_WAIT_READY}" = 0 ]; then
106+
echo "Waiting on deployments to be ready"
107+
for DEPLOYMENT in $(oc get deployments --no-headers=true -n "${OLM_NAMESPACE}" | awk '{ print $1 }'); do
108+
echo "Waiting for ${DEPLOYMENT}"
109+
kubectl wait --for=condition=available --timeout=120s "deployment/${DEPLOYMENT}" -n "${OLM_NAMESPACE}"
110+
done
111+
fi
112+
113+
echo "Done"
114+
115+
exit 0

scripts/crc-start.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
# This script manages the creation of the CRC cluster to be used for testing
6+
# Usage: crc-start.sh
7+
# FORCE_CLEAN=1 crc-start.sh will delete any current crc cluster, clear the cache and start a fresh installation
8+
# If CRC is already running, nothing happens
9+
10+
# Check CRC is installed
11+
if ! [ -x "$(command -v crc)" ]; then
12+
echo "Error: CRC is not installed. Go to: https://developers.redhat.com/products/codeready-containers/overview"
13+
exit 1
14+
fi
15+
16+
# Blast CRC if necessary
17+
if [ "${FORCE_CLEAN}" = 1 ]; then
18+
crc delete --clear-cache --force
19+
fi
20+
21+
# Start CRC if necessary
22+
if [ "$(crc status -o json | jq -r .success)" = "false" ] || [ "$(crc status -o json | jq -r .crcStatus)" = "Stopped" ]; then
23+
echo "Setting up CRC"
24+
crc setup
25+
crc start
26+
fi
27+
28+
# Check CRC started successfully
29+
if ! [ "$(crc status -o json | jq -r .crcStatus)" = "Running" ]; then
30+
echo "Error: CRC is unreachable. Please try recreating the cluster."
31+
exit 1
32+
fi
33+
34+
echo "SUCCESS! kubeconfig=${HOME}/.crc/machines/crc/kubeconfig"

0 commit comments

Comments
 (0)