diff --git a/README.md b/README.md index 21e014b5..b9bc72c9 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ There are manifests to install the operator under the [`deploy/openshift`](deplo * If deploying to a namespace other than `deployment-validation-operator`, there are commented lines you must change in `deploy/openshift/cluster-role-binding.yaml` and `deploy/openshift/role-binding.yaml` first * Create the service, service account, configmap, roles and role bindings * Create the operator deployment - * **Note that the `nodeAffinity` attribute by default requires a node with the `node-role.kubernetes.io/infra` selector. In common (self-managed) clusters there is usually no such node, so you can remove the `nodeAffinity` attribtue when deploying to those environments.** + * **Note that the `nodeAffinity` attribute by default requires a node with the `node-role.kubernetes.io/infra` selector. In common (self-managed) clusters there is usually no such node, so you can remove the `nodeAffinity` attribute when deploying to those environments.** ``` oc new-project deployment-validation-operator @@ -159,8 +159,6 @@ The end-to-end tests depend on [`ginkgo`](https://onsi.github.io/ginkgo/#install make e2e-test ``` -We use [openshift boilerplate](https://github.com/openshift/boilerplate) to manage our make targets. See this [doc](https://github.com/openshift/boilerplate/blob/master/boilerplate/openshift/golang-osd-operator/README.md) for further information. - The OCP e2e PR checks exist in the [deployment-validation-operator-tests](https://gitlab.cee.redhat.com/ccx/deployment-validation-operator-tests) repository. Tests are developed there and once a new build is done, the image is pushed onto [quay.io](https://quay.io/repository/redhatqe/deployment-validation-operator-tests). This image is then mirrored by the mirroring job in openshift release with this [config](https://github.com/openshift/release/blob/master/core-services/image-mirroring/supplemental-ci-images/mapping_supplemental_ci_images_ci#L22). diff --git a/boilerplate/_data/backing-image-tag b/boilerplate/_data/backing-image-tag deleted file mode 100644 index cb5b3ffc..00000000 --- a/boilerplate/_data/backing-image-tag +++ /dev/null @@ -1 +0,0 @@ -image-v5.0.1 diff --git a/boilerplate/_data/last-boilerplate-commit b/boilerplate/_data/last-boilerplate-commit deleted file mode 100644 index a1c75ff1..00000000 --- a/boilerplate/_data/last-boilerplate-commit +++ /dev/null @@ -1 +0,0 @@ -3ecc810186d436652ece9751ad4d181228fba0bf diff --git a/boilerplate/_lib/boilerplate-commit b/boilerplate/_lib/boilerplate-commit deleted file mode 100755 index 074f74f4..00000000 --- a/boilerplate/_lib/boilerplate-commit +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/env bash - -set -e - -REPO_ROOT=$(git rev-parse --show-toplevel) -source $REPO_ROOT/boilerplate/_lib/common.sh - -tmpd=$(mktemp -d) -trap "rm -fr $tmpd" EXIT -git_status=$tmpd/git_status -bp_log=$tmpd/bp_git_log -bp_clone=$tmpd/bp_git_clone -convention_status=$tmpd/convention_status -commit_message=$tmpd/commit_msg - -# Variables to keep track of what's happening in this commit. Empty -# means we're not doing whatever it is. -#### -# - Bootstrapping: bringing boilerplate into the repo for the first -# time. Nonempty if bootstrapping. -bootstrap= -#### -# - If we were already bootstrapped, and boilerplate-update brought in a -# newer boilerplate commit, we'll put "{from_hash}...{to_hash}" here. -# This should be mutually exclusive with `bootstrap`. -bp_commit_change= -#### -# - Changes in conventions. This is a file containing one line per -# convention indicating what was done in this commit with respect to -# that convention: "Subscribe", "Update", or "No change". (TODO: -# "Unsubscribe".) The file is only empty if update.cfg is -# (substantively) empty. -convention_statuses=$tmpd/convention_statuses ->$convention_statuses -#### - -git status --porcelain > $git_status - -# Bootstrapping includes adding the boilerplate-update target to the -# Makefile and adding boilerplate/update and boilerplate/update.cfg. We -# won't bother with the former. Since the latter are new files in a new -# directory, `git status` will just show the `boilerplate/` directory as -# untracked. -if grep -q '^?? boilerplate/$' $git_status; then - bootstrap=true - -# This wasn't a bootstrap. We can detect it was an update if the -# last-boilerplate-commit file was changed. -elif grep -q '^ M boilerplate/_data/last-boilerplate-commit$' $git_status; then - # Produce a string of the form {old_hash}...{new_hash} - bp_commit_change=$(git diff boilerplate/_data/last-boilerplate-commit | tail -2 | paste -d/ -s - | sed 's/[+-]//g; s,/,...,') - # Handy URL showing the commits and deltas - bp_compare_url="https://github.com/openshift/boilerplate/compare/$bp_commit_change" - # Generate the commit history for this range. This will go in the commit message. - ( - $BOILERPLATE_GIT_CLONE $bp_clone - cd $bp_clone - # Matches promote.sh - git log --no-merges --pretty=format:'commit: %H%nauthor: %an%n%s%n%n%b%n%n' $bp_commit_change > $bp_log - ) - -fi - -# Okay, let's look for convention changes. -# TODO: Handle unsubscribes (not yet handled by the main `update` either). -while read convention junk; do - # TODO: These first few conditions, scrubbing the config file, are - # identical to what's in `update`. It would be lovely to library-ize - # them. However, `update` needs to remain self-contained since it's - # part of the bootstrap process. - - # Skip comment lines (which can have leading whitespace) - if [[ "$convention" == '#'* ]]; then - continue - fi - # Skip blank or whitespace-only lines - if [[ "$convention" == "" ]]; then - continue - fi - # Lines like - # valid/path other_junk - # are not acceptable, unless `other_junk` is a comment - if [[ "$junk" != "" ]] && [[ "$junk" != '#'* ]]; then - echo "Invalid config! Only one convention is allowed per line. Found '$junk'. Ignoring." - # `update` bails for this. We're being a bit more forgiving. - continue - fi - - dir_path="boilerplate/${convention}" - # Make sure the directory exists - if ! [[ -d "$dir_path" ]]; then - echo "Invalid convention directory: '$convention'." - echo "(Could be because we don't handle unsubscribing yet.)" - echo "Ignoring." - # `update` bails for this. We're being a bit more forgiving. - continue - fi - - # Okay, we have a legit convention. Let's see if the current checkout - # touches it - # (Note that we're reusing the same temp file on each iteration.) - git status --porcelain $dir_path > $convention_status - if ! [[ -s $convention_status ]]; then - # No deltas here. - echo "- $convention: No change" >> $convention_statuses - - elif grep -q -v '^??' $convention_status; then - # If there's anything *other than* untracked, this was an update - echo "- $convention: Update" >> $convention_statuses - - else - # If we get here, everything is '^??' (untracked), meaning this is a - # new subscription. (Or, I suppose, the convention was previously - # empty? We'll call it a new subscription anyway.) - echo "- $convention: Subscribe" >> $convention_statuses - fi - -done < boilerplate/update.cfg - -# Let's make sure *something* boilerplate-related is happening here. -if [[ -z "$bootstrap" ]] && [[ -z "$bp_commit_change" ]] && ! grep -v -q "No change" $convention_statuses; then - err "No boilerplate-related activity found in the current checkout!" -fi - -# Okay, we're ready to do this. -# Generate the commit title and branch name indicating the *main* action -# we're taking. This is 'bootstrap' or 'update'; or if we're doing -# neither of those things and only changing config, 'subscribe'. -# => Commit titles will be of one of the following forms: -# "Boilerplate: Bootstrap at {hash}" -# "Boilerplate: Update to {hash}" -# "Boilerplate: Subscribe at {hash}" -# => Branch names will be of the form: -# boilerplate-{bootstrap|update|subscribe}-{N}-{hash} -# where {N} is the number of configured conventions (omitted if zero) -title="Boilerplate:" -branch=boilerplate -if [[ -n "$bootstrap" ]]; then - title="$title Bootstrap at" - branch="$branch-bootstrap" -elif [[ -n "$bp_commit_change" ]]; then - title="$title Update to" - branch="$branch-update" -else - title="$title Subscribe at" - branch="$branch-subscribe" -fi -cur_commit=$(cat boilerplate/_data/last-boilerplate-commit) -title="$title $cur_commit" -echo "$title -" > $commit_message - -if [[ -n "$bootstrap" ]]; then - echo "https://github.com/openshift/boilerplate/commit/$cur_commit ----" >> $commit_message -fi - -echo "Conventions:" >> $commit_message -if [[ -s $convention_statuses ]]; then - cat $convention_statuses >> $commit_message - # Add the number of conventions to the branch name - branch="$branch-"$(wc -l $convention_statuses | sed 's/ .*//') -else - echo " None." >> $commit_message -fi - -branch="$branch-$cur_commit" - -if [[ -n "$bp_commit_change" ]]; then - - echo "--- -$bp_compare_url -" >> $commit_message -cat $bp_log >> $commit_message - -fi - -# TODO: Handle branch name conflict. At the moment, this should really only be -# possible if unsubscribing and subscribing the same number of conventions. -# Since we don't handle unsubscribing (properly), we'll take our chances that -# it "can't" happen for now. -git checkout -b $branch -# We can get away with -A because `update` forces a clean checkout. -git add -A -git commit -F $commit_message -echo "Ready to push branch $branch" diff --git a/boilerplate/_lib/boilerplate.mk b/boilerplate/_lib/boilerplate.mk deleted file mode 100644 index 14294c84..00000000 --- a/boilerplate/_lib/boilerplate.mk +++ /dev/null @@ -1,7 +0,0 @@ -.PHONY: boilerplate-commit -boilerplate-commit: - @boilerplate/_lib/boilerplate-commit - -.PHONY: boilerplate-freeze-check -boilerplate-freeze-check: - @boilerplate/_lib/freeze-check diff --git a/boilerplate/_lib/common.sh b/boilerplate/_lib/common.sh deleted file mode 100755 index 26a10c4c..00000000 --- a/boilerplate/_lib/common.sh +++ /dev/null @@ -1,200 +0,0 @@ -err() { - echo "==ERROR== $@" >&2 - exit 1 -} - -banner() { - echo - echo "==============================" - echo "$@" - echo "==============================" -} - -## osdk_version BINARY -# -# Print the version of the specified operator-sdk BINARY -osdk_version() { - local osdk=$1 - # `operator-sdk version` output looks like - # operator-sdk version: v0.8.2, commit: 28bd2b0d4fd25aa68e15d928ae09d3c18c3b51da - # or - # operator-sdk version: "v0.16.0", commit: "55f1446c5f472e7d8e308dcdf36d0d7fc44fc4fd", go version: "go1.13.8 linux/amd64" - # Peel out the version number, accounting for the optional quotes. - $osdk version | ${SED?} 's/operator-sdk version: "*\([^,"]*\)"*,.*/\1/' -} - -## opm_version BINARY -# -# Print the version of the specified opm BINARY -opm_version() { - local opm=$1 - # `opm version` output looks like: - # Version: version.Version{OpmVersion:"v1.15.2", GitCommit:"fded0bf", BuildDate:"2020-11-18T14:21:24Z", GoOs:"darwin", GoArch:"amd64"} - $opm version | ${SED?} 's/.*OpmVersion:"//;s/".*//' -} - -## grpcurl_version BINARY -# -# Print the version of the specified grpcurl BINARY -grpcurl_version() { - local grpcurl=$1 - # `grpcurl -version` output looks like: grpcurl 1.7.0 - $grpcurl -version 2>&1 | cut -d " " -f 2 -} - -## repo_import REPODIR -# -# Print the qualified org/name of the current repository, e.g. -# "openshift/wizbang-foo-operator". This relies on git remotes being set -# reasonably. -repo_name() { - # Just strip off the first component of the import-ish path - repo_import $1 | ${SED?} 's,^[^/]*/,,' -} - -## repo_import REPODIR -# -# Print the go import-ish path to the current repository, e.g. -# "github.com/openshift/wizbang-foo-operator". This relies on git -# remotes being set reasonably. -repo_import() { - # Account for remotes which are - # - upstream or origin - # - ssh ("git@host.com:org/name.git") or https ("https://host.com/org/name.git") - (git -C $1 config --get remote.upstream.url || git -C $1 config --get remote.origin.url) | ${SED?} 's,git@\([^:]*\):,\1/,; s,https://,,; s/\.git$//' -} - -## current_branch REPO -# -# Outputs the name of the current branch in the REPO directory -current_branch() { - ( - cd $1 - git rev-parse --abbrev-ref HEAD - ) -} - -## image_exits_in_repo IMAGE_URI -# -# Checks whether IMAGE_URI -- e.g. quay.io/app-sre/osd-metrics-exporter:abcd123 -# -- exists in the remote repository. -# If so, returns success. -# If the image does not exist, but the query was otherwise successful, returns -# failure. -# If the query fails for any reason, prints an error and *exits* nonzero. -image_exists_in_repo() { - local image_uri=$1 - local output - local rc - - local skopeo_stderr=$(mktemp) - - output=$(skopeo inspect docker://${image_uri} 2>$skopeo_stderr) - rc=$? - # So we can delete the temp file right away... - stderr=$(cat $skopeo_stderr) - rm -f $skopeo_stderr - if [[ $rc -eq 0 ]]; then - # The image exists. Sanity check the output. - local digest=$(echo $output | jq -r .Digest) - if [[ -z "$digest" ]]; then - echo "Unexpected error: skopeo inspect succeeded, but output contained no .Digest" - echo "Here's the output:" - echo "$output" - echo "...and stderr:" - echo "$stderr" - exit 1 - fi - echo "Image ${image_uri} exists with digest $digest." - return 0 - elif [[ "$output" == *"manifest unknown"* || "$stderr" == *"manifest unknown"* ]]; then - # We were able to talk to the repository, but the tag doesn't exist. - # This is the normal "green field" case. - echo "Image ${image_uri} does not exist in the repository." - return 1 - elif [[ "$output" == *"manifest unknown"* || "$stderr" == *"was deleted or has expired"* ]]; then - # This should be rare, but accounts for cases where we had to - # manually delete an image. - echo "Image ${image_uri} was deleted from the repository." - echo "Proceeding as if it never existed." - return 1 - else - # Any other error. For example: - # - "unauthorized: access to the requested resource is not - # authorized". This happens not just on auth errors, but if we - # reference a repository that doesn't exist. - # - "no such host". - # - Network or other infrastructure failures. - # In all these cases, we want to bail, because we don't know whether - # the image exists (and we'd likely fail to push it anyway). - echo "Error querying the repository for ${image_uri}:" - echo "stdout: $output" - echo "stderr: $stderr" - exit 1 - fi -} - -if [ "$BOILERPLATE_SET_X" ]; then - set -x -fi - -# Only used for error messages -_lib=${BASH_SOURCE##*/} - -# When this lib is sourced (which is what it's designed for), $0 is the -# script that did the sourcing. -SOURCER=$(realpath $0) -[[ -n "$SOURCER" ]] || err "$_lib couldn't discover where it was sourced from" - -HERE=${SOURCER%/*} -[[ -n "$HERE" ]] || err "$_lib failed to discover the dirname of sourcer at $SOURCER" - -REPO_ROOT=$(git rev-parse --show-toplevel) -[[ -n "$REPO_ROOT" ]] || err "$_lib couldn't discover the repo root" - -CONVENTION_ROOT=$REPO_ROOT/boilerplate -[[ -d "$CONVENTION_ROOT" ]] || err "$CONVENTION_ROOT: not a directory" - -# Were we sourced from within a convention? -if [[ "$HERE" == "$CONVENTION_ROOT/"* ]]; then - # Okay, figure out the name of the convention - CONVENTION_NAME=${HERE#$CONVENTION_ROOT/} - # If we got here, we really expected to be able to identify the - # convention name. - [[ -n "$CONVENTION_NAME" ]] || err "$_lib couldn't discover the name of the sourcing convention" -fi - -# Set SED variable -if LANG=C sed --help 2>&1 | grep -q GNU; then - SED="sed" -elif command -v gsed &>/dev/null; then - SED="gsed" -else - echo "Failed to find GNU sed as sed or gsed. If you are on Mac: brew install gnu-sed." >&2 - exit 1 -fi - -if [ -z "$BOILERPLATE_GIT_REPO" ]; then - export BOILERPLATE_GIT_REPO=https://github.com/openshift/boilerplate.git -fi -if [ -z "$BOILERPLATE_GIT_CLONE" ]; then - export BOILERPLATE_GIT_CLONE="git clone $BOILERPLATE_GIT_REPO" -fi - -# The namespace of the ImageStream by which prow will import the image. -IMAGE_NAMESPACE=openshift -IMAGE_NAME=boilerplate -# LATEST_IMAGE_TAG may be set manually or by `update`, in which case -# that's the value we want to use. -if [[ -z "$LATEST_IMAGE_TAG" ]]; then - # (Non-ancient) consumers will have the tag in this file. - if [[ -f ${CONVENTION_ROOT}/_data/backing-image-tag ]]; then - LATEST_IMAGE_TAG=$(cat ${CONVENTION_ROOT}/_data/backing-image-tag) - - # In boilerplate itself, we can discover the latest from git. - elif [[ $(repo_name .) == openshift/boilerplate ]]; then - LATEST_IMAGE_TAG=$(git describe --tags --abbrev=0 --match image-v*) - fi -fi -# The public image location -IMAGE_PULL_PATH=${IMAGE_PULL_PATH:-quay.io/app-sre/$IMAGE_NAME:$LATEST_IMAGE_TAG} diff --git a/boilerplate/_lib/container-make b/boilerplate/_lib/container-make deleted file mode 100755 index e847e3a8..00000000 --- a/boilerplate/_lib/container-make +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$1" == "-h"* ]] || [[ "$1" == "--h"* ]]; then - echo "Usage: $0 {arguments to the real 'make'}" - echo "Runs 'make' in the boilerplate backing container." - echo "If the command fails, starts a shell in the container so you can debug." - exit -1 -fi - -source ${0%/*}/common.sh - -CONTAINER_ENGINE="${CONTAINER_ENGINE:-$(command -v podman || command -v docker)}" -[[ -n "$CONTAINER_ENGINE" ]] || err "Couldn't find a container engine. Are you already in a container?" - -# Make sure the mount inside the container is named in such a way that -# - openapi-gen (which relies on GOPATH) produces absolute paths; and -# - other go-ish paths are writeable, e.g. for `go mod download`. -CONTAINER_MOUNT=/go/src/$(repo_import $REPO_ROOT) - -# First set up a detached container with the repo mounted. -banner "Starting the container" -CE_OPTS="--platform=linux/amd64" -if [[ "${CONTAINER_ENGINE##*/}" == "podman" ]]; then - CE_OPTS="${CE_OPTS} --userns keep-id" -fi -if [[ "${CONTAINER_ENGINE##*/}" == "podman" ]] && [[ $OSTYPE == *"linux"* ]]; then - CE_OPTS="${CE_OPTS} -v $REPO_ROOT:$CONTAINER_MOUNT:Z" -else - CE_OPTS="${CE_OPTS} -v $REPO_ROOT:$CONTAINER_MOUNT" -fi -container_id=$($CONTAINER_ENGINE run -d ${CE_OPTS} $IMAGE_PULL_PATH sleep infinity) - -if [[ $? -ne 0 ]] || [[ -z "$container_id" ]]; then - err "Couldn't start detached container" -fi - -# Now run our `make` command in it with the right UID and working directory -args="exec -it -u $(id -u):0 -w $CONTAINER_MOUNT $container_id" -banner "Running: make $@" -$CONTAINER_ENGINE $args make "$@" -rc=$? - -# If it failed, drop into the container in a shell -if [[ $rc -ne 0 ]]; then - banner "The 'make' command failed! Starting a shell in the container for debugging. Just 'exit' when done." - $CONTAINER_ENGINE $args /bin/bash -fi - -# Finally, remove the container -banner "Cleaning up the container" -$CONTAINER_ENGINE rm -f $container_id >/dev/null diff --git a/boilerplate/_lib/freeze-check b/boilerplate/_lib/freeze-check deleted file mode 100755 index 080629f5..00000000 --- a/boilerplate/_lib/freeze-check +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env bash - -# NOTE: For security reasons, everything imported or invoked (even -# indirectly) by this script should be audited for vulnerabilities and -# explicitly excluded from `linguist-generated` in the consuming -# repository's .gitattributes. In other words, we want PRs to show -# deltas to this script and all its dependencies by default so that -# attempts to inject or circumvent code are visible. - -set -e - -REPO_ROOT=$(git rev-parse --show-toplevel) -# Hardcoded rather than sourced to reduce attack surface. -BOILERPLATE_GIT_REPO=https://github.com/openshift/boilerplate.git - -# Validate that no subscribed boilerplate artifacts have been changed. -# PR checks may wish to gate on this. - -# This works by grabbing the commit hash of the boilerplate repository -# at which the last update was applied, running the main `update` driver -# against that, and failing if there's a resulting diff. - -# If we can't tell what that commit was, we must assume this is the -# first update, and we'll (noisily) "succeed". - -# Note that this ought to work when you've just committed an update, -# even if you've changed your update.cfg beforehand. We're basically -# making sure you didn't muck with anything after updating. - -# For this to work, you have to be starting from a clean repository -# state (any changes committed). -# TODO(efried): This is not ideal -- it would be nice if I could check -# this before committing my changes -- but how would that work? Diff to -# a file, create a temporary commit, run the rest, remove the commit, -# and reapply the diff? Messy and error-prone -- and I would be -# seriously ticked off if something went wrong and lost my in-flight -# changes. -if ! [ -z "$(git status --porcelain -- ':!build/Dockerfile*')" ]; then - echo "Can't validate boilerplate in a dirty repository. Please commit your changes and try again." >&2 - exit 1 -fi - -# We glean the last boilerplate commit from the -# last-boilerplate-commit file, which gets laid down by the main -# `update` driver each time it runs. -LBCF=${REPO_ROOT}/boilerplate/_data/last-boilerplate-commit -if ! [[ -f "$LBCF" ]]; then - echo "Couldn't discover last boilerplate commit! Assuming you're bootstrapping." - exit 0 -fi -LBC=$(cat $LBCF) - -# Download just that commit -echo "Fetching $LBC from $BOILERPLATE_GIT_REPO" -# boilerplate/update cleans up this temp dir -TMPD=$(mktemp -d) -cd $TMPD -git init -# TODO(efried): DRY this remote. Make it configurable? -git remote add origin $BOILERPLATE_GIT_REPO -git fetch origin $(cat $LBCF) --tags -git reset --hard FETCH_HEAD - -# Now invoke the update script, overriding the source repository we've -# just downloaded at the appropriate commit. -# We invoke the script explicitly rather than via the make target to -# close a security hole whereby the latter is overridden. -echo "Running update" -cd $REPO_ROOT -BOILERPLATE_GIT_CLONE="git clone $TMPD" boilerplate/update - -# Okay, if anything has changed, that's bad. -if [[ $(git status --porcelain -- ':!build/Dockerfile*' | wc -l) -ne 0 ]]; then - echo "Your boilerplate is dirty!" >&2 - git status --porcelain -- ':!build/Dockerfile*' - exit 1 -fi - -echo "Your boilerplate is clean!" -exit 0 diff --git a/boilerplate/_lib/release.sh b/boilerplate/_lib/release.sh deleted file mode 100755 index 3a98c935..00000000 --- a/boilerplate/_lib/release.sh +++ /dev/null @@ -1,129 +0,0 @@ -# Helpers and variables for dealing with openshift/release - -# NOTE: This library is sourced from user-run scripts. It should not be -# sourced in CI, as it relies on git config that's not necessarily -# present there. - -RELEASE_REPO=openshift/release - -## Information about the boilerplate consumer -# E.g. "openshift/my-wizbang-operator" -CONSUMER=$(repo_name .) -[[ -z "$CONSUMER" ]] && err " -Failed to determine current repository name" -# -# E.g. "openshift" -CONSUMER_ORG=${CONSUMER%/*} -[[ -z "$CONSUMER_ORG" ]] && err " -Failed to determine consumer org" -# -# E.g. "my-wizbang-operator" -CONSUMER_NAME=${CONSUMER#*/} -[[ -z "$CONSUMER_NAME" ]] && err " -Failed to determine consumer name" -# -# E.g. "master" -# This will produce something like refs/remotes/origin/master -DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/upstream/HEAD 2>/dev/null || git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || echo defaulting/to/master) -# Strip off refs/remotes/{upstream|origin}/ -DEFAULT_BRANCH=${DEFAULT_BRANCH##*/} -[[ -z "$DEFAULT_BRANCH" ]] && err " -Failed to determine default branch name" - -## release_process_args "$@" -# -# This is for use by commands expecting one optional argument which is -# the file system path to a clone of the $RELEASE_REPO. -# -# Will invoke `usage` -- which must be defined by the caller -- if -# the wrong number of arguments are received, or if the single argument -# is `help` or a flag. -# -# If exactly one argument is specified and it is valid, it is assigned -# to the global RELEASE_CLONE variable. -release_process_args() { - if [[ $# -eq 1 ]]; then - # Special cases for usage queries - if [[ "$1" == '-'* ]] || [[ "$1" == help ]]; then - usage - fi - - [[ -d $1 ]] || err " - $1: Not a directory." - - [[ $(repo_name $1) == "$RELEASE_REPO" ]] || err " - $1 is not a clone of $RELEASE_REPO; or its 'origin' remote is not set properly." - - # Got a usable clone of openshift/release - RELEASE_CLONE="$1" - - elif [[ $# -ne 0 ]]; then - usage - fi -} - -## release_validate_invocation -# -# Make sure we were called from a reasonable place, that being: -# - A boilerplate consumer -# - ...that's actually subscribed to a convention -# - ...containing the script being invoked -release_validate_invocation() { - # Make sure we were invoked from a boilerplate consumer. - [[ -z "$CONVENTION_NAME" ]] && err " - $cmd must be invoked from a consumer of an appropriate convention. Where did you get this script from?" - # Or at least not from boilerplate itself - [[ "$CONSUMER" == "openshift/boilerplate" ]] && err " - $cmd must be invoked from a boilerplate consumer, not from boilerplate itself." - - [[ -s $CONVENTION_ROOT/_data/last-boilerplate-commit ]] || err " - $cmd must be invoked from a boilerplate consumer!" - - grep -E -q "^$CONVENTION_NAME(\s.*)?$" $CONVENTION_ROOT/update.cfg || err " - $CONSUMER is not subscribed to $CONVENTION_NAME!" -} - -## release_prep_clone -# -# If $RELEASE_CLONE is already set: -# - It should represent a directory containing a clean checkout of the -# release repository; otherwise we error. -# - We checkout and pull master. -# Otherwise: -# - We clone the release repo to a temporary directory. -# - We set the $RELEASE_CLONE global variable to point to that -# directory. -release_prep_clone() { - # If a release repo clone wasn't specified, create one - if [[ -z "$RELEASE_CLONE" ]]; then - RELEASE_CLONE=$(mktemp -dt openshift_release_XXXXXXX) - git clone --depth=1 git@github.com:${RELEASE_REPO}.git $RELEASE_CLONE - else - [[ -z "$(git -C $RELEASE_CLONE status --porcelain)" ]] || err " -Your release clone must start clean." - # These will blow up if it's misconfigured - git -C $RELEASE_CLONE checkout master - git -C $RELEASE_CLONE pull - fi -} - -## release_done_msg BRANCH -# -# Print exit instructions for submitting the release PR. -# BRANCH is a suggested branch name. -release_done_msg() { - echo - git status - - cat < $TMPD/$f - echo $TMPD/$f - return - fi - done -} - -## expected_prow_config ORG PROJ BRANCH -# -# Prints to stdout the expected prow configuration for the specified -# ORG/PROJ. -expected_prow_config() { - local org=$1 - local consumer_name=$2 - local branch=$3 - # TODO: DRY this with what's in prow-config. - # Do it by making it a template in the convention dir. - cat <&2 - continue - fi - to_process[$a]=1 - done - - for subscriber in "${!to_process[@]}"; do - [[ "${to_process[$subscriber]}" -eq 1 ]] || continue - echo -n "${subscriber} " - done -} diff --git a/boilerplate/generated-includes.mk b/boilerplate/generated-includes.mk deleted file mode 100644 index 78b982f6..00000000 --- a/boilerplate/generated-includes.mk +++ /dev/null @@ -1,7 +0,0 @@ -# THIS FILE IS GENERATED BY BOILERPLATE. DO NOT EDIT. -# This file automatically includes any *.mk files in your subscribed -# conventions. Please ensure your base Makefile includes only this file. -include boilerplate/_lib/boilerplate.mk -include boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.mk -include boilerplate/openshift/golang-osd-operator/project.mk -include boilerplate/openshift/golang-osd-operator/standard.mk diff --git a/boilerplate/openshift/golang-osd-operator/.ci-operator.yaml b/boilerplate/openshift/golang-osd-operator/.ci-operator.yaml deleted file mode 100644 index 1e29c57a..00000000 --- a/boilerplate/openshift/golang-osd-operator/.ci-operator.yaml +++ /dev/null @@ -1,4 +0,0 @@ -build_root_image: - name: __NAME__ - namespace: __NAMESPACE__ - tag: __TAG__ diff --git a/boilerplate/openshift/golang-osd-operator/.codecov.yml b/boilerplate/openshift/golang-osd-operator/.codecov.yml deleted file mode 100644 index ba05647a..00000000 --- a/boilerplate/openshift/golang-osd-operator/.codecov.yml +++ /dev/null @@ -1,30 +0,0 @@ -codecov: - notify: - require_ci_to_pass: no - -coverage: - precision: 2 - round: down - range: "20...100" - - status: - project: no - patch: no - changes: no - -parsers: - gcov: - branch_detection: - conditional: yes - loop: yes - method: no - macro: no - -comment: - layout: "reach,diff,flags,tree" - behavior: default - require_changes: no - -ignore: - - "**/mocks" - - "**/zz_generated*.go" diff --git a/boilerplate/openshift/golang-osd-operator/Dockerfile.olm-registry b/boilerplate/openshift/golang-osd-operator/Dockerfile.olm-registry deleted file mode 100644 index 396756db..00000000 --- a/boilerplate/openshift/golang-osd-operator/Dockerfile.olm-registry +++ /dev/null @@ -1,25 +0,0 @@ -FROM registry.redhat.io/openshift4/ose-operator-registry:v4.14 AS builder -ARG SAAS_OPERATOR_DIR -COPY ${SAAS_OPERATOR_DIR} manifests -RUN initializer --permissive - -# ubi-micro does not work for clusters with fips enabled unless we make OpenSSL available -FROM registry.access.redhat.com/ubi8/ubi-minimal:latest - -COPY --from=builder /bin/registry-server /bin/registry-server -COPY --from=builder /bin/grpc_health_probe /bin/grpc_health_probe -COPY --from=builder /bin/initializer /bin/initializer - -WORKDIR /registry -RUN chgrp -R 0 /registry && chmod -R g+rwx /registry - -USER 1001 - -COPY --from=builder /registry /registry - -EXPOSE 50051 - -CMD ["registry-server", "-t", "/tmp/terminate.log"] - -# Set the DC specific label for the location of the DC database in the image -LABEL operators.operatorframework.io.index.database.v1=/registry/bundles.db diff --git a/boilerplate/openshift/golang-osd-operator/OWNERS_ALIASES b/boilerplate/openshift/golang-osd-operator/OWNERS_ALIASES deleted file mode 100644 index 9d966c85..00000000 --- a/boilerplate/openshift/golang-osd-operator/OWNERS_ALIASES +++ /dev/null @@ -1,85 +0,0 @@ -# ================================ DO NOT EDIT ================================ -# This file is managed in https://github.com/openshift/boilerplate -# See the OWNERS_ALIASES docs: https://git.k8s.io/community/contributors/guide/owners.md#OWNERS_ALIASES -# ============================================================================= -aliases: - srep-functional-team-aurora: - - abyrne55 - - AlexVulaj - - dakotalongRH - - lnguyen1401 - - luis-falcon - - rafael-azevedo - - reedcort - srep-functional-team-fedramp: - - tonytheleg - - theautoroboto - - rhdedgar - - katherinelc321 - - robotmaxtron - - rojasreinold - - hbhushan3 - - fsferraz-rh - srep-functional-team-hulk: - - a7vicky - - rendhalver - - ravitri - - shitaljante - - weherdh - - devppratik - srep-functional-team-orange: - - bergmannf - - bng0y - - typeid - - Makdaam - - mrWinston - - Nikokolas3270 - - ninabauer - - RaphaelBut - - Tessg22 - srep-functional-team-rocket: - - aliceh - - anispate - - clcollins - - iamkirkbater - - Mhodesty - - nephomaniac - - tnierman - srep-functional-team-security: - - gsleeman - - jaybeeunix - - sam-nguyen7 - - wshearn - - dem4gus - - npecka - srep-functional-team-thor: - - bmeng - - MitaliBhalla - - hectorakemp - - feichashao - - Tafhim - - samanthajayasinghe - srep-functional-leads: - - rafael-azevedo - - iamkirkbater - - Nikokolas3270 - - theautoroboto - - bmeng - - mjlshen - - sam-nguyen7 - - ravitri - srep-team-leads: - - NautiluX - - rogbas - - fahlmant - - dustman9000 - - wanghaoran1988 - - bng0y - sre-group-leads: - - apahim - - maorfr - - rogbas - srep-architects: - - jewzaam - - jharrington22 - - cblecker diff --git a/boilerplate/openshift/golang-osd-operator/README.md b/boilerplate/openshift/golang-osd-operator/README.md deleted file mode 100644 index 690eb038..00000000 --- a/boilerplate/openshift/golang-osd-operator/README.md +++ /dev/null @@ -1,167 +0,0 @@ -# Conventions for OSD operators written in Go - -- [Conventions for OSD operators written in Go](#conventions-for-osd-operators-written-in-go) - - [`make` targets and functions.](#make-targets-and-functions) - - [Prow](#prow) - - [Local Testing](#local-testing) - - [app-sre](#app-sre) - - [Code coverage](#code-coverage) - - [Linting and other static analysis with `golangci-lint`](#linting-and-other-static-analysis-with-golangci-lint) - - [Checks on generated code](#checks-on-generated-code) - - [FIPS](#fips-federal-information-processing-standards) - - [Additional deployment support](#additional-deployment-support) - - [OLM SkipRange](#olm-skiprange) - -This convention is suitable for both cluster- and hive-deployed operators. - -The following components are included: - -## `make` targets and functions. - -**Note:** Your repository's main `Makefile` needs to be edited to include the -"nexus makefile include": - -``` -include boilerplate/generated-includes.mk -``` - -One of the primary purposes of these `make` targets is to allow you to -standardize your prow and app-sre pipeline configurations using the -following: - -### Prow - -| Test name / `make` target | Purpose | -| ------------------------- | --------------------------------------------------------------------------------------------------------------- | -| `validate` | Ensure code generation has not been forgotten; and ensure generated and boilerplate code has not been modified. | -| `lint` | Perform static analysis. | -| `test` | "Local" unit and functional testing. | -| `coverage` | [Code coverage](#code-coverage) analysis and reporting. | - -To standardize your prow configuration, you may run: - -```shell -$ make prow-config -``` - -If you already have the openshift/release repository cloned locally, you -may specify its path via `$RELEASE_CLONE`: - -```shell -$ make RELEASE_CLONE=/home/me/github/openshift/release prow-config -``` - -This will generate a delta configuring prow to: - -- Build your `build/Dockerfile`. -- Run the above targets in presubmit tests. -- Run the `coverage` target in a postsubmit. This is the step that - updates your coverage report in codecov.io. - -#### Local Testing - -You can run these `make` targets locally during development to test your -code changes. However, differences in platforms and environments may -lead to unpredictable results. Therefore boilerplate provides a utility -to run targets in a container environment that is designed to be as -similar as possible to CI: - -```shell -$ make container-{target} -``` - -or - -```shell -$ ./boilerplate/_lib/container-make {target} -``` - -### app-sre - -The `build-push` target builds and pushes the operator and OLM registry images, -ready to be SaaS-deployed. -By default it is configured to be run from the app-sre jenkins pipelines. -Consult [this doc](app-sre.md) for information on local execution/testing. - -## Code coverage - -- A `codecov.sh` script, referenced by the `coverage` `make` target, to - run code coverage analysis per [this SOP](https://github.com/openshift/ops-sop/blob/93d100347746ce04ad552591136818f82043c648/services/codecov.md). - -- A `.codecov.yml` configuration file for - [codecov.io](https://docs.codecov.io/docs/codecov-yaml). Note that - this is copied into the repository root, because that's - [where codecov.io expects it](https://docs.codecov.io/docs/codecov-yaml#can-i-name-the-file-codecovyml). - -## Linting and other static analysis with `golangci-lint` - -- A `go-check` `make` target, which -- ensures the proper version of `golangci-lint` is installed, and -- runs it against -- a `golangci.yml` config. -- a `GOLANGCI_OPTIONAL_CONFIG` config if it is defined and file exists - -## Checks on generated code - -The convention embeds default checks to ensure generated code generation is current, committed, and unaltered. -To trigger the check, you can use `make generate-check` provided your Makefile properly includes the boilerplate-generated include `boilerplate/generated-includes.mk`. - -Checks consist of: - -- Checking all files are committed to ensure a safe point to revert to in case of error -- Running the `make generate` command (see below) to regenerate the needed code -- Checking if this results in any new uncommitted files in the git project or if all is clean. - -`make generate` does the following: - -- generate crds and deepcopy via controller-gen. This is a no-op if your - operator has no APIs. -- `openapi-gen`. This is a no-op if your operator has no APIs. -- `go generate`. This is a no-op if you have no `//go:generate` - directives in your code. - -## FIPS (Federal Information Processing Standards) - -To enable FIPS in your build there is a `make ensure-fips` target. - -Add `FIPS_ENABLED=true` to your repos Makefile. Please ensure that this variable is added **before** including boilerplate Makefiles. - -e.g. - -```.mk -FIPS_ENABLED=true - -include boilerplate/generated-includes.mk -``` - -`ensure-fips` will add a [fips.go](./fips.go) file in the same directory as the `main.go` file. (Please commit this file as normal) - -`fips.go` will import the necessary packages to restrict all TLS configuration to FIPS-approved settings. - -With `FIPS_ENABLED=true`, `ensure-fips` is always run before `make go-build` - -## Additional deployment support - -- The convention currently supports a maximum of two deployments. i.e. The operator deployment itself plus an optional additional deployment. -- If an additional deployment image has to be built and appended to the CSV as part of the build process, then the consumer needs to: - - Specify `SupplementaryImage` which is the deployment name in the consuming repository's `config/config.go`. - - Define the image to be built as `ADDITIONAL_IMAGE_SPECS` in the consuming repository's Makefile, Boilerplate later parses this image as part of the build process; [ref](https://github.com/openshift/boilerplate/blob/master/boilerplate/openshift/golang-osd-operator/standard.mk#L56). - - e.g. - - ```.mk - # Additional Deployment Image - define ADDITIONAL_IMAGE_SPECS - build/Dockerfile.webhook $(SUPPLEMENTARY_IMAGE_URI) - end - ``` - - Ensure the CSV template of the consuming repository has the additional deployment name. - -## OLM SkipRange - -- OLM currently doesn't support cross-catalog upgrades. -- The convention standardizes the catalog repositories to adhere to the naming convention `${OPERATOR_NAME}-registry`. -- For an existing operator that has been deployed looking to onboard Boilerplate is a problem. Once deployed, for an existing operator to upgrade to the new Boilerplate-deployed operator which refers to the new catalog registry with `staging/production` channels, OLM needs to support cross-catalog upgrades. -- Cross catalog upgrades are only possible via [OLM Skiprange](https://v0-18-z.olm.operatorframework.io/docs/concepts/olm-architecture/operator-catalog/creating-an-update-graph/#skiprange). -- The consumer can explictly enable OLM SkipRange for their operator by specifying `EnableOLMSkipRange="true"` in the repository's `config/config.go`. -- If specified, the `olm.skipRange` annotation will be appended to the CSV during the build process creating an upgrade path for the operator. diff --git a/boilerplate/openshift/golang-osd-operator/app-sre-build-deploy.sh b/boilerplate/openshift/golang-osd-operator/app-sre-build-deploy.sh deleted file mode 100755 index a316a26f..00000000 --- a/boilerplate/openshift/golang-osd-operator/app-sre-build-deploy.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env bash - -set -ev - -usage() { - cat < Generate Encrypted Password. -# Even if you're not using quay, the pipeline expects these variables to -# be named QUAY_* -export QUAY_USER= -export QUAY_TOKEN= - -# Tell the scripts where to find your fork of the SaaS bundle repository. -# Except for the authentication part, this should correspond to what you see in the -# https "clone" button in your fork. -# Generate an access token via Settings => Access Tokens. Enable `write_repository`. -# - {gitlab-user} is your username in gitlab -# - {gitlab-token} is the authentication token you generated above -# - {operator} is the name of the consumer repository, e.g. `deadmanssnitch-operator` -export GIT_PATH=https://{gitlab-user}:{gitlab-token}@gitlab.cee.redhat.com/{gitlab-user}/saas-{operator}-bundle.git -``` - -## Execute -At this point you should be able to run -``` -make build-push -``` - -This will create the following artifacts if it succeeds -(`{hash}` is the 7-digit SHA of the current git commit in the repository under test): -- Operator image in your personal operator repository, tagged `v{major}.{minor}.{commit-count}-{hash}` (e.g. `v0.1.228-e0b6129`) and `latest` -- Two catalog images in your personal registry repository: - - One image tagged `staging-{hash}` and `staging-latest` - - The other tagged `production-{hash}` and `production-latest` -- Two commits in your fork of the SaaS bundle repository: - - One in the `staging` branch - - The other in the `production` branch - These are also present locally in a `saas-{operator-name}-bundle` subdirectory of your operator repository clone. - You can inspect the artifacts therein to make sure e.g. the CSV was generated correctly. diff --git a/boilerplate/openshift/golang-osd-operator/build-opm-catalog.sh b/boilerplate/openshift/golang-osd-operator/build-opm-catalog.sh deleted file mode 100755 index 3e5ef6dd..00000000 --- a/boilerplate/openshift/golang-osd-operator/build-opm-catalog.sh +++ /dev/null @@ -1,403 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -## Global vars to modify behaviour of the script -SET_X=${SET_X:-false} -[[ "$SET_X" != "false" ]] && set -x - -DRY_RUN=${DRY_RUN:-false} -DELETE_TEMP_DIR=${DELETE_TEMP_DIR:-true} -NO_LOG=${NO_LOG:-false} -OLM_BUNDLE_VERSIONS_REPO=${OLM_BUNDLE_VERSIONS_REPO:-gitlab.cee.redhat.com/service/saas-operator-versions.git} -OLM_BUNDLE_VERSIONS_REPO_BRANCH=${OLM_BUNDLE_VERSIONS_REPO_BRANCH:-master} - -# Global vars -REPO_ROOT=$(git rev-parse --show-toplevel) -PYTHON=.venv/bin/python3 - -function log() { - local to_log=${1} - [[ "$NO_LOG" != "false" ]] && return 0 - local msg - msg="$(date "+%Y-%m-%d %H:%M:%S")" - [[ "$DRY_RUN" != "false" ]] && msg="$msg -- DRY-RUN" - echo "$msg -- $to_log" 1>&2 -} - -function check_required_environment() { - local count=0 - for var in OLM_BUNDLE_IMAGE \ - OLM_CATALOG_IMAGE \ - OPERATOR_IMAGE \ - OPERATOR_IMAGE_TAG \ - OPERATOR_VERSION \ - OPERATOR_NAME \ - CONTAINER_ENGINE \ - CONTAINER_ENGINE_CONFIG_DIR \ - CURRENT_COMMIT \ - OLM_CHANNEL - do - if [ ! "${!var:-}" ]; then - log "$var is not set" - count=$((count + 1)) - fi - done - - [[ $count -eq 0 ]] && return 0 || return 1 -} - -function setup_temp_dir() { - local temp_dir - temp_dir=$(mktemp -d --suffix "-$(basename "$0")") - [[ "$DELETE_TEMP_DIR" == "true" ]] && trap "rm -rf $temp_dir" EXIT - - echo "$temp_dir" -} - -function setup_local_executable() { - local executable=${1} - "$REPO_ROOT"/boilerplate/openshift/golang-osd-operator/ensure.sh "$executable" >&2 - echo "$REPO_ROOT/.$executable/bin/$executable" -} - -function check_bundle_contents_cmd() { - bundle_contents_cmd="$REPO_ROOT/hack/generate-operator-bundle-contents.py" - if [[ ! -x "$bundle_contents_cmd" ]]; then - log "$bundle_contents_cmd is either missing or non-executable" - return 1 - fi -} - -# Check we are running an opm supported container engine -function check_opm_supported_container_engine() { - local image_builder=${1} - if [[ "$image_builder" != "docker" && "$image_builder" != "podman" ]]; then - # opm error messages are obscure. Let's make this clear - log "image_builder $image_builder is not one of docker or podman" - return 1 - fi - - return 0 -} - -# Check we will be able to properly authenticate ourselves against the registry -function check_authenticated_registry_command() { - if [[ ! -f "$CONTAINER_ENGINE_CONFIG_DIR/config.json" ]]; then - log "$CONTAINER_ENGINE_CONFIG_DIR/config.json missing" - return 1 - fi - - return 0 -} - -function setup_authenticated_registry_command() { - echo "$CONTAINER_ENGINE --config=$CONTAINER_ENGINE_CONFIG_DIR" -} - -function clone_olm_bundle_versions_repo() { - local saas_root_dir=${1} - - local bundle_versions_repo_url - if [[ -n "${APP_SRE_BOT_PUSH_TOKEN:-}" ]]; then - log "Using APP_SRE_BOT_PUSH_TOKEN credentials to authenticate" - bundle_versions_repo_url="https://app:${APP_SRE_BOT_PUSH_TOKEN}@$OLM_BUNDLE_VERSIONS_REPO" - else - bundle_versions_repo_url="https://$OLM_BUNDLE_VERSIONS_REPO" - fi - - log "Cloning $OLM_BUNDLE_VERSIONS_REPO into $saas_root_dir" - git clone --branch "$OLM_BUNDLE_VERSIONS_REPO_BRANCH" "$bundle_versions_repo_url" "$saas_root_dir" -} - -function get_prev_operator_version() { - local bundle_versions_file=${1} - - local return_message="" - - # if the line contains SKIP it will not be included - local prev_operator_version="" - local prev_good_operator_version="" - local skip_versions=() - if [[ -s "$bundle_versions_file" ]]; then - log "$bundle_versions_file exists. We'll use to determine current version" - - prev_operator_version=$(tail -n 1 "$bundle_versions_file" | awk '{print $1}') - - # we traverse the bundle versions file backwards - # we cannot use pipes here or we would lose the inner variables changes - local version - while read -r line; do - if [[ "$line" == *SKIP* ]]; then - version=$(echo "$line" | awk '{print $1}') - skip_versions+=("$version") - else - prev_good_operator_version="$line" - break - fi - done < <(sort -r -t . -k 3 -g "$bundle_versions_file") - - if [[ -z "$prev_good_operator_version" ]]; then - # This means that we have skipped all the available versions. In this case we're going to use the last - # SKIP version as the prev_good_operator_version to have something to feed replaces in the CSV - log "No unskipped version in $bundle_versions_file. We'll use the last skipped one: ${skip_versions[0]}" - prev_good_operator_version="${skip_versions[0]}" - fi - - log "Previous operator version is $prev_operator_version" - log "Previous good operator version is $prev_good_operator_version" - return_message="$prev_operator_version $prev_good_operator_version" - - if [[ ${#skip_versions[@]} -gt 0 ]]; then - log "We will be skipping: ${skip_versions[*]}" - return_message="$return_message ${skip_versions[*]}" - fi - else - log "No $bundle_versions_file exist or it is empty. This is the first time the operator is built" - if [[ ! -d "$(dirname "$bundle_versions_file")" ]]; then - log "Operator directory doesn't exist in versions repository. Exiting" - exit 1 - fi - fi - - echo "$return_message" - -} - -function build_opm_bundle() { - local temp_dir=${1} - local bundle_contents_cmd=${2} - local opm_local_executable=${3} - local image_builder=${4} - local prev_good_operator_version=${5} - # shellcheck disable=SC2206 - local skip_versions=(${@:6}) - - local bundle_temp_dir - bundle_temp_dir=$(mktemp -d -p "$temp_dir" bundle.XXXX) - local generate_csv_template_args="" - [[ -n "$prev_good_operator_version" ]] && generate_csv_template_args="--replaces $prev_good_operator_version" - if [[ ${#skip_versions[@]} -gt 0 ]]; then - for version in "${skip_versions[@]}"; do - generate_csv_template_args="$generate_csv_template_args --skip $version" - done - fi - - local manifests_temp_dir - manifests_temp_dir=$(mktemp -d -p "$bundle_temp_dir" manifests.XXXX) - # shellcheck disable=SC2086 - $bundle_contents_cmd --name "$OPERATOR_NAME" \ - --current-version "$OPERATOR_VERSION" \ - --image "$OPERATOR_IMAGE" \ - --image-tag "$OPERATOR_IMAGE_TAG" \ - --output-dir "$manifests_temp_dir" \ - $generate_csv_template_args - - # opm won't get anything locally, so we need to push the bundle even in dry run mode - # we will use a different tag to make sure those leftovers are clearly recognized - # TODO: remove this tag if we're in dry-run mode in the cleanup trap script - [[ "$DRY_RUN" == "false" ]] || bundle_image_current_commit="${bundle_image_current_commit}-dryrun" - - log "Creating bundle image $bundle_image_current_commit" - local current_dir="$PWD" - cd "$bundle_temp_dir" - $opm_local_executable alpha bundle build --directory "$manifests_temp_dir" \ - --channels "$OLM_CHANNEL" \ - --default "$OLM_CHANNEL" \ - --package "$OPERATOR_NAME" \ - --tag "$bundle_image_current_commit" \ - --image-builder "$image_builder" \ - --overwrite \ - 1>&2 - cd "$current_dir" - - echo "$bundle_image_current_commit" -} - -function build_opm_catalog() { - local opm_local_executable=${1} - local image_builder=${2} - local bundle_image_current_commit=${3} - local catalog_image_current_commit=${4} - local prev_operator_version=${5} - - local from_arg="" - if [[ "$prev_operator_version" ]]; then - local prev_commit=${prev_operator_version#*-} - from_arg="--from-index $OLM_CATALOG_IMAGE:$prev_commit" - fi - - # check if the previous catalog image is available - if [ $(${image_builder} pull ${OLM_CATALOG_IMAGE}:${prev_commit} &> /dev/null;echo $?) -gt 0 ]; then - # remove the first character - prev_commit=${prev_commit:1} - from_arg="--from-index $OLM_CATALOG_IMAGE:$prev_commit" - fi - - log "Index argument is $from_arg" - log "Creating catalog image $catalog_image_current_commit using opm" - # shellcheck disable=SC2086 - $opm_local_executable index add --bundles "$bundle_image_current_commit" \ - --tag "$catalog_image_current_commit" \ - --build-tool "$image_builder" \ - $from_arg -} - -function check_opm_catalog() { - local catalog_image_current_commit=${1} - local engine_cmd=${2} - local grpcurl_local_executable=${3} - - # Check that catalog works fine - log "Checking that catalog we have built returns the correct version $OPERATOR_VERSION" - - local free_port - free_port=$(${PYTHON} -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()') - - log "Running $catalog_image_current_commit and exposing $free_port" - local catalog_container_id - catalog_container_id=$($engine_cmd run -d -p "$free_port:50051" "$catalog_image_current_commit") - - log "Getting current version from running catalog" - current_version_from_catalog=$( - $grpcurl_local_executable -plaintext -d '{"name": "'"$OPERATOR_NAME"'"}' \ - "localhost:$free_port" api.Registry/GetPackage | \ - jq -r '.channels[] | select(.name=="'"$OLM_CHANNEL"'") | .csvName' | \ - sed "s/$OPERATOR_NAME\.//" - ) - - log "Removing docker container $catalog_container_id" - $engine_cmd rm -f "$catalog_container_id" - - if [[ "$current_version_from_catalog" != "v$OPERATOR_VERSION" ]]; then - log "Version from catalog $current_version_from_catalog != v$OPERATOR_VERSION" - return 1 - fi - - return 0 -} - -function add_current_version_to_bundle_versions_file() { - local bundle_versions_file=${1} - local saas_root_dir=${2} - local prev_operator_version=${3} - - log "Adding the current version $OPERATOR_VERSION to the bundle versions file in $OLM_BUNDLE_VERSIONS_REPO" - echo "$OPERATOR_VERSION" >> "$bundle_versions_file" - - local current_directory="$PWD" - - cd "$saas_root_dir/$OPERATOR_NAME" - git add . - message="add version $OPERATOR_VERSION" - [[ "$prev_operator_version" ]] && message="$message - - replaces $prev_operator_version" - - git commit -m "$message" - - log "Pushing the repository changes to $OLM_BUNDLE_VERSIONS_REPO into $OLM_BUNDLE_VERSIONS_REPO_BRANCH branch" - [[ "$DRY_RUN" == "false" ]] && git push origin "$OLM_BUNDLE_VERSIONS_REPO_BRANCH" - - cd "$current_directory" -} - -function main() { - log "Building $OPERATOR_NAME version $OPERATOR_VERSION" - - check_required_environment || return 1 - check_bundle_contents_cmd || return 1 - check_authenticated_registry_command || return 1 - - local temp_dir - local opm_local_executable - local grpcurl_local_executable - local engine_cmd - local image_builder - temp_dir=$(setup_temp_dir) - opm_local_executable=$(setup_local_executable opm) - grpcurl_local_executable=$(setup_local_executable grpcurl) - engine_cmd=$(setup_authenticated_registry_command) - image_builder=$(basename "$CONTAINER_ENGINE" | awk '{print $1}') - - check_opm_supported_container_engine "$image_builder" || return 1 - - local saas_root_dir="$temp_dir/saas-operator-versions" - clone_olm_bundle_versions_repo "$saas_root_dir" - - local bundle_versions_file="$saas_root_dir/$OPERATOR_NAME/${OPERATOR_NAME}-versions.txt" - local versions - # shellcheck disable=SC2207 - versions=($(get_prev_operator_version "$bundle_versions_file")) - # This condition is triggered when an operator is built for the first time. In such case the - # get_prev_operator_version returns an empty string and causes undefined variables failures - # in a few lines below. - if [ -z ${versions+x} ] - then - versions[0]="" - versions[1]="" - fi - local prev_operator_version="${versions[0]}" - local prev_good_operator_version="${versions[1]}" - local skip_versions=("${versions[@]:2}") - - if [[ "$OPERATOR_VERSION" == "$prev_operator_version" ]]; then - log "stopping script as $OPERATOR_VERSION version was already built, so no need to rebuild it" - return 0 - fi - - # the commit needs a 'g' prefix for the bundle image - local bundle_image_current_commit="${OLM_BUNDLE_IMAGE}:g${CURRENT_COMMIT}" - local bundle_image_latest="$OLM_BUNDLE_IMAGE:latest" - local catalog_image_current_commit="${OLM_CATALOG_IMAGE}:${CURRENT_COMMIT}" - local catalog_image_latest="$OLM_CATALOG_IMAGE:latest" - - bundle_image_current_commit=$(build_opm_bundle "${temp_dir}" \ - "$bundle_contents_cmd" \ - "$opm_local_executable" \ - "$image_builder" \ - "$prev_good_operator_version" \ - "${skip_versions[*]:-}") - - log "Pushing bundle image $bundle_image_current_commit" - $engine_cmd push "$bundle_image_current_commit" - - # Make sure this is run after pushing the image - log "Validating bundle $bundle_image_current_commit" - $opm_local_executable alpha bundle validate --tag "$bundle_image_current_commit" \ - --image-builder "$image_builder" - - log "Tagging bundle image $bundle_image_current_commit as $bundle_image_latest" - $engine_cmd tag "$bundle_image_current_commit" "$bundle_image_latest" - - build_opm_catalog "$opm_local_executable" \ - "$image_builder" \ - "$bundle_image_current_commit" \ - "$catalog_image_current_commit" \ - "$prev_operator_version" - - check_opm_catalog "$catalog_image_current_commit" "$engine_cmd" "$grpcurl_local_executable" || return 1 - - log "Tagging catalog image $catalog_image_current_commit as $catalog_image_latest" - $engine_cmd tag "$catalog_image_current_commit" "$catalog_image_latest" - - add_current_version_to_bundle_versions_file "$bundle_versions_file" \ - "$saas_root_dir" \ - "$prev_operator_version" - - log "Pushing catalog image $catalog_image_current_commit" - [[ "$DRY_RUN" == "false" ]] && $engine_cmd push "$catalog_image_current_commit" - - log "Pushing bundle image $catalog_image_latest" - [[ "$DRY_RUN" == "false" ]] && $engine_cmd push "$catalog_image_latest" - - log "Pushing bundle image $bundle_image_latest" - [[ "$DRY_RUN" == "false" ]] && $engine_cmd push "$bundle_image_latest" - - return 0 -} - -# Main -if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then - main -fi diff --git a/boilerplate/openshift/golang-osd-operator/codecov.sh b/boilerplate/openshift/golang-osd-operator/codecov.sh deleted file mode 100755 index 8fc79bd0..00000000 --- a/boilerplate/openshift/golang-osd-operator/codecov.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -REPO_ROOT=$(git rev-parse --show-toplevel) -CI_SERVER_URL=https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test -COVER_PROFILE=${COVER_PROFILE:-coverage.out} -JOB_TYPE=${JOB_TYPE:-"local"} - -# Default concurrency to four threads. By default it's the number of procs, -# which seems to be 16 in the CI env. Some consumers' coverage jobs were -# regularly getting OOM-killed; so do this rather than boost the pod resources -# unreasonably. -COV_THREAD_COUNT=${COV_THREAD_COUNT:-4} -make -C "${REPO_ROOT}" go-test TESTOPTS="-coverprofile=${COVER_PROFILE}.tmp -covermode=atomic -coverpkg=./... -p ${COV_THREAD_COUNT}" - -# Remove generated files from coverage profile -grep -v "zz_generated" "${COVER_PROFILE}.tmp" > "${COVER_PROFILE}" -rm -f "${COVER_PROFILE}.tmp" - -# Configure the git refs and job link based on how the job was triggered via prow -if [[ "${JOB_TYPE}" == "presubmit" ]]; then - echo "detected PR code coverage job for #${PULL_NUMBER}" - REF_FLAGS="-P ${PULL_NUMBER} -C ${PULL_PULL_SHA}" - JOB_LINK="${CI_SERVER_URL}/pr-logs/pull/${REPO_OWNER}_${REPO_NAME}/${PULL_NUMBER}/${JOB_NAME}/${BUILD_ID}" -elif [[ "${JOB_TYPE}" == "postsubmit" ]]; then - echo "detected branch code coverage job for ${PULL_BASE_REF}" - REF_FLAGS="-B ${PULL_BASE_REF} -C ${PULL_BASE_SHA}" - JOB_LINK="${CI_SERVER_URL}/logs/${JOB_NAME}/${BUILD_ID}" -elif [[ "${JOB_TYPE}" == "local" ]]; then - echo "coverage report available at ${COVER_PROFILE}" - exit 0 -else - echo "${JOB_TYPE} jobs not supported" >&2 - exit 1 -fi - -# Configure certain internal codecov variables with values from prow. -export CI_BUILD_URL="${JOB_LINK}" -export CI_BUILD_ID="${JOB_NAME}" -export CI_JOB_ID="${BUILD_ID}" - -if [[ "${JOB_TYPE}" != "local" ]]; then - if [[ -z "${ARTIFACT_DIR:-}" ]] || [[ ! -d "${ARTIFACT_DIR}" ]] || [[ ! -w "${ARTIFACT_DIR}" ]]; then - echo '${ARTIFACT_DIR} must be set for non-local jobs, and must point to a writable directory' >&2 - exit 1 - fi - curl -sS https://codecov.io/bash -o "${ARTIFACT_DIR}/codecov.sh" - bash <(cat "${ARTIFACT_DIR}/codecov.sh") -Z -K -f "${COVER_PROFILE}" -r "${REPO_OWNER}/${REPO_NAME}" ${REF_FLAGS} -else - bash <(curl -s https://codecov.io/bash) -Z -K -f "${COVER_PROFILE}" -r "${REPO_OWNER}/${REPO_NAME}" ${REF_FLAGS} -fi diff --git a/boilerplate/openshift/golang-osd-operator/configure-fips.sh b/boilerplate/openshift/golang-osd-operator/configure-fips.sh deleted file mode 100755 index d0092551..00000000 --- a/boilerplate/openshift/golang-osd-operator/configure-fips.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -set -e - -REPO_ROOT=$(git rev-parse --show-toplevel) -CONVENTION_DIR="$REPO_ROOT/boilerplate/openshift/golang-osd-operator" -PRE_V1_SDK_MANAGER_DIR="$REPO_ROOT/cmd/manager" - -if [[ -d "$PRE_V1_SDK_MANAGER_DIR" ]] -then - MAIN_DIR=$PRE_V1_SDK_MANAGER_DIR -else - MAIN_DIR=$REPO_ROOT -fi - -echo "Writing fips file at $MAIN_DIR/fips.go" - -cp $CONVENTION_DIR/fips.go.tmplt "$MAIN_DIR/fips.go" diff --git a/boilerplate/openshift/golang-osd-operator/csv-generate/catalog-build.sh b/boilerplate/openshift/golang-osd-operator/csv-generate/catalog-build.sh deleted file mode 100755 index c899879a..00000000 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/catalog-build.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source `dirname $0`/common.sh - -usage() { echo "Usage: $0 -o operator-name -c saas-repository-channel -r registry-image" 1>&2; exit 1; } - -while getopts "o:c:r:" option; do - case "${option}" in - o) - operator_name=${OPTARG} - ;; - c) - operator_channel=${OPTARG} - ;; - r) - # NOTE: This is the URL without the tag/digest - registry_image=${OPTARG} - ;; - *) - usage - esac -done - -# Detect the container engine to use, allowing override from the env -CONTAINER_ENGINE=${CONTAINER_ENGINE:-$(command -v podman || command -v docker || true)} -if [[ -z "$CONTAINER_ENGINE" ]]; then - echo "WARNING: Couldn't find a container engine! Defaulting to docker." - CONTAINER_ENGINE=docker -fi - -# Checking parameters -check_mandatory_params operator_channel operator_name - -# Parameters for the Dockerfile -SAAS_OPERATOR_DIR="saas-${operator_name}-bundle" -BUNDLE_DIR="${SAAS_OPERATOR_DIR}/${operator_name}" -DOCKERFILE_REGISTRY="build/Dockerfile.olm-registry" - -# Checking SAAS_OPERATOR_DIR exist -if [ ! -d "${SAAS_OPERATOR_DIR}/.git" ] ; then - echo "${SAAS_OPERATOR_DIR} should exist and be a git repository" - exit 1 -fi - -# Calculate new operator version from bundles inside the saas directory -OPERATOR_NEW_VERSION=$(ls "${BUNDLE_DIR}" | sort -t . -k 3 -g | tail -n 1) - -# Create package yaml -# This must be included in the registry build -# `currentCSV` must reference the latest bundle version included. -# Any version their after `currentCSV` loaded by the initalizer -# will be silently pruned as it's not reachable -PACKAGE_YAML_PATH="${BUNDLE_DIR}/${operator_name}.package.yaml" - -cat < "${PACKAGE_YAML_PATH}" -packageName: ${operator_name} -channels: -- name: ${operator_channel} - currentCSV: ${operator_name}.v${OPERATOR_NEW_VERSION} -EOF - -TAG="${operator_channel}-latest" -if [[ "${RELEASE_BRANCHED_BUILDS}" ]]; then - TAG="v${OPERATOR_NEW_VERSION}" -fi - -${CONTAINER_ENGINE} build --pull -f "${DOCKERFILE_REGISTRY}" --build-arg "SAAS_OPERATOR_DIR=${SAAS_OPERATOR_DIR}" --tag "${registry_image}:${TAG}" . - -if [ $? -ne 0 ] ; then - echo "docker build failed, exiting..." - exit 1 -fi - -# TODO : Test the image and the version it contains diff --git a/boilerplate/openshift/golang-osd-operator/csv-generate/catalog-publish.sh b/boilerplate/openshift/golang-osd-operator/csv-generate/catalog-publish.sh deleted file mode 100755 index eb1c7547..00000000 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/catalog-publish.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source `dirname $0`/common.sh - -usage() { echo "Usage: $0 -o operator-name -c saas-repository-channel -r registry-image -H operator-commit-hash -n operator-commit-number [-p]" 1>&2; exit 1; } - -while getopts "o:c:n:H:pr:" option; do - case "${option}" in - c) - operator_channel=${OPTARG} - ;; - H) - operator_commit_hash=${OPTARG} - ;; - n) - operator_commit_number=${OPTARG} - ;; - o) - operator_name=${OPTARG} - ;; - p) - push_catalog=true - ;; - r) - # NOTE: This is the URL without the tag/digest - registry_image=${OPTARG} - ;; - *) - usage - esac -done - -# Checking parameters -check_mandatory_params operator_channel operator_name operator_commit_hash operator_commit_number registry_image - -# Calculate previous version -SAAS_OPERATOR_DIR="saas-${operator_name}-bundle" -BUNDLE_DIR="${SAAS_OPERATOR_DIR}/${operator_name}" -OPERATOR_NEW_VERSION=$(ls "${BUNDLE_DIR}" | sort -t . -k 3 -g | tail -n 1) -OPERATOR_PREV_VERSION=$(ls "${BUNDLE_DIR}" | sort -t . -k 3 -g | tail -n 2 | head -n 1) - -if [[ "$OPERATOR_NEW_VERSION" == "$OPERATOR_PREV_VERSION" ]]; then - echo "New version and previous version are identical. Exiting." - exit 1 -fi - -# Get container engine -CONTAINER_ENGINE=$(command -v podman || command -v docker || true) -[[ -n "$CONTAINER_ENGINE" ]] || echo "WARNING: Couldn't find a container engine. Assuming you already in a container, running unit tests." >&2 - -# Set SRC container transport based on container engine -if [[ "${CONTAINER_ENGINE##*/}" == "podman" ]]; then - SRC_CONTAINER_TRANSPORT="containers-storage" -else - SRC_CONTAINER_TRANSPORT="docker-daemon" -fi - -# Checking SAAS_OPERATOR_DIR exist -if [ ! -d "${SAAS_OPERATOR_DIR}/.git" ] ; then - echo "${SAAS_OPERATOR_DIR} should exist and be a git repository" - exit 1 -fi - -# Read the bundle version we're attempting to publish -# in the OLM catalog from the package yaml -PACKAGE_YAML_PATH="${BUNDLE_DIR}/${operator_name}.package.yaml" -PACKAGE_YAML_VERSION=$(awk '$1 == "currentCSV:" {print $2}' ${PACKAGE_YAML_PATH}) - -# Ensure we're commiting and pushing the version we think we are pushing -# Since we build the bundle in catalog-build.sh this script could be run -# independently and push a version we're not expecting. -# if ! [ "${operator_name}.v${OPERATOR_NEW_VERSION}" = "${PACKAGE_YAML_VERSION}" ]; then -# echo "You are attemping to push a bundle that's pointing to a version of this catalog you are not building" -# echo "You are building version: ${operator_name}.v${OPERATOR_NEW_VERSION}" -# echo "Your local package yaml version is: ${PACKAGE_YAML_VERSION}" -# exit 1 -# fi - -# add, commit & push -pushd "${SAAS_OPERATOR_DIR}" - -git add . - -MESSAGE="add version ${operator_commit_number}-${operator_commit_hash} - -replaces ${OPERATOR_PREV_VERSION} -removed versions: ${REMOVED_VERSIONS}" - -git commit -m "${MESSAGE}" -git push origin HEAD - -if [ $? -ne 0 ] ; then - echo "git push failed, exiting..." - exit 1 -fi - -popd - -if [ "$push_catalog" = true ] ; then - # push image - if [[ "${RELEASE_BRANCHED_BUILDS}" ]]; then - skopeo copy --dest-creds "${QUAY_USER}:${QUAY_TOKEN}" \ - "${SRC_CONTAINER_TRANSPORT}:${registry_image}:v${OPERATOR_NEW_VERSION}" \ - "docker://${registry_image}:v${OPERATOR_NEW_VERSION}" - - if [ $? -ne 0 ] ; then - echo "skopeo push of ${registry_image}:v${OPERATOR_NEW_VERSION}-latest failed, exiting..." - exit 1 - fi - - exit 0 - fi - - skopeo copy --dest-creds "${QUAY_USER}:${QUAY_TOKEN}" \ - "${SRC_CONTAINER_TRANSPORT}:${registry_image}:${operator_channel}-latest" \ - "docker://${registry_image}:${operator_channel}-latest" - - if [ $? -ne 0 ] ; then - echo "skopeo push of ${registry_image}:${operator_channel}-latest failed, exiting..." - exit 1 - fi - - skopeo copy --dest-creds "${QUAY_USER}:${QUAY_TOKEN}" \ - "${SRC_CONTAINER_TRANSPORT}:${registry_image}:${operator_channel}-latest" \ - "docker://${registry_image}:${operator_channel}-${operator_commit_hash}" - - if [ $? -ne 0 ] ; then - echo "skopeo push of ${registry_image}:${operator_channel}-${operator_commit_hash} failed, exiting..." - exit 1 - fi -fi diff --git a/boilerplate/openshift/golang-osd-operator/csv-generate/common-generate-operator-bundle.py b/boilerplate/openshift/golang-osd-operator/csv-generate/common-generate-operator-bundle.py deleted file mode 100755 index da70a06b..00000000 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/common-generate-operator-bundle.py +++ /dev/null @@ -1,413 +0,0 @@ -#!/usr/bin/env python3 -# -# Common script to generate OSD operator bundles for publishing to OLM. Copies appropriate files -# into a directory, and composes the ClusterServiceVersion which needs bits and -# pieces of our rbac and deployment files. -# -# Usage ./common-generate-operator-bundle.py \ -# -o OPERATOR_NAME \ -# -d OUTPUT_DIR \ -# -p PREVIOUS_VERSION \ -# -i OPERATOR_IMAGE_URI \ -# -V VERSION_BASE - -import datetime -import os -import yaml -import argparse - -# The registry is pinned to version 4.7 and only the following resouces are permitted in -# the bundle. The full list can be found at https://github.com/operator-framework/operator-registry/blob/release-4.7/pkg/lib/bundle/supported_resources.go#L4-L19 -BUNDLE_PERMITTED_RESOURCES = ( - "ClusterServiceVersion", - "CustomResourceDefinition", - "Deployment", # this resource is injected into the CSV directly but not supported by the registry - "Secret", - "ClusterRole", - "ClusterRoleBinding", - "ConfigMap", - "ServiceAccount", - "Service", - "Role", - "RoleBinding", - "PrometheusRule", - "ServiceMonitor", - "PodDisruptionBudget", - "PriorityClass", - "VerticalPodAutoscaler", - "ConsoleYamlSample", -) - -parser = argparse.ArgumentParser() -parser.add_argument("-o", "--operator-name", type=str, help="Name of the operator", required=True) -parser.add_argument("-d", "--output-dir", type=str, help="Directory for the CSV generation", required=True) -parser.add_argument("-p", "--previous-version", type=str, help="Semver of the version being replaced", required=False) -parser.add_argument("-i", "--operator-image", type=str, help="Base index image to be used", required=True) -parser.add_argument("-V", "--operator-version", type=str, help="The full version of the operator (without the leading `v`): {major}.{minor}.{commit-number}-{hash}", required=True) -parser.add_argument("-s", "--supplementary-image", type=str, help="Image of the supplementary deployment", required=False) -parser.add_argument("-e", "--skip-range-enabled", type=str, help="OLM skip range is enabled", required=False) -args = parser.parse_args() - -OPERATOR_NAME = args.operator_name -outdir = args.output_dir -prev_version = args.previous_version -operator_image = args.operator_image -full_version = args.operator_version -supplementary_image = args.supplementary_image -skip_range_enabled=args.skip_range_enabled - -hasMultipleDeployments = False - -# Verify that this is not creating a cycle. -if prev_version == full_version: - print( - "Previous version equals current version. " - "This would result in a cycle that can not be installed - aborting." - ) - sys.exit(1) - - -class UnsupportedRegistryResourceKind(Exception): - def __init__(self, kind, path): - super().__init__( - f"The resource at {path} of kind {kind} is not supported" - ) - -class NoServiceAccountSubjectInBinding(Exception): - def __init__(self, binding): - super().__init__( - f"No ServiceAccount Subject in the following Binding:\n{binding}") - -class NoDeploymentFound(Exception): - def __init__(self): - super().__init__("At least one Deployment is required!") - -class BindingsNotSupported(Exception): - def __init__(self, bindings): - super().__init__( - "[Cluster]RoleBindings are only supported when they correspond " + - "to provided [Cluster]Roles. Found the following orphans:\n" + - f"{bindings}") - -class UndefinedCSVNamespace(Exception): - def __init__(self, operator_name): - super().__init__( - f"Namespace not defined for operator {operator_name} in CSV template" - ) - -class UndefinedSupplementaryImage(Exception): - def __init__(self): - super().__init__( - f"Image has not been defined for the additional deployment" - ) - -class NoAssociatedRoleBinding(Exception): - def __init__(name, namespace): - super.__init__( - f"The Role {name}/{namespace} does not have an associated RoleBinding" - ) - -print("Generating CSV for version: %s" % full_version) - -if not os.path.exists(outdir): - os.mkdir(outdir) - -VERSION_DIR = os.path.join(outdir, full_version) -if not os.path.exists(VERSION_DIR): - os.mkdir(VERSION_DIR) - -with open('config/templates/csv-template.yaml', 'r') as stream: - csv = yaml.safe_load(stream) - -# by_kind is a map, keyed by Kind, of all the yaml documents we find -# under the deploy/ directory. We need to load them all before we start -# processing because some (e.g. a ClusterRole and the ServiceAccount in -# its corresponding ClusterRoleBinding) are interdependent. -by_kind = {} -# crb_by_cr is a map, keyed by ClusterRole name, of ClusterRoleBinding -# documents. -crb_by_cr = {} -# rb_by_role is a map, keyed by Role name, of RoleBinding documents -rb_by_role = {} -for d, _, files in os.walk('deploy'): - for fname in files: - if not fname.endswith('.yaml'): - continue - path = os.path.join(d, fname) - with open(path, 'r') as stream: - for doc in yaml.safe_load_all(stream): - print( - f"Loading {doc['kind']} {doc['metadata']['name']} " + - f"from {path}") - if doc['kind'] not in BUNDLE_PERMITTED_RESOURCES: - raise UnsupportedRegistryResourceKind(doc['kind'], path) - if doc['kind'] not in by_kind: - by_kind[doc['kind']] = [] - by_kind[doc['kind']].append(doc) - if doc['kind'] == 'ClusterRoleBinding': - crb_by_cr[doc['roleRef']['name']] = doc - if doc['kind'] == 'RoleBinding': - rb_by_role[doc['roleRef']['name']] = doc - -def log_resource(resource): - """Log a message that we're processing the given resource. - - :param resource: A k8s resource definition dict, expected to have at least - a kind and metadata.name. - """ - print(f"Processing {resource['kind']} {resource['metadata']['name']}") - -def filename_for(resource): - """Generate a unique base file name for the given resource. - - :param resource: A k8s resource definition dict, expected to have at least - a kind and metadata.name. - :return: A base file name (no directory) that should be unique for the - given resource (assuming the resource is itself unique). - """ - chunks = [resource['kind']] - ns = resource['metadata'].get('namespace') - if ns: - chunks.append(ns) - chunks.append(resource['metadata']['name']) - return '_'.join(chunks) + '.yaml' - -def bundle(resource): - """Create a yaml file for the given resource in the bundle. - - Uses the VERSION_DIR global. - - :param resource: A k8s resource definition dict, expected to have at least - a kind and metadata.name. - """ - path = os.path.join(VERSION_DIR, filename_for(resource)) - print(f"Bundling {path}") - with open(path, 'w') as outfile: - yaml.dump(resource, outfile, default_flow_style=False) - -def discover_service_account(binding): - """Discover or default the service account in a [Cluster]RoleBinding. - - If binding is None, default to the operator name. - Uses the OPERATOR_NAME global. - - :param binding: A [Cluster]RoleBinding resource dict. - :return: A string ServiceAccount name. - :raise NoServiceAccountSubjectInBinding: if binding does not contain a - ServiceAccount Subject. - """ - if not binding: - print( - f" Using default ServiceAccount ({OPERATOR_NAME}).") - return OPERATOR_NAME - for subject in binding.get('subjects', []): - if subject['kind'] == 'ServiceAccount': - sa = subject['name'] - print(f" Discovered ServiceAccount {sa}.") - return sa - raise NoServiceAccountSubjectInBinding(binding) - -def trim_index(index, kind, item): - """Removes one or all items of a given kind from the index. - - :param index: Dict, keyed by kind, of k8s resources. - :param kind: String kind name to trim. - :param item: The item to trim. May be: - - A dict k8s resource. That specific resource is removed. If not found, - this function is a no-op. - - None. This function is a no-op. - - The string 'ALL'. The entire list for the given kind is removed. - """ - if kind not in index: - return - if not item: - return - if item == 'ALL': - index.pop(kind, None) - return - name = item['metadata']['name'] - ns = item['metadata'].get('namespace') - # Find the specific resource to remove - for i in range(len(index[kind])): - meta = index[kind][i]['metadata'] - if meta['name'] == name and meta.get('namespace') == ns: - found = i - break - else: - # not found - return - # Reconstruct the list without the requested item - index[kind] = index[kind][:found] + index[kind][found+1:] - -## Up front sanity checks -if 'Deployment' not in by_kind: - raise NoDeploymentFound() - -# We support no more than two deployments -if len(by_kind['Deployment']) > 1: - hasMultipleDeployments = True - -# Check if the supplementary image has been provided -if hasMultipleDeployments and not supplementary_image: - raise UndefinedSupplementaryImage() - - -## Process CRDs -if 'CustomResourceDefinition' in by_kind: - csv['spec']['customresourcedefinitions'] = {'owned': []} -for crd in by_kind.get('CustomResourceDefinition', []): - log_resource(crd) - - # And register the CRD as "owned" in the CSV - for version in crd["spec"]["versions"]: - csv['spec']['customresourcedefinitions']['owned'].append( - { - "name": crd["metadata"]["name"], - "description": crd["spec"]["names"]["kind"], - "displayName": crd["spec"]["names"]["kind"], - "kind": crd["spec"]["names"]["kind"], - "version": version["name"] - } - ) -# These will be written to the bundle at the end along with generic resources - -## Process [Cluster]Role[Binding]s (TODO: Match up ServiceAccounts) -# Role and ClusterRole are processed similarly -rolekind_csvkey_bindingmap = ( - ('ClusterRole', 'clusterPermissions', crb_by_cr), - # NOTE: The schema supports `permissions` for Roles, but OLM may not. For - # backward compatibility, treat Roles and RoleBindings as generic bundle - # resources. - # ('Role', 'permissions', rb_by_role), -) -for kind, csvkey, binding_map in rolekind_csvkey_bindingmap: - if kind in by_kind: - csv['spec']['install']['spec'][csvkey] = [] - for role in by_kind.get(kind, []): - log_resource(role) - # Figure out the ServiceAccount. - binding = binding_map.get(role['metadata']['name'], None) - sa = discover_service_account(binding) - # Get rid of the binding, if found, so it doesn't end up in generic - # bundle resources. - trim_index(by_kind, f"{kind}Binding", binding) - # Inject the rules and ServiceAccount - csv['spec']['install']['spec'][csvkey].append( - { - 'rules': role['rules'], - 'serviceAccountName': sa, - }) - # Get rid of these so we can iterate over what's left at the end - trim_index(by_kind, kind, 'ALL') - - -csv['spec']['install']['spec']['permissions'] = [] - -if 'namespace' not in csv['metadata']: - raise UndefinedCSVNamespace(OPERATOR_NAME) - -# Find namespace of operator from CSV template -namespace = csv['metadata']['namespace'] - -if 'Role' in by_kind: - for role in by_kind['Role']: - # We assume there is always a rolebinding of defined role - if role['metadata']['name'] not in rb_by_role: - raise NoAssociatedRoleBinding(role['metadata']['name'], role['metadata']['namespace']) - role_binding = rb_by_role[role['metadata']['name']] - - # If the RoleBinding subject is a ServiceAccount in the same namespace as the operator - # we add it to CSV and remove it from the by_kind dict - if len(role_binding['subjects']) == 1 and \ - role_binding['subjects'][0]['kind'] == 'ServiceAccount' and \ - role_binding['subjects'][0].get('namespace', namespace) == namespace: - csv['spec']['install']['spec']['permissions'].append( - { - 'rules': role['rules'], - 'serviceAccountName': role_binding['subjects'][0]['name'] - } - ) - trim_index(by_kind, 'Role', role) - trim_index(by_kind, 'RoleBinding', role_binding) - -## Add the Deployment -# We currently support a maximum of two Deployments -deploy = by_kind['Deployment'][0] -# Use the operator image pull spec we were passed -deploy['spec']['template']['spec']['containers'][0]['image'] = operator_image -# Add or replace OPERATOR_IMAGE env var -env = deploy['spec']['template']['spec']['containers'][0].get('env') -if env: - # Does OPERATOR_IMAGE key already exist in spec? If so, update value - for entry in env: - if entry['name'] == 'OPERATOR_IMAGE': - entry['value'] = operator_image - break - # If not, add it - else: - env.append(dict(name='OPERATOR_IMAGE', value=operator_image)) -else: - # The container has no environment variables, so just set this one - env = dict(name='OPERATOR_IMAGE', value=operator_image) - -csv['spec']['install']['spec']['deployments'] = [ - { - 'name': deploy['metadata']['name'], - 'spec': deploy['spec'], - } -] - -# If the supplementary image is specified, -# Append the Deployment to the CSV. -if hasMultipleDeployments: - deploy = by_kind['Deployment'][1] - deploy['spec']['template']['spec']['containers'][0]['image'] = supplementary_image - - csv['spec']['install']['spec']['deployments'].append( - { - 'name': deploy['metadata']['name'], - 'spec': deploy['spec'], - } - ) -# Get rid of these so we can iterate over what's left at the end -trim_index(by_kind, 'Deployment', 'ALL') - -# Get rid of ServiceAccounts -# TODO: Sanity check these against "generated" ServiceAccounts -print("Ignoring all explicitly defined ServiceAccounts") -trim_index(by_kind, 'ServiceAccount', 'ALL') - -# If there are any bindings left, it's an error -leftover_bindings = [] -for kind, _, _ in rolekind_csvkey_bindingmap: - leftover_bindings.extend(by_kind.get(kind, [])) -if leftover_bindings: - raise BindingsNotSupported(leftover_bindings) - -## Process any additional resources -# These don't go in the CSV; they just get copied into the bundle as is. -for kind, docs in by_kind.items(): - for doc in docs: - bundle(doc) - -# Update the versions to include git hash: -csv['metadata']['name'] = f"{OPERATOR_NAME}.v{full_version}" -csv['spec']['version'] = full_version - -# Support cross-catalog upgrades via OLM skiprange. -# Attributes 'skiprange' and 'replaces' cannot coexists in a CSV. -if skip_range_enabled == "true": - csv['metadata']['annotations']['olm.skipRange'] = f">=0.0.1 <{full_version}" -elif prev_version: - csv['spec']['replaces'] = f"{OPERATOR_NAME}.v{prev_version}" - -# Set the CSV createdAt annotation: -now = datetime.datetime.now() -csv['metadata']['annotations']['createdAt'] = now.strftime("%Y-%m-%dT%H:%M:%SZ") - -# Write the CSV to disk: -csv_filename = f"{OPERATOR_NAME}.v{full_version}.clusterserviceversion.yaml" -csv_file = os.path.join(VERSION_DIR, csv_filename) -with open(csv_file, 'w') as outfile: - yaml.dump(csv, outfile, default_flow_style=False) -print("Wrote ClusterServiceVersion: %s" % csv_file) diff --git a/boilerplate/openshift/golang-osd-operator/csv-generate/common.sh b/boilerplate/openshift/golang-osd-operator/csv-generate/common.sh deleted file mode 100644 index 2b44480a..00000000 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/common.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -REPO_ROOT=$(git rev-parse --show-toplevel) -source $REPO_ROOT/boilerplate/_lib/common.sh - -function check_mandatory_params() { - local csv_missing_param_error - local param_name - local param_val - for param_name in "$@"; do - eval param_val=\$$param_name - if [ -z "$param_val" ]; then - echo "Missing $param_name parameter" - csv_missing_param_error=true - fi - done - if [ ! -z "$csv_missing_param_error" ]; then - usage - fi -} - -# generateImageDigest returns the image URI as repo URL + image digest -function generateImageDigest() { - local param_image - local param_version - local image_digest - - param_image="$1" - param_version="$2" - if [[ -z $param_image || -z $param_version ]]; then - usage - fi - - image_digest=$(skopeo inspect docker://${param_image}:v${param_version} | jq -r .Digest) - if [[ -z "$image_digest" ]]; then - echo "Couldn't discover IMAGE_DIGEST for docker://${param_image}:v${param_version}!" - exit 1 - fi - - echo "${param_image}@${image_digest}" -} diff --git a/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.mk b/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.mk deleted file mode 100644 index bf4bb0ac..00000000 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.mk +++ /dev/null @@ -1,69 +0,0 @@ -.PHONY: staging-csv-build -staging-csv-build: - @${CONVENTION_DIR}/csv-generate/csv-generate.sh -o $(OPERATOR_NAME) -i $(OPERATOR_IMAGE) -V $(OPERATOR_VERSION) -c staging -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -s $(SUPPLEMENTARY_IMAGE) -e $(SKIP_RANGE_ENABLED) - -.PHONY: staging-catalog-build -staging-catalog-build: - @${CONVENTION_DIR}/csv-generate/catalog-build.sh -o $(OPERATOR_NAME) -c staging -r ${REGISTRY_IMAGE} - -.PHONY: staging-saas-bundle-push -staging-saas-bundle-push: - @${CONVENTION_DIR}/csv-generate/catalog-publish.sh -o $(OPERATOR_NAME) -c staging -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -r ${REGISTRY_IMAGE} - -.PHONY: staging-catalog-publish -staging-catalog-publish: - @${CONVENTION_DIR}/csv-generate/catalog-publish.sh -o $(OPERATOR_NAME) -c staging -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -p -r ${REGISTRY_IMAGE} - -.PHONY: staging-catalog-build-and-publish -staging-catalog-build-and-publish: - @$(MAKE) -s staging-csv-build --no-print-directory - @$(MAKE) -s staging-catalog-build --no-print-directory - @$(MAKE) -s staging-catalog-publish --no-print-directory - -.PHONY: production-hack-csv-build -production-hack-csv-build: - @${CONVENTION_DIR}/csv-generate/csv-generate.sh -o $(OPERATOR_NAME) -i $(OPERATOR_IMAGE) -V $(OPERATOR_VERSION) -c production -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -s $(SUPPLEMENTARY_IMAGE) -e $(SKIP_RANGE_ENABLED) -g hack - -.PHONY: production-csv-build -production-csv-build: - @${CONVENTION_DIR}/csv-generate/csv-generate.sh -o $(OPERATOR_NAME) -i $(OPERATOR_IMAGE) -V $(OPERATOR_VERSION) -c production -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -s $(SUPPLEMENTARY_IMAGE) -e $(SKIP_RANGE_ENABLED) - -.PHONY: production-catalog-build -production-catalog-build: - @${CONVENTION_DIR}/csv-generate/catalog-build.sh -o $(OPERATOR_NAME) -c production -r ${REGISTRY_IMAGE} - -.PHONY: production-saas-bundle-push -production-saas-bundle-push: - @${CONVENTION_DIR}/csv-generate/catalog-publish.sh -o $(OPERATOR_NAME) -c production -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -r ${REGISTRY_IMAGE} - -.PHONY: production-catalog-publish -production-catalog-publish: - @${CONVENTION_DIR}/csv-generate/catalog-publish.sh -o $(OPERATOR_NAME) -c production -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -p -r ${REGISTRY_IMAGE} - -.PHONY: production-catalog-build-and-publish -production-catalog-build-and-publish: - @$(MAKE) -s production-csv-build --no-print-directory - @$(MAKE) -s production-catalog-build --no-print-directory - @$(MAKE) -s production-catalog-publish --no-print-directory - -.PHONY: stable-csv-build -stable-csv-build: - @${CONVENTION_DIR}/csv-generate/csv-generate.sh -o $(OPERATOR_NAME) -i $(OPERATOR_IMAGE) -V $(OPERATOR_VERSION) -c stable -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -s $(SUPPLEMENTARY_IMAGE) -e $(SKIP_RANGE_ENABLED) - -.PHONY: stable-catalog-build -stable-catalog-build: - @${CONVENTION_DIR}/csv-generate/catalog-build.sh -o $(OPERATOR_NAME) -c stable -r ${REGISTRY_IMAGE} - -.PHONY: stable-saas-bundle-push -stable-saas-bundle-push: - @${CONVENTION_DIR}/csv-generate/catalog-publish.sh -o $(OPERATOR_NAME) -c stable -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -r ${REGISTRY_IMAGE} - -.PHONY: stable-catalog-publish -stable-catalog-publish: - @${CONVENTION_DIR}/csv-generate/catalog-publish.sh -o $(OPERATOR_NAME) -c stable -H $(CURRENT_COMMIT) -n $(COMMIT_NUMBER) -p -r ${REGISTRY_IMAGE} - -.PHONY: stable-catalog-build-and-publish -stable-catalog-build-and-publish: - @$(MAKE) -s stable-csv-build --no-print-directory - @$(MAKE) -s stable-catalog-build --no-print-directory - @$(MAKE) -s stable-catalog-publish --no-print-directory diff --git a/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.sh b/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.sh deleted file mode 100755 index 3778ebef..00000000 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.sh +++ /dev/null @@ -1,223 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source `dirname $0`/common.sh - -usage() { echo "Usage: $0 -o operator-name -c saas-repository-channel -H operator-commit-hash -n operator-commit-number -i operator-image -V operator-version -s supplementary-image -e skip-range-enabled" 1>&2; exit 1; } - -# TODO : Add support of long-options -while getopts "c:dg:H:i:n:o:V:s:e:" option; do - case "${option}" in - c) - operator_channel=${OPTARG} - ;; - H) - operator_commit_hash=${OPTARG} - ;; - i) - # This should be $OPERATOR_IMAGE from standard.mk - # I.e. the URL to the image repository with *no* tag. - operator_image=${OPTARG} - ;; - n) - operator_commit_number=${OPTARG} - ;; - o) - operator_name=${OPTARG} - ;; - V) - # This should be $OPERATOR_VERSION from standard.mk: - # `{major}.{minor}.{commit-number}-{hash}` - # Notably, it does *not* start with `v`. - operator_version=${OPTARG} - ;; - s) - supplementary_image=${OPTARG} - ;; - e) - skip_range_enabled=${OPTARG} - ;; - *) - usage - esac -done - -# Checking parameters -check_mandatory_params operator_channel operator_image operator_version operator_name operator_commit_hash operator_commit_number - -# Use set container engine or select one from available binaries -if [[ -z "$CONTAINER_ENGINE" ]]; then - CONTAINER_ENGINE=$(command -v podman || command -v docker || true) -fi - -if [[ -z "$CONTAINER_ENGINE" ]]; then - YQ_CMD="yq" -else - yq_image="quay.io/app-sre/yq:4" - $CONTAINER_ENGINE pull $yq_image - YQ_CMD="$CONTAINER_ENGINE run --rm -i $yq_image" -fi - -REPO_DIGEST=$(generateImageDigest $operator_image $operator_version) - -# Given a supplementary image is specified, -# generate the image digest. -if [[ -n $supplementary_image ]]; then - SECONDARY_REPO_DIGEST=$(generateImageDigest $supplementary_image $operator_version) - SECONDARY_REPO_DIGEST="-s ${SECONDARY_REPO_DIGEST}" -else - SECONDARY_REPO_DIGEST="" -fi - -# If no override, using the gitlab repo -if [ -z "$GIT_PATH" ] ; then - GIT_PATH="https://app:"${APP_SRE_BOT_PUSH_TOKEN}"@gitlab.cee.redhat.com/service/saas-${operator_name}-bundle.git" -fi - -# Calculate previous version -SAAS_OPERATOR_DIR="saas-${operator_name}-bundle" -BUNDLE_DIR="$SAAS_OPERATOR_DIR/${operator_name}/" - -rm -rf "$SAAS_OPERATOR_DIR" -BRANCH="$operator_channel" -if [[ "${RELEASE_BRANCHED_BUILDS}" ]]; then - # operator version will be set to `X.Y.BUILD_NUMBER-commit sha`, this will - # be `release-X.Y` - BRANCH="release-${operator_version%.*}" -fi - -if [[ "${RELEASE_BRANCHED_BUILDS}" ]]; then - git clone ${GIT_PATH} "$SAAS_OPERATOR_DIR" - pushd "${SAAS_OPERATOR_DIR}" - # if branch doesn't exist, checkout a new branch based on main/master - if git ls-remote --exit-code --heads "${GIT_PATH}" "${BRANCH}"; then - git checkout "${BRANCH}" - else - git checkout -b "${BRANCH}" - fi - popd -else - git clone --branch "$operator_channel" ${GIT_PATH} "$SAAS_OPERATOR_DIR" -fi - -# If this is a brand new SaaS setup, then set up accordingly -if [[ ! -d "${BUNDLE_DIR}" ]]; then - echo "Setting up new SaaS operator dir: ${BUNDLE_DIR}" - mkdir -p "${BUNDLE_DIR}" -fi - -# For testing purposes, support disabling anything that relies on -# querying the saas file in app-interface. This includes pruning -# undeployed commits in production. -# FIXME -- This should go away when we're querying app-interface via -# graphql. -if [[ -z "$SKIP_SAAS_FILE_CHECKS" ]]; then - # PATH to saas file in app-interface - SAAS_FILE_URL="https://gitlab.cee.redhat.com/service/app-interface/raw/master/data/services/osd-operators/cicd/saas/saas-${operator_name}.yaml" - - # MANAGED_RESOURCE_TYPE - # SAAS files contain the type of resources managed within the OC templates that - # are being applied to hive. - # For customer cluster resources this should always be of type "SelectorSyncSet" resources otherwise - # can't be sync'd to the customer cluster. We're explicity selecting the first element in the array. - # We can safely assume anything that is not of type "SelectorSyncSet" is being applied to hive only - # since it matches ClusterDeployment resources. - # From this we'll assume that the namespace reference in resourceTemplates to be: - # For customer clusters: /services/osd-operators/namespace//namespaces/cluster-scope.yaml - # For hive clusters: /services/osd-operators/namespace//namespaces/.yaml - MANAGED_RESOURCE_TYPE=$(curl -s "${SAAS_FILE_URL}" | \ - $YQ_CMD '.managedResourceTypes[0]' - - ) - if [[ "${MANAGED_RESOURCE_TYPE}" == "" ]]; then - echo "Unable to determine if SAAS file managed resource type" - exit 1 - fi - - # Determine namespace reference path, output resource type - if [[ "${MANAGED_RESOURCE_TYPE}" == "SelectorSyncSet" ]]; then - echo "SAAS file is NOT applied to Hive, MANAGED_RESOURCE_TYPE=$MANAGED_RESOURCE_TYPE" - resource_template_ns_path="/services/osd-operators/namespaces/hivep01ue1/cluster-scope.yml" - else - echo "SAAS file is applied to Hive, MANAGED_RESOURCE_TYPE=$MANAGED_RESOURCE_TYPE" - resource_template_ns_path="/services/osd-operators/namespaces/hivep01ue1/${operator_name}.yml" - fi - - # remove any versions more recent than deployed hash - if [[ "$operator_channel" == "production" ]]; then - if [ -z "$DEPLOYED_HASH" ] ; then - deployed_hash_yq_filter=".resourceTemplates[].targets[] | select(.namespace.\$ref == \"${resource_template_ns_path}\") | .ref" - DEPLOYED_HASH="$(curl -s "${SAAS_FILE_URL}" | $YQ_CMD "${deployed_hash_yq_filter}" -)" - fi - - # Ensure that our query for the current deployed hash worked - # Validate that our DEPLOYED_HASH var isn't empty. - # Although we have `set -e` defined the docker container isn't returning - # an error and allowing the script to continue - echo "Current deployed production HASH: $DEPLOYED_HASH" - - if [[ ! "${DEPLOYED_HASH}" =~ [0-9a-f]{40} ]]; then - echo "Error discovering current production deployed HASH" - exit 1 - fi - - delete=false - # Sort based on commit number - for version in $(ls $BUNDLE_DIR | sort -t . -k 3 -g); do - # skip if not directory - [ -d "$BUNDLE_DIR/$version" ] || continue - - if [[ "$delete" == false ]]; then - short_hash=$(echo "$version" | cut -d- -f2) - - if [[ "$DEPLOYED_HASH" == "${short_hash}"* ]]; then - delete=true - fi - else - rm -rf "${BUNDLE_DIR:?BUNDLE_DIR var not set}/$version" - fi - done - fi -fi # End of SKIP_SAAS_FILE_CHECKS granny switch - -OPERATOR_PREV_VERSION=$(ls "$BUNDLE_DIR" | sort -t . -k 3 -g | tail -n 1) -OPERATOR_NEW_VERSION="${operator_version}" -OUTPUT_DIR=${BUNDLE_DIR} - -VERSION_DIR="${OUTPUT_DIR}/${OPERATOR_NEW_VERSION}" - -# Check if the VERSION_DIR already exists and is not empty - if so skip building -# anything, as only timestamps would be changed. -if [[ -d "${VERSION_DIR}" && -n $(ls -A "${VERSION_DIR}") ]]; then - echo "Output directory for bundle already exists and is not empty: ${VERSION_DIR}. Skipping bundle creation." - exit 0 -fi - -# If setting up a new SaaS repo, there is no previous version when building a bundle -# Optionally pass it to the bundle generator in that case. -if [[ -z "${OPERATOR_PREV_VERSION}" ]]; then - PREV_VERSION_OPTS="" -else - OPERATOR_PREV_COMMIT_NUMBER=$(echo "${OPERATOR_PREV_VERSION}" | awk -F. '{print $3}' | awk -F- '{print $1}') - if [[ "${OPERATOR_PREV_COMMIT_NUMBER}" -gt "${operator_commit_number}" ]]; - then - echo "Revert detected. Reverting OLM operators is not allowed" - exit 99 - fi - - PREV_VERSION_OPTS="-p ${OPERATOR_PREV_VERSION}" -fi -# Jenkins can't be relied upon to have py3, so run the generator in -# a container. -# ...Unless we're already in a container, which is how boilerplate -# CI runs. We have py3 there, so run natively in that case. -if [[ -z "$CONTAINER_ENGINE" ]]; then - ./boilerplate/openshift/golang-osd-operator/csv-generate/common-generate-operator-bundle.py -o ${operator_name} -d ${OUTPUT_DIR} ${PREV_VERSION_OPTS} -i ${REPO_DIGEST} -V ${operator_version} ${SECONDARY_REPO_DIGEST} -e ${skip_range_enabled} -else - if [[ ${CONTAINER_ENGINE##*/} == "podman" ]]; then - CE_OPTS="--userns keep-id -v `pwd`:`pwd`:Z" - else - CE_OPTS="-v `pwd`:`pwd`" - fi - $CONTAINER_ENGINE run --pull=always --rm ${CE_OPTS} -u `id -u`:0 -w `pwd` registry.access.redhat.com/ubi8/python-36 /bin/bash -c "python -m pip install --disable-pip-version-check oyaml; python ./boilerplate/openshift/golang-osd-operator/csv-generate/common-generate-operator-bundle.py -o ${operator_name} -d ${OUTPUT_DIR} ${PREV_VERSION_OPTS} -i ${REPO_DIGEST} -V ${operator_version} ${SECONDARY_REPO_DIGEST} -e ${skip_range_enabled}" -fi diff --git a/boilerplate/openshift/golang-osd-operator/dependabot.yml b/boilerplate/openshift/golang-osd-operator/dependabot.yml deleted file mode 100644 index 004cb068..00000000 --- a/boilerplate/openshift/golang-osd-operator/dependabot.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "docker" - directory: "/build" - labels: - - "area/dependency" - - "ok-to-test" - schedule: - interval: "weekly" - ignore: - - dependency-name: "app-sre/boilerplate" - # don't upgrade boilerplate via these means - - dependency-name: "openshift4/ose-operator-registry" - # don't upgrade ose-operator-registry via these means diff --git a/boilerplate/openshift/golang-osd-operator/ensure.sh b/boilerplate/openshift/golang-osd-operator/ensure.sh deleted file mode 100755 index 5e51f810..00000000 --- a/boilerplate/openshift/golang-osd-operator/ensure.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env bash -set -x -set -eo pipefail - -REPO_ROOT=$(git rev-parse --show-toplevel) -source $REPO_ROOT/boilerplate/_lib/common.sh - -GOLANGCI_LINT_VERSION="1.59.1" -OPM_VERSION="v1.23.2" -GRPCURL_VERSION="1.7.0" -DEPENDENCY=${1:-} -GOOS=$(go env GOOS) - -case "${DEPENDENCY}" in - -golangci-lint) - GOPATH=$(go env GOPATH) - if which golangci-lint ; then - exit - else - mkdir -p "${GOPATH}/bin" - echo "${PATH}" | grep -q "${GOPATH}/bin" - IN_PATH=$? - if [ $IN_PATH != 0 ]; then - echo "${GOPATH}/bin not in $$PATH" - exit 1 - fi - DOWNLOAD_URL="https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/golangci-lint-${GOLANGCI_LINT_VERSION}-${GOOS}-amd64.tar.gz" - curl -sfL "${DOWNLOAD_URL}" | tar -C "${GOPATH}/bin" -zx --strip-components=1 "golangci-lint-${GOLANGCI_LINT_VERSION}-${GOOS}-amd64/golangci-lint" - fi - ;; - -opm) - mkdir -p .opm/bin - cd .opm/bin - - if [[ -x ./opm && "$(opm_version ./opm)" == "$OPM_VERSION" ]]; then - exit 0 - fi - - if which opm && [[ "$(opm_version $(which opm))" == "$OPM_VERSION" ]]; then - opm=$(realpath $(which opm)) - else - opm="opm-$OPM_VERSION-$GOOS-amd64" - opm_download_url="https://github.com/operator-framework/operator-registry/releases/download/$OPM_VERSION/$GOOS-amd64-opm" - curl -sfL "${opm_download_url}" -o "$opm" - chmod +x "$opm" - fi - - ln -fs "$opm" opm - ;; - -grpcurl) - mkdir -p .grpcurl/bin - cd .grpcurl/bin - - if [[ -x ./grpcurl && "$(grpcurl_version ./grpcurl)" == "$GRPCURL_VERSION" ]]; then - exit 0 - fi - - if which grpcurl && [[ "$(grpcurl_version $(which grpcurl))" == "$GRPCURL_VERSION" ]]; then - grpcurl=$(realpath $(which grpcurl)) - else - # mapping from https://github.com/fullstorydev/grpcurl/blob/master/.goreleaser.yml - [[ "$GOOS" == "darwin" ]] && os=osx || os="$GOOS" - grpcurl="grpcurl-$GRPCURL_VERSION-$os-x86_64" - grpcurl_download_url="https://github.com/fullstorydev/grpcurl/releases/download/v$GRPCURL_VERSION/grpcurl_${GRPCURL_VERSION}_${os}_x86_64.tar.gz" - curl -sfL "$grpcurl_download_url" | tar -xzf - -O grpcurl > "$grpcurl" - chmod +x "$grpcurl" - fi - - ln -fs "$grpcurl" grpcurl - ;; - -venv) - # Set up a python virtual environment - python3 -m venv .venv - # Install required libs, if a requirements file was given - if [[ -n "$2" ]]; then - .venv/bin/python3 -m pip install -r "$2" - fi - ;; - -*) - echo "Unknown dependency: ${DEPENDENCY}" - exit 1 - ;; -esac diff --git a/boilerplate/openshift/golang-osd-operator/fips.go.tmplt b/boilerplate/openshift/golang-osd-operator/fips.go.tmplt deleted file mode 100644 index d4b108ee..00000000 --- a/boilerplate/openshift/golang-osd-operator/fips.go.tmplt +++ /dev/null @@ -1,16 +0,0 @@ -//go:build fips_enabled -// +build fips_enabled - -// BOILERPLATE GENERATED -- DO NOT EDIT -// Run 'make ensure-fips' to regenerate - -package main - -import ( - _ "crypto/tls/fipsonly" - "fmt" -) - -func init() { - fmt.Println("***** Starting with FIPS crypto enabled *****") -} diff --git a/boilerplate/openshift/golang-osd-operator/golangci.yml b/boilerplate/openshift/golang-osd-operator/golangci.yml deleted file mode 100644 index b489f3ba..00000000 --- a/boilerplate/openshift/golang-osd-operator/golangci.yml +++ /dev/null @@ -1,33 +0,0 @@ -# options for analysis running -run: - # default concurrency is a available CPU number - concurrency: 10 - # timeout for analysis, e.g. 30s, 5m, default is 1m - # We're using a somewhat resource-constrained container in the CI - # environment, so make this longish. - timeout: 10m - -issues: - # We want to make sure we get a full report every time. Setting these - # to zero disables the limit. - max-issues-per-linter: 0 - max-same-issues: 0 - -linters: - disable-all: true - enable: - - errcheck - - gosec - - gosimple - - govet - - ineffassign - - misspell - - staticcheck - - typecheck - - unused - -linters-settings: - misspell: - extra-words: - - typo: "openshit" - correction: "OpenShift" diff --git a/boilerplate/openshift/golang-osd-operator/project.mk b/boilerplate/openshift/golang-osd-operator/project.mk deleted file mode 100644 index 1b9b5028..00000000 --- a/boilerplate/openshift/golang-osd-operator/project.mk +++ /dev/null @@ -1,53 +0,0 @@ -# Project specific values -OPERATOR_NAME?=$(shell sed -n 's/.*OperatorName .*"\([^"]*\)".*/\1/p' config/config.go) -OPERATOR_NAMESPACE?=$(shell sed -n 's/.*OperatorNamespace .*"\([^"]*\)".*/\1/p' config/config.go) - -IMAGE_REGISTRY?=quay.io -IMAGE_REPOSITORY?=app-sre -IMAGE_NAME?=$(OPERATOR_NAME) - -# Optional additional deployment image -SUPPLEMENTARY_IMAGE_NAME?=$(shell sed -n 's/.*SupplementaryImage .*"\([^"]*\)".*/\1/p' config/config.go) - -# Optional: Enable OLM skip-range -# https://v0-18-z.olm.operatorframework.io/docs/concepts/olm-architecture/operator-catalog/creating-an-update-graph/#skiprange -EnableOLMSkipRange?=$(shell sed -n 's/.*EnableOLMSkipRange .*"\([^"]*\)".*/\1/p' config/config.go) - -VERSION_MAJOR?=0 -VERSION_MINOR?=1 - -ifdef RELEASE_BRANCHED_BUILDS - # Make sure all called shell scripts know what's up - export RELEASE_BRANCHED_BUILDS - - # RELEASE_BRANCH from env vars takes precedence; if not set, try to figure it out - RELEASE_BRANCH:=${RELEASE_BRANCH} - ifneq ($(RELEASE_BRANCH),) - # Sanity check, just to be nice - RELEASE_BRANCH_TEST := $(shell echo ${RELEASE_BRANCH} | grep -E '^release-[0-9]+\.[0-9]+$$') - ifeq ($(RELEASE_BRANCH_TEST),) - $(warning Provided RELEASE_BRANCH doesn't conform to "release-X.Y" pattern; you sure you didn't make a mistake?) - endif - endif - - ifeq ($(RELEASE_BRANCH),) - # Check git repo's branch first - RELEASE_BRANCH := $(shell git rev-parse --abbrev-ref HEAD | grep -E '^release-[0-9]+\.[0-9]+$$') - endif - - ifeq ($(RELEASE_BRANCH),) - # Try to parse it out of Jenkins' JOB_NAME - RELEASE_BRANCH := $(shell echo ${JOB_NAME} | grep -E --only-matching 'release-[0-9]+\.[0-9]+') - endif - - ifeq ($(RELEASE_BRANCH),) - $(error RELEASE_BRANCHED_BUILDS is set, but couldn't detect a release branch and RELEASE_BRANCH is not set; giving up) - else - SEMVER := $(subst release-,,$(subst ., ,$(RELEASE_BRANCH))) - VERSION_MAJOR := $(firstword $(SEMVER)) - VERSION_MINOR := $(lastword $(SEMVER)) - endif -endif - -REGISTRY_USER?=$(QUAY_USER) -REGISTRY_TOKEN?=$(QUAY_TOKEN) diff --git a/boilerplate/openshift/golang-osd-operator/prow-config b/boilerplate/openshift/golang-osd-operator/prow-config deleted file mode 100755 index 9ff8f46f..00000000 --- a/boilerplate/openshift/golang-osd-operator/prow-config +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env bash - -set -e - -REPO_ROOT=$(git rev-parse --show-toplevel) -source $REPO_ROOT/boilerplate/_lib/common.sh -source $REPO_ROOT/boilerplate/_lib/release.sh - -cmd=${0##*/} - -usage() { - cat < $config_dir/$config -build_root: - from_repository: true -images: -- dockerfile_path: build/Dockerfile - to: unused -resources: - '*': - limits: - memory: 4Gi - requests: - cpu: 100m - memory: 200Mi -tests: -- as: coverage - commands: | - export CODECOV_TOKEN=\$(cat /tmp/secret/CODECOV_TOKEN) - make coverage - container: - from: src - secret: - mount_path: /tmp/secret - name: ${CONSUMER_NAME}-codecov-token -- as: publish-coverage - commands: | - export CODECOV_TOKEN=\$(cat /tmp/secret/CODECOV_TOKEN) - make coverage - container: - from: src - postsubmit: true - secret: - mount_path: /tmp/secret - name: ${CONSUMER_NAME}-codecov-token -- as: lint - commands: make lint - container: - from: src -- as: test - commands: make test - container: - from: src -- as: validate - commands: make validate - container: - from: src -zz_generated_metadata: - branch: ${DEFAULT_BRANCH} - org: ${CONSUMER_ORG} - repo: ${CONSUMER_NAME} -EOF - -make jobs - -release_done_msg $release_branch diff --git a/boilerplate/openshift/golang-osd-operator/py-requirements.txt b/boilerplate/openshift/golang-osd-operator/py-requirements.txt deleted file mode 100644 index 66f08c20..00000000 --- a/boilerplate/openshift/golang-osd-operator/py-requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pyyaml>=5.3.1 diff --git a/boilerplate/openshift/golang-osd-operator/rvmo-bundle.sh b/boilerplate/openshift/golang-osd-operator/rvmo-bundle.sh deleted file mode 100644 index f49d8c66..00000000 --- a/boilerplate/openshift/golang-osd-operator/rvmo-bundle.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -e - -REPOSITORY=${REPOSITORY:-"https://github.com/openshift/managed-release-bundle-osd.git"} -CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD|egrep '^main$|^release-[0-9]+\.[0-9]+$'|cat) -RVMO_BRANCH=${CURRENT_BRANCH:-main} -# You can override any branch detection by setting RELEASE_BRANCH -BRANCH=${RELEASE_BRANCH:-$RVMO_BRANCH} -DELETE_TEMP_DIR=${DELETE_TEMP_DIR:-true} -TMPD=$(mktemp -d --suffix -rvmo-bundle) -[[ "${DELETE_TEMP_DIR}" == "true" ]] && trap 'rm -rf ${TMPD}' EXIT - -cd "${TMPD}" -echo "Cloning RVMO from ${REPOSITORY}:${BRANCH}" -git clone --single-branch -b "${BRANCH}" "${REPOSITORY}" . -bash hack/update-operator-release.sh diff --git a/boilerplate/openshift/golang-osd-operator/standard.mk b/boilerplate/openshift/golang-osd-operator/standard.mk deleted file mode 100644 index 67a77b66..00000000 --- a/boilerplate/openshift/golang-osd-operator/standard.mk +++ /dev/null @@ -1,394 +0,0 @@ -# Validate variables in project.mk exist -ifndef IMAGE_REGISTRY -$(error IMAGE_REGISTRY is not set; check project.mk file) -endif -ifndef IMAGE_REPOSITORY -$(error IMAGE_REPOSITORY is not set; check project.mk file) -endif -ifndef IMAGE_NAME -$(error IMAGE_NAME is not set; check project.mk file) -endif -ifndef VERSION_MAJOR -$(error VERSION_MAJOR is not set; check project.mk file) -endif -ifndef VERSION_MINOR -$(error VERSION_MINOR is not set; check project.mk file) -endif - -### Accommodate docker or podman -# -# The docker/podman creds cache needs to be in a location unique to this -# invocation; otherwise it could collide across jenkins jobs. We'll use -# a .docker folder relative to pwd (the repo root). -CONTAINER_ENGINE_CONFIG_DIR = .docker -export REGISTRY_AUTH_FILE = ${CONTAINER_ENGINE_CONFIG_DIR}/config.json - -# If this configuration file doesn't exist, podman will error out. So -# we'll create it if it doesn't exist. -ifeq (,$(wildcard $(REGISTRY_AUTH_FILE))) -$(shell mkdir -p $(CONTAINER_ENGINE_CONFIG_DIR)) -# Copy the node container auth file so that we get access to the registries the -# parent node has access to -$(shell cp /var/lib/jenkins/.docker/config.json $(REGISTRY_AUTH_FILE)) -endif - -# ==> Docker uses --config=PATH *before* (any) subcommand; so we'll glue -# that to the CONTAINER_ENGINE variable itself. (NOTE: I tried half a -# dozen other ways to do this. This was the least ugly one that actually -# works.) -ifndef CONTAINER_ENGINE -CONTAINER_ENGINE=$(shell command -v podman 2>/dev/null || echo docker --config=$(CONTAINER_ENGINE_CONFIG_DIR)) -endif - -# Generate version and tag information from inputs -COMMIT_NUMBER=$(shell git rev-list `git rev-list --parents HEAD | grep -E "^[a-f0-9]{40}$$"`..HEAD --count) -CURRENT_COMMIT=$(shell git rev-parse --short=7 HEAD) -OPERATOR_VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).$(COMMIT_NUMBER)-g$(CURRENT_COMMIT) - -OPERATOR_IMAGE=$(IMAGE_REGISTRY)/$(IMAGE_REPOSITORY)/$(IMAGE_NAME) -OPERATOR_IMAGE_TAG=v$(OPERATOR_VERSION) -IMG?=$(OPERATOR_IMAGE):$(OPERATOR_IMAGE_TAG) -OPERATOR_IMAGE_URI=${IMG} -OPERATOR_IMAGE_URI_LATEST=$(IMAGE_REGISTRY)/$(IMAGE_REPOSITORY)/$(IMAGE_NAME):latest -OPERATOR_DOCKERFILE ?=build/Dockerfile -REGISTRY_IMAGE=$(IMAGE_REGISTRY)/$(IMAGE_REPOSITORY)/$(IMAGE_NAME)-registry -OPERATOR_REPO_NAME=$(shell git config --get remote.origin.url | sed 's,.*/,,; s/\.git$$//') - -ifeq ($(SUPPLEMENTARY_IMAGE_NAME),) -# We need SUPPLEMENTARY_IMAGE to be defined for csv-generate.mk -SUPPLEMENTARY_IMAGE="" -else -# If the configuration specifies a SUPPLEMENTARY_IMAGE_NAME -# then append the image registry and generate the image URI. -SUPPLEMENTARY_IMAGE=$(IMAGE_REGISTRY)/$(IMAGE_REPOSITORY)/$(SUPPLEMENTARY_IMAGE_NAME) -SUPPLEMENTARY_IMAGE_URI=$(IMAGE_REGISTRY)/$(IMAGE_REPOSITORY)/$(SUPPLEMENTARY_IMAGE_NAME):${OPERATOR_IMAGE_TAG} -endif - -ifeq ($(EnableOLMSkipRange), true) -SKIP_RANGE_ENABLED=true -else -SKIP_RANGE_ENABLED=false -endif - -# Consumer can optionally define ADDITIONAL_IMAGE_SPECS like: -# define ADDITIONAL_IMAGE_SPECS -# ./path/to/a/Dockerfile $(IMAGE_REGISTRY)/$(IMAGE_REPOSITORY)/a-image:v1.2.3 -# ./path/to/b/Dockerfile $(IMAGE_REGISTRY)/$(IMAGE_REPOSITORY)/b-image:v4.5.6 -# endef -# Each will be conditionally built and pushed along with the operator image. -define IMAGES_TO_BUILD -$(OPERATOR_DOCKERFILE) $(OPERATOR_IMAGE_URI) -$(ADDITIONAL_IMAGE_SPECS) -endef -export IMAGES_TO_BUILD - -OLM_BUNDLE_IMAGE = $(OPERATOR_IMAGE)-bundle -OLM_CATALOG_IMAGE = $(OPERATOR_IMAGE)-catalog -OLM_CHANNEL ?= alpha - -REGISTRY_USER ?= -REGISTRY_TOKEN ?= - -GOOS?=$(shell go env GOOS) -GOARCH?=$(shell go env GOARCH) -GOBIN?=$(shell go env GOBIN) - -# Consumers may override GOFLAGS_MOD e.g. to use `-mod=vendor` -unexport GOFLAGS -GOFLAGS_MOD ?= - -# In openshift ci (Prow), we need to set $HOME to a writable directory else tests will fail -# because they don't have permissions to create /.local or /.cache directories -# as $HOME is set to "/" by default. -ifeq ($(HOME),/) -export HOME=/tmp/home -endif -PWD=$(shell pwd) - -GOENV=GOOS=${GOOS} GOARCH=${GOARCH} CGO_ENABLED=1 GOFLAGS="${GOFLAGS_MOD}" -GOBUILDFLAGS=-gcflags="all=-trimpath=${GOPATH}" -asmflags="all=-trimpath=${GOPATH}" - -ifeq (${FIPS_ENABLED}, true) -GOFLAGS_MOD+=-tags=fips_enabled -GOFLAGS_MOD:=$(strip ${GOFLAGS_MOD}) -$(warning Setting GOEXPERIMENT=strictfipsruntime,boringcrypto - this generally causes builds to fail unless building inside the provided Dockerfile. If building locally consider calling 'go build .') -GOENV+=GOEXPERIMENT=strictfipsruntime,boringcrypto -GOENV:=$(strip ${GOENV}) -endif - -# GOLANGCI_LINT_CACHE needs to be set to a directory which is writeable -# Relevant issue - https://github.com/golangci/golangci-lint/issues/734 -GOLANGCI_LINT_CACHE ?= /tmp/golangci-cache - -GOLANGCI_OPTIONAL_CONFIG ?= - -ifeq ($(origin TESTTARGETS), undefined) -TESTTARGETS := $(shell ${GOENV} go list -e ./... | grep -E -v "/(vendor)/" | grep -E -v "/(osde2e)/") -endif -# ex, -v -TESTOPTS := - -ALLOW_DIRTY_CHECKOUT?=false - -# TODO: Figure out how to discover this dynamically -CONVENTION_DIR := boilerplate/openshift/golang-osd-operator -BOILERPLATE_CONTAINER_MAKE := boilerplate/_lib/container-make - -# Set the default goal in a way that works for older & newer versions of `make`: -# Older versions (<=3.8.0) will pay attention to the `default` target. -# Newer versions pay attention to .DEFAULT_GOAL, where unsetting it makes the next defined target the default: -# https://www.gnu.org/software/make/manual/make.html#index-_002eDEFAULT_005fGOAL-_0028define-default-goal_0029 -.DEFAULT_GOAL := -.PHONY: default -default: go-check go-test go-build - -.PHONY: clean -clean: - rm -rf ./build/_output - -.PHONY: isclean -isclean: - @(test "$(ALLOW_DIRTY_CHECKOUT)" != "false" || test 0 -eq $$(git status --porcelain | wc -l)) || (echo "Local git checkout is not clean, commit changes and try again or use ALLOW_DIRTY_CHECKOUT=true to override." >&2 && git --no-pager diff && exit 1) - -# TODO: figure out how to docker-login only once across multiple `make` calls -.PHONY: docker-build-push-one -docker-build-push-one: isclean docker-login - @(if [[ -z "${IMAGE_URI}" ]]; then echo "Must specify IMAGE_URI"; exit 1; fi) - @(if [[ -z "${DOCKERFILE_PATH}" ]]; then echo "Must specify DOCKERFILE_PATH"; exit 1; fi) - ${CONTAINER_ENGINE} build --pull -f $(DOCKERFILE_PATH) -t $(IMAGE_URI) . - ${CONTAINER_ENGINE} push ${IMAGE_URI} - -# TODO: Get rid of docker-build. It's only used by opm-build-push -.PHONY: docker-build -docker-build: isclean - ${CONTAINER_ENGINE} build --pull -f $(OPERATOR_DOCKERFILE) -t $(OPERATOR_IMAGE_URI) . - ${CONTAINER_ENGINE} tag $(OPERATOR_IMAGE_URI) $(OPERATOR_IMAGE_URI_LATEST) - -# TODO: Get rid of docker-push. It's only used by opm-build-push -.PHONY: docker-push -docker-push: docker-login docker-build - ${CONTAINER_ENGINE} push ${OPERATOR_IMAGE_URI} - ${CONTAINER_ENGINE} push ${OPERATOR_IMAGE_URI_LATEST} - -# TODO: Get rid of push. It's not used. -.PHONY: push -push: docker-push - -.PHONY: docker-login -docker-login: - @test "${REGISTRY_USER}" != "" && test "${REGISTRY_TOKEN}" != "" || (echo "REGISTRY_USER and REGISTRY_TOKEN must be defined" && exit 1) - mkdir -p ${CONTAINER_ENGINE_CONFIG_DIR} - @${CONTAINER_ENGINE} login -u="${REGISTRY_USER}" -p="${REGISTRY_TOKEN}" quay.io - -.PHONY: go-check -go-check: ## Golang linting and other static analysis - ${CONVENTION_DIR}/ensure.sh golangci-lint - GOLANGCI_LINT_CACHE=${GOLANGCI_LINT_CACHE} golangci-lint run -c ${CONVENTION_DIR}/golangci.yml ./... - test "${GOLANGCI_OPTIONAL_CONFIG}" = "" || test ! -e "${GOLANGCI_OPTIONAL_CONFIG}" || GOLANGCI_LINT_CACHE="${GOLANGCI_LINT_CACHE}" golangci-lint run -c "${GOLANGCI_OPTIONAL_CONFIG}" ./... - -.PHONY: go-generate -go-generate: - ${GOENV} go generate $(TESTTARGETS) - # Don't forget to commit generated files - -# go-get-tool will 'go install' any package $2 and install it to $1. -define go-get-tool -@{ \ -set -e ;\ -TMP_DIR=$$(mktemp -d) ;\ -cd $$TMP_DIR ;\ -go mod init tmp ;\ -echo "Downloading $(2)" ;\ -GOBIN=$(shell dirname $(1)) go install $(2) ;\ -echo "Installed in $(1)" ;\ -rm -rf $$TMP_DIR ;\ -} -endef - -CONTROLLER_GEN = controller-gen -OPENAPI_GEN = openapi-gen -KUSTOMIZE = kustomize -YQ = yq - -.PHONY: op-generate -## CRD v1beta1 is no longer supported. -op-generate: - cd ./api; $(CONTROLLER_GEN) crd:crdVersions=v1,generateEmbeddedObjectMeta=true paths=./... output:dir=$(PWD)/deploy/crds - cd ./api; $(CONTROLLER_GEN) object paths=./... - -.PHONY: openapi-generate -openapi-generate: - find ./api -maxdepth 2 -mindepth 1 -type d | xargs -t -I% \ - $(OPENAPI_GEN) --logtostderr=true \ - -i % \ - -o "" \ - -O zz_generated.openapi \ - -p % \ - -h /dev/null \ - -r "-" - -.PHONY: manifests -manifests: -# Only use kustomize to template out manifests if the path config/default exists -ifneq (,$(wildcard config/default)) - $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." - $(KUSTOMIZE) build config/default | $(YQ) -s '"deploy/" + .metadata.name + "." + .kind + ".yaml"' -else - $(info Did not find 'config/default' - skipping kustomize manifest generation) -endif - -.PHONY: generate -generate: op-generate go-generate openapi-generate manifests - -ifeq (${FIPS_ENABLED}, true) -go-build: ensure-fips -endif - -.PHONY: go-build -go-build: ## Build binary - # Force GOOS=linux as we may want to build containers in other *nix-like systems (ie darwin). - # This is temporary until a better container build method is developed - ${GOENV} GOOS=linux go build ${GOBUILDFLAGS} -o build/_output/bin/$(OPERATOR_NAME) . - -# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.23 -SETUP_ENVTEST = setup-envtest - -.PHONY: setup-envtest -setup-envtest: - $(eval KUBEBUILDER_ASSETS := "$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) -p path --bin-dir /tmp/envtest/bin)") - -# Setting SHELL to bash allows bash commands to be executed by recipes. -# This is a requirement for 'setup-envtest.sh' in the test target. -# Options are set to exit when a recipe line exits non-zero or a piped command fails. -SHELL = /usr/bin/env bash -o pipefail -.SHELLFLAGS = -ec - -.PHONY: go-test -go-test: setup-envtest - KUBEBUILDER_ASSETS=$(KUBEBUILDER_ASSETS) go test $(TESTOPTS) $(TESTTARGETS) - -.PHONY: python-venv -python-venv: - ${CONVENTION_DIR}/ensure.sh venv ${CONVENTION_DIR}/py-requirements.txt - $(eval PYTHON := .venv/bin/python3) - -.PHONY: generate-check -generate-check: - @$(MAKE) -s isclean --no-print-directory - @$(MAKE) -s generate --no-print-directory - @$(MAKE) -s isclean --no-print-directory || (echo 'Files after generation are different than committed ones. Please commit updated and unaltered generated files' >&2 && exit 1) - @echo "All generated files are up-to-date and unaltered" - -.PHONY: yaml-validate -yaml-validate: python-venv - ${PYTHON} ${CONVENTION_DIR}/validate-yaml.py $(shell git ls-files | grep -E -v '^(vendor|boilerplate)/' | grep -E '.*\.ya?ml') - -.PHONY: olm-deploy-yaml-validate -olm-deploy-yaml-validate: python-venv - ${PYTHON} ${CONVENTION_DIR}/validate-yaml.py $(shell git ls-files 'deploy/*.yaml' 'deploy/*.yml') - -.PHONY: prow-config -prow-config: - ${CONVENTION_DIR}/prow-config ${RELEASE_CLONE} - - -###################### -# Targets used by prow -###################### - -# validate: Ensure code generation has not been forgotten; and ensure -# generated and boilerplate code has not been modified. -.PHONY: validate -validate: boilerplate-freeze-check generate-check - -# lint: Perform static analysis. -.PHONY: lint -lint: olm-deploy-yaml-validate go-check - -# test: "Local" unit and functional testing. -.PHONY: test -test: go-test - -# coverage: Code coverage analysis and reporting. -.PHONY: coverage -coverage: - ${CONVENTION_DIR}/codecov.sh - -######################### -# Targets used by app-sre -######################### - -# build-push: Construct, tag, and push the official operator and -# registry container images. -# TODO: Boilerplate this script. -.PHONY: build-push -build-push: - OPERATOR_VERSION="${OPERATOR_VERSION}" \ - ${CONVENTION_DIR}/app-sre-build-deploy.sh ${REGISTRY_IMAGE} ${CURRENT_COMMIT} "$$IMAGES_TO_BUILD" - -.PHONY: opm-build-push -opm-build-push: python-venv docker-push - OLM_BUNDLE_IMAGE="${OLM_BUNDLE_IMAGE}" \ - OLM_CATALOG_IMAGE="${OLM_CATALOG_IMAGE}" \ - CONTAINER_ENGINE="${CONTAINER_ENGINE}" \ - CONTAINER_ENGINE_CONFIG_DIR="${CONTAINER_ENGINE_CONFIG_DIR}" \ - CURRENT_COMMIT="${CURRENT_COMMIT}" \ - OPERATOR_VERSION="${OPERATOR_VERSION}" \ - OPERATOR_NAME="${OPERATOR_NAME}" \ - OPERATOR_IMAGE="${OPERATOR_IMAGE}" \ - OPERATOR_IMAGE_TAG="${OPERATOR_IMAGE_TAG}" \ - OLM_CHANNEL="${OLM_CHANNEL}" \ - ${CONVENTION_DIR}/build-opm-catalog.sh - -.PHONY: ensure-fips -ensure-fips: - ${CONVENTION_DIR}/configure-fips.sh - -# You will need to export the forked/cloned operator repository directory as OLD_SDK_REPO_DIR to make this work. -# Example: export OLD_SDK_REPO_DIR=~/Projects/My-Operator-Fork -.PHONY: migrate-to-osdk1 -migrate-to-osdk1: -ifndef OLD_SDK_REPO_DIR - $(error OLD_SDK_REPO_DIR is not set) -endif - # Copying files & folders from old repository to current project - rm -rf config - rsync -a $(OLD_SDK_REPO_DIR)/deploy . --exclude=crds - rsync -a $(OLD_SDK_REPO_DIR)/pkg . --exclude={'apis','controller'} - rsync -a $(OLD_SDK_REPO_DIR)/Makefile . - rsync -a $(OLD_SDK_REPO_DIR)/.gitignore . - rsync -a $(OLD_SDK_REPO_DIR)/ . --exclude={'cmd','version','boilerplate','deploy','pkg'} --ignore-existing - -# Boilerplate container-make targets. -# Runs 'make' in the boilerplate backing container. -# If the command fails, starts a shell in the container so you can debug. -.PHONY: container-test -container-test: - ${BOILERPLATE_CONTAINER_MAKE} test - -.PHONY: container-generate -container-generate: - ${BOILERPLATE_CONTAINER_MAKE} generate - -.PHONY: container-lint -container-lint: - ${BOILERPLATE_CONTAINER_MAKE} lint - -.PHONY: container-validate -container-validate: - ${BOILERPLATE_CONTAINER_MAKE} validate - -.PHONY: container-coverage -container-coverage: - ${BOILERPLATE_CONTAINER_MAKE} coverage - -.PHONY: rvmo-bundle -rvmo-bundle: - RELEASE_BRANCH=$(RELEASE_BRANCH) \ - REPO_NAME=$(OPERATOR_REPO_NAME) \ - OPERATOR_NAME=$(OPERATOR_NAME) \ - OPERATOR_VERSION=$(OPERATOR_VERSION) \ - OPERATOR_OLM_REGISTRY_IMAGE=$(REGISTRY_IMAGE) \ - TEMPLATE_DIR=$(abspath hack/release-bundle) \ - bash ${CONVENTION_DIR}/rvmo-bundle.sh diff --git a/boilerplate/openshift/golang-osd-operator/update b/boilerplate/openshift/golang-osd-operator/update deleted file mode 100755 index f64a6f27..00000000 --- a/boilerplate/openshift/golang-osd-operator/update +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source $CONVENTION_ROOT/_lib/common.sh - -# No PRE -[[ "$1" == "PRE" ]] && exit 0 - -# Expect POST -[[ "$1" == "POST" ]] || err "Got a parameter I don't understand: '$1'. Did the infrastructure change?" - -# Add codecov configuration -echo "Copying .codecov.yml to your repository root." -cp ${HERE}/.codecov.yml $REPO_ROOT - -# Add OWNERS_ALIASES to $REPO_ROOT -echo "Copying OWNERS_ALIASES to your repository root." -cp ${HERE}/OWNERS_ALIASES $REPO_ROOT - -# Add dependabot configuration -mkdir -p $REPO_ROOT/.github -echo "Copying dependabot.yml to .github/dependabot.yml" -cp ${HERE}/dependabot.yml ${REPO_ROOT}/.github/dependabot.yml - -# Add olm-registry Dockerfile -mkdir -p $REPO_ROOT/build -echo "Copying Dockerfile.olm-registry to build/Dockerfile.olm-registry" -cp ${HERE}/Dockerfile.olm-registry ${REPO_ROOT}/build/Dockerfile.olm-registry -# if the gitignore file exists, remove the olm-registry line -if [[ -f ${REPO_ROOT}/.gitignore ]]; then - ${SED?} -i "/Dockerfile.olm-registry/d" ${REPO_ROOT}/.gitignore -fi - -# Update Dockerfile builder image -DOCKERFILES=$(ls -1 $REPO_ROOT/build/Dockerfile*) -for file in $DOCKERFILES; do - # only update boilerplate base on the main file - if [[ $file == *"Dockerfile" ]]; then - echo "Overwriting $file's initial FROM with $IMAGE_PULL_PATH" - ${SED?} -i "1s,.*,FROM $IMAGE_PULL_PATH AS builder," $file - fi - - # Update any UBI images to use a versioned tag of ubi8/ubi-minimal that is compatible with dependabot - for ubi_latest in $(grep -oE 'registry.access.redhat.com/ubi[7-9]/ubi.*?:.*' ${file}); do - replacement_image=$(skopeo inspect --override-os linux --override-arch amd64 docker://registry.access.redhat.com/ubi8/ubi-minimal --format "{{.Name}}:{{.Labels.version}}-{{.Labels.release}}") - echo "Overwriting ${file}'s ${ubi_latest} image to ${replacement_image}" - ${SED?} -i "s,${ubi_latest},${replacement_image}," ${file} - done -done - -# Add ci-operator configuration -echo "Writing .ci-operator.yaml in your repository root with:" -echo " namespace: $IMAGE_NAMESPACE" -echo " name: $IMAGE_NAME" -echo " tag: $LATEST_IMAGE_TAG" -${SED?} "s/__NAMESPACE__/$IMAGE_NAMESPACE/; s/__NAME__/$IMAGE_NAME/; s/__TAG__/$LATEST_IMAGE_TAG/" ${HERE}/.ci-operator.yaml > $REPO_ROOT/.ci-operator.yaml - -cat </dev/null && pwd ))" -CONFIG_FILE="${CONVENTION_ROOT}/update.cfg" - -# Set SED variable -if LANG=C sed --help 2>&1 | grep -q GNU; then - SED="sed" -elif command -v gsed &>/dev/null; then - SED="gsed" -else - echo "Failed to find GNU sed as sed or gsed. If you are on Mac: brew install gnu-sed." >&2 - exit 1 -fi - -# scrubbed_conventions -# Parses the $CONFIG_FILE and outputs a space-delimited list of conventions. -scrubbed_conventions() { - local conventions= - - while read convention junk; do - # Skip comment lines (which can have leading whitespace) - if [[ "$convention" == '#'* ]]; then - continue - fi - - # Skip blank or whitespace-only lines - if [[ "$convention" == "" ]]; then - continue - fi - - # Lines like - # valid/path other_junk - # are not acceptable, unless `other_junk` is a comment - if [[ "$junk" != "" ]] && [[ "$junk" != '#'* ]]; then - echo "Invalid config! Only one convention is allowed per line. Found '$junk'" - exit 1 - fi - - # This one is legit - echo $convention - - done < "$CONFIG_FILE" -} - -## unacceptable_deltas [GREP_FLAGS] -# -# Looks for uncommitted changes in the current checkout, ignoring certain -# things as noted below. -# -# If changes are found, they are printed (à la `git status --porcelain`) -# and the function returns nonzero. -# -# If no changes are found, the function is silent and returns zero. -# -# Ignores: -# This function ignores uncommitted changes to: -# - Makefile: Editing this file is part of bootstrapping, and we don't -# want to force an additional commit in the bootstrapping process. -# - .gitattributes: This file is created as part of the bootstrapping -# process. See above. -# - ?? boilerplate/: I.e. the boilerplate subdirectory is brand new, -# meaning you're bootstrapping. See above. -# - boilerplate/update.cfg: Changing this file prior to an update is -# part of the process of subscribing to new conventions. -unacceptable_deltas() { - ignores="Makefile|.gitattributes|boilerplate/(update\.cfg)?" - git status --porcelain | grep -E -v $1 " ($ignores)$" -} - -# We're initially invoked with no arguments. The branch below clones the -# boilerplate repo at the latest level into a temporary directory and copies in -# the update script (this script) and utilities back into the consuming repo. -# Then it re-execs this script with the temporary directory as a CLI argument. -if [[ -z "$1" ]]; then - if unacceptable_deltas -q; then - cat <"${NEXUS_MK}" -# THIS FILE IS GENERATED BY BOILERPLATE. DO NOT EDIT. -# This file automatically includes any *.mk files in your subscribed -# conventions. Please ensure your base Makefile includes only this file. -include boilerplate/_lib/boilerplate.mk -EOF - -for convention in $(scrubbed_conventions $CONFIG_FILE); do - dir_path="${BP_CLONE}/boilerplate/${convention}" - # Make sure the directory exists - if ! [[ -d "$dir_path" ]]; then - echo "Invalid convention directory: '$convention'" - exit 1 - fi - - echo "***********************************************************************************" - echo "$convention is configured in update.cfg." - echo "-----------------------------------------------------------------------------------" - echo "syncing files from source." - if [ -f "${dir_path}/update" ]; then - # Always run the *new* update script - mkdir -p "${CONVENTION_ROOT}/${convention}" - rsync -a "${dir_path}/update" "${CONVENTION_ROOT}/${convention}" - echo "executing ${CONVENTION_ROOT}/${convention}/update PRE" - "${CONVENTION_ROOT}/${convention}/update" PRE - fi - rm -rf "${CONVENTION_ROOT}/${convention}" - mkdir -p $(dirname "${CONVENTION_ROOT}/${convention}") - rsync -a -r --delete "$dir_path" $(dirname "${CONVENTION_ROOT}/${convention}") - if [ -f "${CONVENTION_ROOT}/${convention}/update" ]; then - echo "executing ${CONVENTION_ROOT}/${convention}/update POST" - "${CONVENTION_ROOT}/${convention}/update" POST - fi - echo "adding makefile includes." - for inc in $(find "${CONVENTION_ROOT}/${convention}" -type f -name '*.mk' | sort); do - echo "include ${inc#$REPO_ROOT/}" >> "${NEXUS_MK}" - done - echo "***********************************************************************************" - echo "" -done - -# (Create and) edit .gitattributes to -# - override hiding boilerplate files related to freeze-check (so they -# can't be hacked without you seeing it in the PR by default) -# - unhide .gitattributes itself (so these rules can't be changed -# without you seeing it in the PR by default) -echo "Processing .gitattributes" -gitattributes=${REPO_ROOT}/.gitattributes -if [[ -f "${gitattributes}" ]]; then - # Delete the previously generated section - ${SED?} -i '/BEGIN BOILERPLATE GENERATED/,/END BOILERPLATE GENERATED/d' "${gitattributes}" -fi -# .gitattributes is processed in top-down order. Putting these entries at the -# end ensures they take precedence over earlier, manual entries. -cat <>"${gitattributes}" -### BEGIN BOILERPLATE GENERATED -- DO NOT EDIT ### -### This block must be the last thing in your ### -### .gitattributes file; otherwise the 'validate' ### -### CI check will fail. ### -# Used to ensure nobody mucked with boilerplate files. -boilerplate/_lib/freeze-check linguist-generated=false -# Show the boilerplate commit hash update. It's only one line anyway. -boilerplate/_data/last-boilerplate-commit linguist-generated=false -# Used by freeze-check. Good place for attackers to inject badness. -boilerplate/update linguist-generated=false -# Make sure attackers can't hide changes to this configuration -.gitattributes linguist-generated=false -### END BOILERPLATE GENERATED ### -EOF - -# If all that went well, record some metadata. -mkdir -p ${CONVENTION_ROOT}/_data -# - The last-boilerplate-commit file, which allows freeze-check to work. -echo "Registering commit hash..." -bp_commit=$(cd ${BP_CLONE} && git rev-parse HEAD) -echo ${bp_commit} > ${CONVENTION_ROOT}/_data/last-boilerplate-commit - -# - The boilerplate backing image tag. This is used to run containerized -# local builds/tests. -echo "Registering image tag..." -echo $LATEST_IMAGE_TAG > ${CONVENTION_ROOT}/_data/backing-image-tag - -echo "Done" diff --git a/boilerplate/update.cfg b/boilerplate/update.cfg deleted file mode 100644 index 7e194b21..00000000 --- a/boilerplate/update.cfg +++ /dev/null @@ -1,2 +0,0 @@ -# Use standards for Go-based OSD operators -openshift/golang-osd-operator diff --git a/build/Dockerfile.test b/build/Dockerfile.test deleted file mode 100644 index 88c9f73b..00000000 --- a/build/Dockerfile.test +++ /dev/null @@ -1,9 +0,0 @@ -# Manually keep this in sync with Dockerfile until boilerplate supports it -FROM quay.io/app-sre/boilerplate:image-v0.2.0 AS builder - -RUN mkdir -p /workdir -COPY . /workdir -WORKDIR /workdir - -ENTRYPOINT ["make"] -CMD ["go-check", "test"]