diff --git a/.ci-operator.yaml b/.ci-operator.yaml index 22d2bf0..4f56e30 100644 --- a/.ci-operator.yaml +++ b/.ci-operator.yaml @@ -1,4 +1,4 @@ build_root_image: name: boilerplate namespace: openshift - tag: image-v2.3.2 + tag: image-v4.0.2 diff --git a/.codecov.yml b/.codecov.yml index 844b447..ba05647 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -24,3 +24,7 @@ comment: layout: "reach,diff,flags,tree" behavior: default require_changes: no + +ignore: + - "**/mocks" + - "**/zz_generated*.go" diff --git a/.docker/config.json b/.docker/config.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.docker/config.json @@ -0,0 +1 @@ +{} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..004cb06 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +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/OWNERS_ALIASES b/OWNERS_ALIASES new file mode 100644 index 0000000..ecc0d0a --- /dev/null +++ b/OWNERS_ALIASES @@ -0,0 +1,82 @@ +# ================================ 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 + - bdematte + - boranx + - dakotalongRH + - lnguyen1401 + - luis-falcon + - rafael-azevedo + srep-functional-team-fedramp: + - tonytheleg + - theautoroboto + - rhdedgar + - katherinelc321 + - robotmaxtron + - rojasreinold + srep-functional-team-hulk: + - a7vicky + - rendhalver + - ravitri + - shitaljante + - weherdh + - devppratik + srep-functional-team-orange: + - bng0y + - typeid + - Makdaam + - Nikokolas3270 + - ninabauer + - RaphaelBut + - Tessg22 + srep-functional-team-rocket: + - aliceh + - anispate + - bdmiller3 + - clcollins + - mjlshen + - tnierman + - yithian + srep-functional-team-security: + - gsleeman + - jaybeeunix + - sam-nguyen7 + - wshearn + srep-functional-team-thor: + - bmeng + - MitaliBhalla + - hectorakemp + - feichashao + - Tafhim + - samanthajayasinghe + srep-functional-team-v1alpha1: + - iamkirkbater + - AlexVulaj + - T0MASD + - bergmannf + - dkeohane + - reedcort + - mrWinston + srep-functional-leads: + - rafael-azevedo + - iamkirkbater + - bng0y + - tonytheleg + - bmeng + - mjlshen + - sam-nguyen7 + - ravitri + srep-team-leads: + - NautiluX + - rogbas + - fahlmant + - dustman9000 + - wanghaoran1988 + srep-architects: + - jewzaam + - jharrington22 + - cblecker diff --git a/boilerplate/_data/backing-image-tag b/boilerplate/_data/backing-image-tag index bb65150..041381e 100644 --- a/boilerplate/_data/backing-image-tag +++ b/boilerplate/_data/backing-image-tag @@ -1 +1 @@ -image-v2.3.2 +image-v4.0.2 diff --git a/boilerplate/_data/last-boilerplate-commit b/boilerplate/_data/last-boilerplate-commit index 1f4cbe9..64b6216 100644 --- a/boilerplate/_data/last-boilerplate-commit +++ b/boilerplate/_data/last-boilerplate-commit @@ -1 +1 @@ -0a69514b0c6b0cec124afb603ae2fd2e02ec7fcd +a48d90919cb9a4fe3b4bbd51ac6ef71ea1b49ed6 diff --git a/boilerplate/_lib/container-make b/boilerplate/_lib/container-make index 08850ce..e847e3a 100755 --- a/boilerplate/_lib/container-make +++ b/boilerplate/_lib/container-make @@ -19,10 +19,14 @@ 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="--userns keep-id -v $REPO_ROOT:$CONTAINER_MOUNT:Z" + 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="-v $REPO_ROOT:$CONTAINER_MOUNT" + CE_OPTS="${CE_OPTS} -v $REPO_ROOT:$CONTAINER_MOUNT" fi container_id=$($CONTAINER_ENGINE run -d ${CE_OPTS} $IMAGE_PULL_PATH sleep infinity) diff --git a/boilerplate/_lib/freeze-check b/boilerplate/_lib/freeze-check index 88c91bb..080629f 100755 --- a/boilerplate/_lib/freeze-check +++ b/boilerplate/_lib/freeze-check @@ -35,7 +35,7 @@ BOILERPLATE_GIT_REPO=https://github.com/openshift/boilerplate.git # 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)" ]; then +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 @@ -70,9 +70,9 @@ cd $REPO_ROOT BOILERPLATE_GIT_CLONE="git clone $TMPD" boilerplate/update # Okay, if anything has changed, that's bad. -if [[ $(git status --porcelain | wc -l) -ne 0 ]]; then +if [[ $(git status --porcelain -- ':!build/Dockerfile*' | wc -l) -ne 0 ]]; then echo "Your boilerplate is dirty!" >&2 - git status --porcelain + git status --porcelain -- ':!build/Dockerfile*' exit 1 fi diff --git a/boilerplate/_lib/release.sh b/boilerplate/_lib/release.sh index 3ce9c4b..3a98c93 100755 --- a/boilerplate/_lib/release.sh +++ b/boilerplate/_lib/release.sh @@ -97,7 +97,7 @@ 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 git@github.com:${RELEASE_REPO}.git $RELEASE_CLONE + 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." diff --git a/boilerplate/_lib/subscriber-report b/boilerplate/_lib/subscriber-report index 3150302..022b27d 100755 --- a/boilerplate/_lib/subscriber-report +++ b/boilerplate/_lib/subscriber-report @@ -11,4 +11,3 @@ SUBCOMMANDS=( ) source $REPO_ROOT/boilerplate/_lib/subscriber.sh - diff --git a/boilerplate/_lib/subscriber.sh b/boilerplate/_lib/subscriber.sh index 62ddcaa..23214f2 100644 --- a/boilerplate/_lib/subscriber.sh +++ b/boilerplate/_lib/subscriber.sh @@ -69,13 +69,11 @@ SUBSCRIBERS_FILE=$REPO_ROOT/subscribers.yaml # all: Prints all subscribers # onboarded: Prints only onboarded subscribers subscriber_list() { - local filt case $1 in - all) filt='[*]';; + all) yq '.subscribers[] | .name' $SUBSCRIBERS_FILE;; # TODO: Right now subscribers are only "manual". - onboarded) filt='(conventions.**.status==manual)';; + onboarded) yq '.subscribers[] | select(.conventions[].status == "manual") | .name' $SUBSCRIBERS_FILE;; esac - yq r $SUBSCRIBERS_FILE "subscribers${filt}.name" } ## last_bp_commit ORG/PROJ diff --git a/boilerplate/openshift/golang-osd-operator/.codecov.yml b/boilerplate/openshift/golang-osd-operator/.codecov.yml index 844b447..ba05647 100644 --- a/boilerplate/openshift/golang-osd-operator/.codecov.yml +++ b/boilerplate/openshift/golang-osd-operator/.codecov.yml @@ -24,3 +24,7 @@ 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 new file mode 100644 index 0000000..b120008 --- /dev/null +++ b/boilerplate/openshift/golang-osd-operator/Dockerfile.olm-registry @@ -0,0 +1,22 @@ +FROM registry.redhat.io/openshift4/ose-operator-registry:v4.12 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"] diff --git a/boilerplate/openshift/golang-osd-operator/OWNERS_ALIASES b/boilerplate/openshift/golang-osd-operator/OWNERS_ALIASES new file mode 100644 index 0000000..ecc0d0a --- /dev/null +++ b/boilerplate/openshift/golang-osd-operator/OWNERS_ALIASES @@ -0,0 +1,82 @@ +# ================================ 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 + - bdematte + - boranx + - dakotalongRH + - lnguyen1401 + - luis-falcon + - rafael-azevedo + srep-functional-team-fedramp: + - tonytheleg + - theautoroboto + - rhdedgar + - katherinelc321 + - robotmaxtron + - rojasreinold + srep-functional-team-hulk: + - a7vicky + - rendhalver + - ravitri + - shitaljante + - weherdh + - devppratik + srep-functional-team-orange: + - bng0y + - typeid + - Makdaam + - Nikokolas3270 + - ninabauer + - RaphaelBut + - Tessg22 + srep-functional-team-rocket: + - aliceh + - anispate + - bdmiller3 + - clcollins + - mjlshen + - tnierman + - yithian + srep-functional-team-security: + - gsleeman + - jaybeeunix + - sam-nguyen7 + - wshearn + srep-functional-team-thor: + - bmeng + - MitaliBhalla + - hectorakemp + - feichashao + - Tafhim + - samanthajayasinghe + srep-functional-team-v1alpha1: + - iamkirkbater + - AlexVulaj + - T0MASD + - bergmannf + - dkeohane + - reedcort + - mrWinston + srep-functional-leads: + - rafael-azevedo + - iamkirkbater + - bng0y + - tonytheleg + - bmeng + - mjlshen + - sam-nguyen7 + - ravitri + srep-team-leads: + - NautiluX + - rogbas + - fahlmant + - dustman9000 + - wanghaoran1988 + srep-architects: + - jewzaam + - jharrington22 + - cblecker diff --git a/boilerplate/openshift/golang-osd-operator/README.md b/boilerplate/openshift/golang-osd-operator/README.md index 4b41791..690eb03 100644 --- a/boilerplate/openshift/golang-osd-operator/README.md +++ b/boilerplate/openshift/golang-osd-operator/README.md @@ -8,12 +8,16 @@ - [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": @@ -28,7 +32,7 @@ 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. | @@ -48,18 +52,26 @@ $ 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} ``` @@ -72,8 +84,9 @@ 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). + 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 @@ -94,15 +107,17 @@ The convention embeds default checks to ensure generated code generation is curr 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. + +- 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 + +- 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` +- `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) @@ -112,6 +127,7 @@ 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 @@ -123,3 +139,29 @@ include boilerplate/generated-includes.mk `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/build-opm-catalog.sh b/boilerplate/openshift/golang-osd-operator/build-opm-catalog.sh index 196d07a..3bb8328 100755 --- a/boilerplate/openshift/golang-osd-operator/build-opm-catalog.sh +++ b/boilerplate/openshift/golang-osd-operator/build-opm-catalog.sh @@ -309,7 +309,7 @@ function main() { 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") + image_builder=$(basename "$CONTAINER_ENGINE" | awk '{print $1}') check_opm_supported_container_engine "$image_builder" || return 1 diff --git a/boilerplate/openshift/golang-osd-operator/configure-fips.sh b/boilerplate/openshift/golang-osd-operator/configure-fips.sh index e506a00..d009255 100755 --- a/boilerplate/openshift/golang-osd-operator/configure-fips.sh +++ b/boilerplate/openshift/golang-osd-operator/configure-fips.sh @@ -15,4 +15,4 @@ fi echo "Writing fips file at $MAIN_DIR/fips.go" -cp $CONVENTION_DIR/fips.go.tmplt "$MAIN_DIR/fips.go" \ No newline at end of file +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 index b4ca838..904ef76 100755 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/catalog-build.sh +++ b/boilerplate/openshift/golang-osd-operator/csv-generate/catalog-build.sh @@ -36,7 +36,7 @@ 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="Dockerfile.olm-registry" +DOCKERFILE_REGISTRY="build/Dockerfile.olm-registry" # Checking SAAS_OPERATOR_DIR exist if [ ! -d "${SAAS_OPERATOR_DIR}/.git" ] ; then @@ -61,31 +61,7 @@ channels: currentCSV: ${operator_name}.v${OPERATOR_NEW_VERSION} EOF -# Build registry -cat < $DOCKERFILE_REGISTRY -FROM quay.io/openshift/origin-operator-registry:4.10.0 AS builder -COPY $SAAS_OPERATOR_DIR manifests -RUN initializer --permissive - -FROM registry.access.redhat.com/ubi8/ubi-micro:8.5-836 - -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"] -EOF - -${CONTAINER_ENGINE} build --pull -f $DOCKERFILE_REGISTRY --tag "${registry_image}:${operator_channel}-latest" . +${CONTAINER_ENGINE} build --pull -f "${DOCKERFILE_REGISTRY}" --build-arg "SAAS_OPERATOR_DIR=${SAAS_OPERATOR_DIR}" --tag "${registry_image}:${operator_channel}-latest" . if [ $? -ne 0 ] ; then echo "docker build failed, exiting..." 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 index c8bcf13..e6b4a23 100755 --- 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 @@ -13,11 +13,8 @@ import datetime import os -import sys import yaml -import shutil import argparse -import string # 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 @@ -47,6 +44,8 @@ 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 @@ -54,6 +53,10 @@ 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 class UnsupportedRegistryResourceKind(Exception): def __init__(self, kind, path): @@ -70,11 +73,6 @@ class NoDeploymentFound(Exception): def __init__(self): super().__init__("At least one Deployment is required!") -class MultipleDeploymentsNotSupported(Exception): - def __init__(self, deployments): - super().__init__( - f"Multiple Deployments not supported! Found {len(deployments)}.") - class BindingsNotSupported(Exception): def __init__(self, bindings): super().__init__( @@ -88,6 +86,12 @@ def __init__(self, operator_name): 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__( @@ -230,17 +234,21 @@ def trim_index(index, kind, item): if 'Deployment' not in by_kind: raise NoDeploymentFound() -# TODO: Should we support additional Deployments that aren't the operator -# Deployment? +# We support no more than two deployments if len(by_kind['Deployment']) > 1: - raise MultipleDeploymentsNotSupported(by_kind['Deployment']) + 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( @@ -307,27 +315,31 @@ def trim_index(index, kind, item): csv['spec']['install']['spec']['permissions'].append( { 'rules': role['rules'], - 'serviceAccountName': role_binding['subjects'][0]['name'] + 'serviceAccountName': role_binding['subjects'][0]['name'] } ) trim_index(by_kind, 'Role', role) trim_index(by_kind, 'RoleBinding', role_binding) ## Add the Deployment -# We already made sure there's exactly one 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]['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 +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: - env.append(dict(name='OPERATOR_IMAGE', value=operator_image)) + # The container has no environment variables, so just set this one + env = dict(name='OPERATOR_IMAGE', value=operator_image) csv['spec']['install']['spec']['deployments'] = [ { @@ -335,6 +347,19 @@ def trim_index(index, kind, item): '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') @@ -359,7 +384,12 @@ def trim_index(index, kind, item): # Update the versions to include git hash: csv['metadata']['name'] = f"{OPERATOR_NAME}.v{full_version}" csv['spec']['version'] = full_version -if prev_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: diff --git a/boilerplate/openshift/golang-osd-operator/csv-generate/common.sh b/boilerplate/openshift/golang-osd-operator/csv-generate/common.sh index e8624be..2b44480 100644 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/common.sh +++ b/boilerplate/openshift/golang-osd-operator/csv-generate/common.sh @@ -18,3 +18,24 @@ function check_mandatory_params() { 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 index 21e9ea4..a08868f 100644 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.mk +++ b/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.mk @@ -1,6 +1,6 @@ .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) + @${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: @@ -22,11 +22,11 @@ staging-catalog-build-and-publish: .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) -g hack + @${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) + @${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: diff --git a/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.sh b/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.sh index 5e7a710..5966a8d 100755 --- a/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.sh +++ b/boilerplate/openshift/golang-osd-operator/csv-generate/csv-generate.sh @@ -4,10 +4,10 @@ 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" 1>&2; exit 1; } +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:" option; do +while getopts "c:dg:H:i:n:o:V:s:e:" option; do case "${option}" in c) operator_channel=${OPTARG} @@ -32,6 +32,12 @@ while getopts "c:dg:H:i:n:o:V:" option; do # Notably, it does *not* start with `v`. operator_version=${OPTARG} ;; + s) + supplementary_image=${OPTARG} + ;; + e) + skip_range_enabled=${OPTARG} + ;; *) usage esac @@ -48,16 +54,21 @@ fi if [[ -z "$CONTAINER_ENGINE" ]]; then YQ_CMD="yq" else - YQ_CMD="$CONTAINER_ENGINE run --rm -i quay.io/app-sre/yq:3.4.1 yq" + yq_image="quay.io/app-sre/yq:4" + $CONTAINER_ENGINE pull $yq_image + YQ_CMD="$CONTAINER_ENGINE run --rm -i $yq_image" fi -# Get the image URI as repo URL + image digest -IMAGE_DIGEST=$(skopeo inspect docker://${operator_image}:v${operator_version} | jq -r .Digest) -if [[ -z "$IMAGE_DIGEST" ]]; then - echo "Couldn't discover IMAGE_DIGEST for docker://${operator_image}:v${operator_version}!" - exit 1 +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 -REPO_DIGEST=${operator_image}@${IMAGE_DIGEST} # If no override, using the gitlab repo if [ -z "$GIT_PATH" ] ; then @@ -74,7 +85,7 @@ git clone --branch "$operator_channel" ${GIT_PATH} "$SAAS_OPERATOR_DIR" # 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 "${BUNDLE_DIR}" + mkdir -p "${BUNDLE_DIR}" fi # For testing purposes, support disabling anything that relies on @@ -97,10 +108,10 @@ if [[ -z "$SKIP_SAAS_FILE_CHECKS" ]]; then # 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 r - "managedResourceTypes[0]" + $YQ_CMD '.managedResourceTypes[0]' - ) if [[ "${MANAGED_RESOURCE_TYPE}" == "" ]]; then - echo "Unabled to determine if SAAS file managed resource type" + echo "Unable to determine if SAAS file managed resource type" exit 1 fi @@ -116,10 +127,8 @@ if [[ -z "$SKIP_SAAS_FILE_CHECKS" ]]; then # remove any versions more recent than deployed hash if [[ "$operator_channel" == "production" ]]; then if [ -z "$DEPLOYED_HASH" ] ; then - DEPLOYED_HASH=$( - curl -s "${SAAS_FILE_URL}" | \ - $YQ_CMD r - "resourceTemplates[*].targets(namespace.\$ref==${resource_template_ns_path}).ref" - ) + 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 @@ -161,6 +170,13 @@ OUTPUT_DIR=${BUNDLE_DIR} 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 @@ -168,12 +184,12 @@ fi # ...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} + ./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 --rm ${CE_OPTS} -u `id -u`:0 -w `pwd` registry.access.redhat.com/ubi8/python-36:1-134 /bin/bash -c "python -m pip install 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}" + $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 new file mode 100644 index 0000000..004cb06 --- /dev/null +++ b/boilerplate/openshift/golang-osd-operator/dependabot.yml @@ -0,0 +1,14 @@ +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 index a0a9757..fe4a7fd 100755 --- a/boilerplate/openshift/golang-osd-operator/ensure.sh +++ b/boilerplate/openshift/golang-osd-operator/ensure.sh @@ -6,7 +6,7 @@ REPO_ROOT=$(git rev-parse --show-toplevel) source $REPO_ROOT/boilerplate/_lib/common.sh GOLANGCI_LINT_VERSION="1.30.0" -OPM_VERSION="v1.15.2" +OPM_VERSION="v1.23.2" GRPCURL_VERSION="1.7.0" DEPENDENCY=${1:-} GOOS=$(go env GOOS) diff --git a/boilerplate/openshift/golang-osd-operator/fips.go.tmplt b/boilerplate/openshift/golang-osd-operator/fips.go.tmplt index bc0d454..d4b108e 100644 --- a/boilerplate/openshift/golang-osd-operator/fips.go.tmplt +++ b/boilerplate/openshift/golang-osd-operator/fips.go.tmplt @@ -1,3 +1,4 @@ +//go:build fips_enabled // +build fips_enabled // BOILERPLATE GENERATED -- DO NOT EDIT diff --git a/boilerplate/openshift/golang-osd-operator/golangci.yml b/boilerplate/openshift/golang-osd-operator/golangci.yml index 77ff645..4cd695e 100644 --- a/boilerplate/openshift/golang-osd-operator/golangci.yml +++ b/boilerplate/openshift/golang-osd-operator/golangci.yml @@ -16,13 +16,11 @@ issues: linters: disable-all: true enable: - - deadcode - errcheck + - gosec - gosimple - govet - ineffassign - staticcheck - - structcheck - typecheck - unused - - varcheck diff --git a/boilerplate/openshift/golang-osd-operator/project.mk b/boilerplate/openshift/golang-osd-operator/project.mk index 4dad5b2..e146a08 100644 --- a/boilerplate/openshift/golang-osd-operator/project.mk +++ b/boilerplate/openshift/golang-osd-operator/project.mk @@ -6,6 +6,13 @@ 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 diff --git a/boilerplate/openshift/golang-osd-operator/standard.mk b/boilerplate/openshift/golang-osd-operator/standard.mk index 6d6dd6f..56cc802 100644 --- a/boilerplate/openshift/golang-osd-operator/standard.mk +++ b/boilerplate/openshift/golang-osd-operator/standard.mk @@ -26,6 +26,12 @@ CONTAINER_ENGINE_CONFIG_DIR = .docker # also accepts REGISTRY_AUTH_FILE from the env. See # https://www.mankier.com/1/podman-login#Options---authfile=path 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)) +$(shell echo '{}' > $(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 @@ -46,9 +52,22 @@ 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 -#The api dir that latest osdk generated -NEW_API_DIR=./api -USE_OLD_SDK=$(shell if [[ -d "$(NEW_API_DIR)" ]];then echo FALSE;else echo TRUE;fi) + +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 @@ -69,16 +88,9 @@ OLM_CHANNEL ?= alpha REGISTRY_USER ?= REGISTRY_TOKEN ?= -BINFILE=build/_output/bin/$(OPERATOR_NAME) -MAINPACKAGE = ./main.go -API_DIR = $(NEW_API_DIR) -ifeq ($(USE_OLD_SDK), TRUE) -MAINPACKAGE = ./cmd/manager -API_DIR = ./pkg/apis -endif - 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 @@ -92,15 +104,17 @@ 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 -GOENV=GOOS=${GOOS} GOARCH=${GOARCH} CGO_ENABLED=0 GOFLAGS="${GOFLAGS_MOD}" - -GOBUILDFLAGS=-gcflags="all=-trimpath=${GOPATH}" -asmflags="all=-trimpath=${GOPATH}" - # 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 @@ -108,7 +122,7 @@ GOLANGCI_LINT_CACHE ?= /tmp/golangci-cache GOLANGCI_OPTIONAL_CONFIG ?= ifeq ($(origin TESTTARGETS), undefined) -TESTTARGETS := $(shell ${GOENV} go list -e ./... | egrep -v "/(vendor)/") +TESTTARGETS := $(shell ${GOENV} go list -e ./... | egrep -v "/(vendor)/" | egrep -v "/(osde2e)/") endif # ex, -v TESTOPTS := @@ -117,10 +131,11 @@ 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 uunsetting it makes the next defined target the default: +# 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 @@ -132,7 +147,7 @@ clean: .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." >&2 && git --no-pager diff && exit 1) + @(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 @@ -189,35 +204,20 @@ rm -rf $$TMP_DIR ;\ } endef -# Deciding on the binary versions -CONTROLLER_GEN_VERSION = v0.8.0 -CONTROLLER_GEN = controller-gen-$(CONTROLLER_GEN_VERSION) - -OPENAPI_GEN_VERSION = v0.23.0 -OPENAPI_GEN = openapi-gen-$(OPENAPI_GEN_VERSION) - -ifeq ($(USE_OLD_SDK), TRUE) -#If we are using the old osdk, we use the default controller-gen and openapi-gen versions. -# Default version is 0.3.0 for now. CONTROLLER_GEN = controller-gen -# Default version is 0.19.4 for now. OPENAPI_GEN = openapi-gen -endif +KUSTOMIZE = kustomize +YQ = yq .PHONY: op-generate ## CRD v1beta1 is no longer supported. op-generate: - cd $(API_DIR); $(CONTROLLER_GEN) crd:crdVersions=v1 paths=./... output:dir=$(PWD)/deploy/crds - cd $(API_DIR); $(CONTROLLER_GEN) object paths=./... - -API_DIR_MIN_DEPTH = 1 -ifeq ($(USE_OLD_SDK), TRUE) -API_DIR_MIN_DEPTH = 2 -endif + 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_DIR) -maxdepth 2 -mindepth $(API_DIR_MIN_DEPTH) -type d | xargs -t -I% \ + find ./api -maxdepth 2 -mindepth 1 -type d | xargs -t -I% \ $(OPENAPI_GEN) --logtostderr=true \ -i % \ -o "" \ @@ -225,9 +225,19 @@ openapi-generate: -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 +generate: op-generate go-generate openapi-generate manifests ifeq (${FIPS_ENABLED}, true) go-build: ensure-fips @@ -237,7 +247,7 @@ endif 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 ${BINFILE} ${MAINPACKAGE} + ${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 @@ -246,7 +256,7 @@ 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. @@ -332,3 +342,41 @@ opm-build-push: docker-push .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 diff --git a/boilerplate/openshift/golang-osd-operator/update b/boilerplate/openshift/golang-osd-operator/update index bed4cc8..f64a6f2 100755 --- a/boilerplate/openshift/golang-osd-operator/update +++ b/boilerplate/openshift/golang-osd-operator/update @@ -10,14 +10,46 @@ source $CONVENTION_ROOT/_lib/common.sh # 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 -# TODO: boilerplate more of Dockerfile -DOCKERFILE=build/Dockerfile -echo "Overwriting $DOCKERFILE's initial FROM with $IMAGE_PULL_PATH" -${SED?} -i "1s,.*,FROM $IMAGE_PULL_PATH AS builder," $DOCKERFILE +# 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" diff --git a/build/Dockerfile b/build/Dockerfile index d4a48e9..9817de4 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/app-sre/boilerplate:image-v2.3.2 AS builder +FROM quay.io/app-sre/boilerplate:image-v4.0.2 AS builder RUN mkdir -p /workdir WORKDIR /workdir @@ -7,7 +7,7 @@ RUN go mod download COPY . . RUN make go-build -FROM registry.access.redhat.com/ubi8/ubi-minimal:latest +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.9-1029 ENV USER_UID=1001 \ USER_NAME=aws-efs-operator diff --git a/build/Dockerfile.olm-registry b/build/Dockerfile.olm-registry new file mode 100644 index 0000000..8ee1642 --- /dev/null +++ b/build/Dockerfile.olm-registry @@ -0,0 +1,22 @@ +FROM registry.redhat.io/openshift4/ose-operator-registry:v4.12 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:8.9-1029 + +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"]