From 3898a150269f264ba1728e0cffc9100f98ab1413 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Fri, 3 Mar 2023 19:40:40 -0500 Subject: [PATCH 1/3] Introduce Taskfile to describe developer and CI tasks Signed-off-by: Joe Lanford --- .github/workflows/e2e.yaml | 32 ----- .github/workflows/release.yaml | 17 ++- .github/workflows/test.yaml | 37 ++++++ .github/workflows/unit-test.yaml | 32 ----- .gitignore | 19 +-- .goreleaser.yml | 7 +- .taskfile.build.yaml | 111 ++++++++++++++++++ .taskfile.deploy.yaml | 26 ++++ .taskfile.kind.yaml | 32 +++++ .taskfile.style.yaml | 16 +++ .taskfile.test.yaml | 80 +++++++++++++ .taskfile.tools.yaml | 41 +++++++ Taskfile.dist.yaml | 66 +++++++++++ bin/.dockerignore | 8 -- ...rators.operatorframework.io_operators.yaml | 2 +- 15 files changed, 431 insertions(+), 95 deletions(-) delete mode 100644 .github/workflows/e2e.yaml create mode 100644 .github/workflows/test.yaml delete mode 100644 .github/workflows/unit-test.yaml create mode 100644 .taskfile.build.yaml create mode 100644 .taskfile.deploy.yaml create mode 100644 .taskfile.kind.yaml create mode 100644 .taskfile.style.yaml create mode 100644 .taskfile.test.yaml create mode 100644 .taskfile.tools.yaml create mode 100644 Taskfile.dist.yaml delete mode 100644 bin/.dockerignore diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml deleted file mode 100644 index 59bb1ad01d..0000000000 --- a/.github/workflows/e2e.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: e2e - -on: - workflow_dispatch: - pull_request: - push: - branches: - - main - -jobs: - e2e-kind: - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v3 - - - uses: actions/setup-go@v3 - with: - go-version-file: go.mod - - - uses: actions/cache@v3 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Run e2e tests - run: | - make e2e diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3c4994574e..ab90fbd96c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -26,6 +26,15 @@ jobs: with: go-version-file: "go.mod" + - uses: actions/cache@v3 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Docker Login if: ${{ github.event_name != 'pull_request' }} uses: docker/login-action@v1 @@ -52,12 +61,10 @@ jobs: echo IMAGE_TAG="$(git describe --tags --always)" >> $GITHUB_ENV fi - - name: Generate the operator-controller release manifests - if: ${{ startsWith(github.ref, 'refs/tags/v') }} - run: | - make quickstart VERSION=${GITHUB_REF#refs/tags/} + - name: Install Task + run: go install github.com/go-task/task/v3/cmd/task@latest - name: Run goreleaser - run: make release + run: task release env: GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000000..81127b01dd --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,37 @@ +name: test + +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + test: [ sanity, unit, e2e ] + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-go@v3 + with: + go-version-file: go.mod + + - uses: actions/cache@v3 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Install Task + run: go install github.com/go-task/task/v3/cmd/task@latest + + - name: Run ${{matrix.test}} test + run: | + task test:${{matrix.test}} \ No newline at end of file diff --git a/.github/workflows/unit-test.yaml b/.github/workflows/unit-test.yaml deleted file mode 100644 index 6c3f99fbf5..0000000000 --- a/.github/workflows/unit-test.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: unit-test - -on: - workflow_dispatch: - pull_request: - push: - branches: - - main - -jobs: - unit-test-basic: - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v3 - - - uses: actions/setup-go@v3 - with: - go-version-file: go.mod - - - uses: actions/cache@v3 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Run basic unit tests - run: | - make test-unit diff --git a/.gitignore b/.gitignore index e48b818351..07ff619660 100644 --- a/.gitignore +++ b/.gitignore @@ -6,30 +6,21 @@ vendor *.dll *.so *.dylib -bin/* -testbin/* -Dockerfile.cross +**/bin/* # Test binary, build with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE -*.out +cover.out # Release output -dist/** -operator-controller.yaml -install.sh - -# Kubernetes Generated files - skip generated files, except for vendored files - -!vendor/**/zz_generated.* +/dist/** +/install.sh +/operator-controller.yaml # editor and IDE paraphernalia .idea *.swp *.swo *~ - -# TODO dfranz remove this line and the bin folder when tools binaries are moved to their own folder -!bin/.dockerignore diff --git a/.goreleaser.yml b/.goreleaser.yml index 197c6cb844..30ebce7fa7 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -10,7 +10,7 @@ builds: - id: operator-controller main: ./ binary: bin/manager - tags: $GO_BUILD_TAGS + tags: upstream goos: - linux goarch: @@ -22,7 +22,7 @@ builds: - -X main.Version={{ .Version }} dockers: - image_templates: - - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" + - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" dockerfile: Dockerfile goos: linux goarch: amd64 @@ -58,11 +58,12 @@ changelog: release: disable: '{{ ne .Env.ENABLE_RELEASE_PIPELINE "true" }}' extra_files: + - glob: 'install.sh' - glob: 'operator-controller.yaml' - glob: 'install.sh' header: | ## Installation ```bash - curl -L -s https://github.com/operator-framework/operator-controller/releases/download/{{ .Tag }}/install.sh | bash -s + curl -sSL https://github.com/operator-framework/operator-controller/releases/download/{{ .Env.IMAGE_TAG }}/install.sh | bash -s ``` diff --git a/.taskfile.build.yaml b/.taskfile.build.yaml new file mode 100644 index 0000000000..c6327c1755 --- /dev/null +++ b/.taskfile.build.yaml @@ -0,0 +1,111 @@ +version: '3' + +includes: + tools: + taskfile: .taskfile.tools.yaml + internal: true + +vars: + BIN: "{{.ROOT_DIR}}/bin" + OPERATOR_CONTROLLER_MANIFEST: ./operator-controller.yaml + + OLMV0_VERSION: v0.24.0 + CERT_MANAGER_VERSION: v1.9.0 + RUKPAK_VERSION: v0.11.0 + +env: + IMAGE_REPO: quay.io/operator-framework/operator-controller + IMAGE_TAG: devel + +tasks: + generate: + desc: "Run code generation" + summary: | + This task runs go generate and controller-gen to generate code, CRDs, + webhook configurations, and RBAC manifests. + cmds: + - go generate ./... + - "{{.TOOLSBIN}}/controller-gen object:headerFile=hack/boilerplate.go.txt paths=./..." + - "{{.TOOLSBIN}}/controller-gen rbac:roleName=manager-role crd webhook paths=./... output:crd:artifacts:config=config/crd/bases" + deps: [tools:controller-gen] + + binary: + desc: "Build the binaries for the current OS" + summary: | + This task uses goreleaser to build the operator binary based on GOOS and GOARCH. + By default, the binary is created at ./bin/manager. + + To generate the binary for a different OS, set the GOOS task variable accordingly. + cmds: + - mkdir -p {{.BIN}} + - GOOS={{.GOOS}} {{.TOOLSBIN}}/goreleaser build --single-target --snapshot --clean --output {{.BIN}}/manager + deps: [tools:goreleaser, generate] + + docker: + desc: "Build the docker image" + summary: | + This task builds the operator's linux binary in {{.BIN}}/linux and then uses + the Dockerfile to build the docker image in {{.BIN}}/linux. + + GOARCH is taken from the environment to ensure a binary that will run on the local + machine. GOOS is always set to `linux` for the docker build. + + By default, the image is tagged as quay.io/operator-framework/operator-controller:devel. + You can control the image repo and tag by setting the IMAGE_REPO and IMAGE_TAG + environment variables. + cmds: + - docker build -f Dockerfile -t $IMAGE_REPO:$IMAGE_TAG bin/linux + deps: + - task: binary + vars: + BIN: "{{.ROOT_DIR}}/bin/linux" + GOOS: linux + + manifest: + desc: "Generate the operator manifest" + summary: | + This task uses kustomize to generate the operator manifest. + + The operator manifest is generated by combining the CRD and default manifests + with the controller image set to the IMAGE_REPO and IMAGE_TAG environment variables. + cmds: + - cd config/manager && {{.TOOLSBIN}}/kustomize edit set image controller=$IMAGE_REPO:$IMAGE_TAG + - "{{.TOOLSBIN}}/kustomize build config/default > ./operator-controller.yaml" + deps: [tools:kustomize, generate] + + install-script: + desc: "Generate the install script" + summary: | + This task generates the install script that can be used to install the operator. + + The OPERATOR_CONTROLLER_MANIFEST task variable is used to set the location that + will be used to `kubectl apply -f` the operator-controller manifest. By default, + this is set to `./operator-controller.yaml`. However this can be overridden during + a release to reference the release manifest URL that is uploaded to GitHub during + the release. + silent: true + cmds: + - | + cat << EOF > ./install.sh + #!/usr/bin/env bash + set -o pipefail -o errexit -o nounset + + # Install OLMv0 + curl -L -s https://github.com/operator-framework/operator-lifecycle-manager/releases/download/{{.OLMV0_VERSION}}/install.sh | bash -s {{.OLMV0_VERSION}} + + # Install cert-manager + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/{{.CERT_MANAGER_VERSION}}/cert-manager.yaml + kubectl wait --for=condition=Available --namespace=cert-manager deployment/cert-manager-webhook --timeout=60s + + # Install rukpak + kubectl apply -f https://github.com/operator-framework/rukpak/releases/download/{{.RUKPAK_VERSION}}/rukpak.yaml + kubectl wait --for=condition=Available --namespace=rukpak-system deployment/core --timeout=60s + kubectl wait --for=condition=Available --namespace=rukpak-system deployment/helm-provisioner --timeout=60s + kubectl wait --for=condition=Available --namespace=rukpak-system deployment/rukpak-webhooks --timeout=60s + kubectl wait --for=condition=Available --namespace=crdvalidator-system deployment/crd-validation-webhook --timeout=60s + + # Install operator-controller + kubectl apply -f {{.OPERATOR_CONTROLLER_MANIFEST}} + kubectl wait --for=condition=Available --namespace=operator-controller-system deployment/operator-controller-controller-manager --timeout=60s + EOF + - chmod +x ./install.sh diff --git a/.taskfile.deploy.yaml b/.taskfile.deploy.yaml new file mode 100644 index 0000000000..c9473c12f1 --- /dev/null +++ b/.taskfile.deploy.yaml @@ -0,0 +1,26 @@ +version: '3' + +includes: + build: + taskfile: .taskfile.build.yaml + internal: true + kind: + taskfile: .taskfile.kind.yaml + internal: true + +tasks: + kind: + cmds: + - task: kind:load-image + vars: + IMAGE: "$IMAGE_REPO:$IMAGE_TAG" + KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}" + - ./install.sh + deps: + - task: build:docker + - task: build:manifest + - task: build:install-script + - task: kind:create + vars: + KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}" + desc: "Run the operator in a fresh kind cluster" diff --git a/.taskfile.kind.yaml b/.taskfile.kind.yaml new file mode 100644 index 0000000000..8489b5642e --- /dev/null +++ b/.taskfile.kind.yaml @@ -0,0 +1,32 @@ +version: '3' + +vars: + KIND_CLUSTER_NAME: "operator-controller" + +includes: + tools: + taskfile: .taskfile.tools.yaml + internal: true + +tasks: + create: + desc: "Create a fresh kind cluster" + cmds: + - "{{.TOOLSBIN}}/kind create cluster --name {{.KIND_CLUSTER_NAME}}" + deps: + - tools:kind + - task: delete + vars: + KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}" + + delete: + desc: "Delete a kind cluster" + cmds: + - "{{.TOOLSBIN}}/kind delete cluster --name {{.KIND_CLUSTER_NAME}}" + deps: [tools:kind] + + load-image: + desc: "Load the image into the kind cluster" + cmds: + - "{{.TOOLSBIN}}/kind load docker-image {{.IMAGE}} --name {{.KIND_CLUSTER_NAME}}" + deps: [tools:kind] diff --git a/.taskfile.style.yaml b/.taskfile.style.yaml new file mode 100644 index 0000000000..c40c4140da --- /dev/null +++ b/.taskfile.style.yaml @@ -0,0 +1,16 @@ +version: '3' + +tasks: + default: + deps: [ fmt, vet, tidy ] + + fmt: + cmds: + - go fmt ./... + vet: + cmds: + - go vet ./... + tidy: + cmds: + - go mod tidy + diff --git a/.taskfile.test.yaml b/.taskfile.test.yaml new file mode 100644 index 0000000000..127856db7f --- /dev/null +++ b/.taskfile.test.yaml @@ -0,0 +1,80 @@ +version: '3' + + +includes: + tools: + taskfile: .taskfile.tools.yaml + internal: true + + style: + taskfile: .taskfile.style.yaml + internal: true + + build: + taskfile: .taskfile.build.yaml + internal: true + + kind: + taskfile: .taskfile.kind.yaml + internal: true + + deploy: + taskfile: .taskfile.deploy.yaml + internal: true + +vars: + ENVTEST_VERSION: + sh: go list -m -f {{ "{{.Version}}" }} k8s.io/client-go | sed 's/^v0\.\([[:digit:]]\{1,\}\)\.[[:digit:]]\{1,\}$/1.\1.x/' + + PKGS: + sh: go list ./... | grep -v 'test/e2e$' | cut -d/ -f4 | uniq | sed '/^$/d' | sed 's|.*|./&/...|' | tr '\n' ' ' + +tasks: + default: + desc: "Run all tests" + cmds: + - task: sanity + - task: unit + - task: e2e + + unit: + desc: "Run unit tests" + summary: | + Run unit tests. + + The FOCUS variable can be used to filter tests by name. + The PKGS variable can be used to filter tests by package. + cmds: + - eval $({{.TOOLSBIN}}/setup-envtest use -p env {{.ENVTEST_VERSION}}) && {{.TOOLSBIN}}/ginkgo --tags {{.GO_BUILD_TAGS}} {{with .FOCUS}}-focus "{{.}}"{{end}} -coverprofile cover.out {{.PKGS}} + deps: [tools:setup-envtest, tools:ginkgo] + + e2e: + desc: "Run e2e tests" + summary: | + Run e2e tests. + + The FOCUS variable can be used to filter tests by name. + cmds: + - defer: + task: kind:delete + vars: + KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}-e2e" + - "{{.TOOLSBIN}}/ginkgo --tags {{.GO_BUILD_TAGS}} -progress -trace {{with .FOCUS}}-focus '{{.}}'{{end}} ./test/e2e" + deps: + - tools:ginkgo + - task: deploy:kind + vars: + KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}-e2e" + + sanity: + desc: "Run sanity checks" + summary: | + Run sanity checks. + + These checks include running formatters and code generation to ensure the + repository is in a clean, consistent state. + + They also include running the linters and static analysis tools. + cmds: + - git diff --exit-code + deps: [ style, build:generate ] diff --git a/.taskfile.tools.yaml b/.taskfile.tools.yaml new file mode 100644 index 0000000000..28e65f6adb --- /dev/null +++ b/.taskfile.tools.yaml @@ -0,0 +1,41 @@ +version: '3' + +vars: + CONTROLLER_GEN_VERSION: v0.11.3 + GINKGO_VERSION: + sh: go list -m -f {{ "{{.Version}}" }} github.com/onsi/ginkgo/v2 + GORELEASER_VERSION: main + KIND_VERSION: v0.17.0 + KUSTOMIZE_VERSION: v4.5.7 + SETUP_ENVTEST_VERSION: latest + +tasks: + controller-gen: + desc: "Install controller-gen" + cmds: + - GOBIN={{.TOOLSBIN}} go install sigs.k8s.io/controller-tools/cmd/controller-gen@{{.CONTROLLER_GEN_VERSION}} + + ginkgo: + desc: "Install ginkgo" + cmds: + - GOBIN={{.TOOLSBIN}} go install github.com/onsi/ginkgo/v2/ginkgo@{{.GINKGO_VERSION}} + + goreleaser: + desc: "Install goreleaser" + cmds: + - GOBIN={{.TOOLSBIN}} go install github.com/goreleaser/goreleaser@{{.GORELEASER_VERSION}} + + kind: + desc: "Install kind" + cmds: + - GOBIN={{.TOOLSBIN}} go install sigs.k8s.io/kind@{{.KIND_VERSION}} + + kustomize: + desc: "Install kustomize" + cmds: + - GOBIN={{.TOOLSBIN}} go install sigs.k8s.io/kustomize/kustomize/v4@{{.KUSTOMIZE_VERSION}} + + setup-envtest: + desc: "Install envtest" + cmds: + - GOBIN={{.TOOLSBIN}} go install sigs.k8s.io/controller-runtime/tools/setup-envtest@{{.SETUP_ENVTEST_VERSION}} diff --git a/Taskfile.dist.yaml b/Taskfile.dist.yaml new file mode 100644 index 0000000000..3345cabfba --- /dev/null +++ b/Taskfile.dist.yaml @@ -0,0 +1,66 @@ +version: '3' + +vars: + TOOLSBIN: "{{.ROOT_DIR}}/hack/tools/bin" + GO_BUILD_TAGS: upstream + +env: + IMAGE_REPO: quay.io/operator-framework/operator-controller + IMAGE_TAG: devel + + GORELEASER_ARGS: --snapshot --clean + ENABLE_RELEASE_PIPELINE: false + +includes: + tools: + taskfile: .taskfile.tools.yaml + internal: true + + build: + taskfile: .taskfile.build.yaml + + test: + taskfile: .taskfile.test.yaml + + deploy: + taskfile: .taskfile.deploy.yaml + internal: true + +run: when_changed + +tasks: + default: + cmds: + - task: build:binary + + run: + desc: "Run the operator locally in a kind cluster" + summary: | + This task will run the operator in a kind cluster. + + The KIND_CLUSTER_NAME task variable is used to control the name of the + kind cluster. By default, this is set to "operator-controller". + cmds: + - task: deploy:kind + vars: + KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}" + + release: + desc: "Release the operator (by default only local release steps are executed)" + summary: | + This task will run the release pipeline. + + The GORELEASER_ARGS environment variable is used as the arguments for the + `goreleaser release` command. The default arguments are `--snapshot --clean`. + + The ENABLE_RELEASE_PIPELINE environment variable is used to control the + GitHub changelog and release pipeline steps. By default, this is set to false. + This should only be set to true when running the release task for a tagged + release. + cmds: + - task: build:manifest + - task: build:install-script + vars: + OPERATOR_CONTROLLER_MANIFEST: https://github.com/operator-framework/operator-controller/releases/download/$IMAGE_TAG/operator-controller.yaml + - "{{.TOOLSBIN}}/goreleaser release $GORELEASER_ARGS" + deps: [tools:goreleaser] diff --git a/bin/.dockerignore b/bin/.dockerignore deleted file mode 100644 index 97e40c0e3b..0000000000 --- a/bin/.dockerignore +++ /dev/null @@ -1,8 +0,0 @@ -# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file -# Ignore tools binaries -# TODO dfranz: We don't need this file anymore once we move the tool binaries out. -controller-gen -ginkgo -goreleaser -kind -kustomize diff --git a/config/crd/bases/operators.operatorframework.io_operators.yaml b/config/crd/bases/operators.operatorframework.io_operators.yaml index 894b7699c0..0a5185c2da 100644 --- a/config/crd/bases/operators.operatorframework.io_operators.yaml +++ b/config/crd/bases/operators.operatorframework.io_operators.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.10.0 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: operators.operators.operatorframework.io spec: From 29acbfff81a48916843422f2c008e4a55fa820ab Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Thu, 9 Mar 2023 12:49:23 -0500 Subject: [PATCH 2/3] instrument coverage collection during e2e test; other minor tweaks Signed-off-by: Joe Lanford --- .github/workflows/test.yaml | 16 ++++++- .gitignore | 4 +- .goreleaser.yml | 10 +++- .taskfile.build.yaml | 13 ++++- .taskfile.deploy.yaml | 10 +++- .taskfile.kind.yaml | 2 +- .taskfile.test.yaml | 50 +++++++++++++++++--- .taskfile.tools.yaml | 2 +- Taskfile.dist.yaml | 3 ++ config/default/manager_auth_proxy_patch.yaml | 16 ------- config/e2e/kustomization.yaml | 7 +++ config/e2e/manager_e2e_patch.yaml | 22 +++++++++ config/manager/manager.yaml | 45 +++++++----------- go.mod | 2 +- test/e2e/e2e_suite_test.go | 2 +- 15 files changed, 144 insertions(+), 60 deletions(-) create mode 100644 config/e2e/kustomization.yaml create mode 100644 config/e2e/manager_e2e_patch.yaml diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 81127b01dd..f1c7e39d20 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -34,4 +34,18 @@ jobs: - name: Run ${{matrix.test}} test run: | - task test:${{matrix.test}} \ No newline at end of file + task test:${{matrix.test}} + + - name: Convert coverage data to Codecov format + if: ${{matrix.test == 'unit' || matrix.test == 'e2e'}} + run: | + go tool covdata textfmt -i=coverage/${{matrix.test}} -o=coverage/${{matrix.test}}.out + + - name: Upload coverage data to Codecov + if: ${{matrix.test == 'unit' || matrix.test == 'e2e'}} + uses: codecov/codecov-action@v3 + with: + file: coverage/${{matrix.test}}.out + flags: ${{matrix.test}} + fail_ci_if_error: true + diff --git a/.gitignore b/.gitignore index 07ff619660..932c5cd1f6 100644 --- a/.gitignore +++ b/.gitignore @@ -12,12 +12,12 @@ vendor *.test # Output of the go coverage tool, specifically when used with LiteIDE -cover.out +/coverage # Release output /dist/** /install.sh -/operator-controller.yaml +/operator-controller*.yaml # editor and IDE paraphernalia .idea diff --git a/.goreleaser.yml b/.goreleaser.yml index 30ebce7fa7..f88ea4fdc7 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -10,7 +10,8 @@ builds: - id: operator-controller main: ./ binary: bin/manager - tags: upstream + tags: + - "{{ .Env.GO_BUILD_TAGS }}" goos: - linux goarch: @@ -18,6 +19,13 @@ builds: - arm64 - ppc64le - s390x + flags: + - -cover={{ .Env.GO_COVER }} + mod_timestamp: "{{ .CommitTimestamp }}" + asmflags: + - all=-trimpath={{ dir .Env.PWD }} + gcflags: + - all=-trimpath={{ dir .Env.PWD }} ldflags: - -X main.Version={{ .Version }} dockers: diff --git a/.taskfile.build.yaml b/.taskfile.build.yaml index c6327c1755..3b07b0c2a0 100644 --- a/.taskfile.build.yaml +++ b/.taskfile.build.yaml @@ -7,6 +7,7 @@ includes: vars: BIN: "{{.ROOT_DIR}}/bin" + KUSTOMIZE_DIR: "config/default" OPERATOR_CONTROLLER_MANIFEST: ./operator-controller.yaml OLMV0_VERSION: v0.24.0 @@ -36,9 +37,16 @@ tasks: By default, the binary is created at ./bin/manager. To generate the binary for a different OS, set the GOOS task variable accordingly. + + The GO_COVER task variable instruments the operator with coverage enabled when set to "true" + or disabled when set to "false". The default is "false". + env: + GOOS: "{{.GOOS}}" + GO_COVER: '{{.GO_COVER | default "false" }}' + GO_BUILD_TAGS: "{{.GO_BUILD_TAGS}}" cmds: - mkdir -p {{.BIN}} - - GOOS={{.GOOS}} {{.TOOLSBIN}}/goreleaser build --single-target --snapshot --clean --output {{.BIN}}/manager + - "{{.TOOLSBIN}}/goreleaser build --debug --single-target --snapshot --clean --output {{.BIN}}/manager" deps: [tools:goreleaser, generate] docker: @@ -60,6 +68,7 @@ tasks: vars: BIN: "{{.ROOT_DIR}}/bin/linux" GOOS: linux + GO_COVER: "{{.GO_COVER}}" manifest: desc: "Generate the operator manifest" @@ -70,7 +79,7 @@ tasks: with the controller image set to the IMAGE_REPO and IMAGE_TAG environment variables. cmds: - cd config/manager && {{.TOOLSBIN}}/kustomize edit set image controller=$IMAGE_REPO:$IMAGE_TAG - - "{{.TOOLSBIN}}/kustomize build config/default > ./operator-controller.yaml" + - "{{.TOOLSBIN}}/kustomize build {{.KUSTOMIZE_DIR}} > {{.OPERATOR_CONTROLLER_MANIFEST}}" deps: [tools:kustomize, generate] install-script: diff --git a/.taskfile.deploy.yaml b/.taskfile.deploy.yaml index c9473c12f1..265233f552 100644 --- a/.taskfile.deploy.yaml +++ b/.taskfile.deploy.yaml @@ -18,9 +18,17 @@ tasks: - ./install.sh deps: - task: build:docker + vars: + GO_COVER: "{{.GO_COVER}}" + GO_BUILD_TAGS: "{{.GO_BUILD_TAGS}}" - task: build:manifest + vars: + KUSTOMIZE_DIR: "{{.KUSTOMIZE_DIR}}" + OPERATOR_CONTROLLER_MANIFEST: "{{.OPERATOR_CONTROLLER_MANIFEST}}" - task: build:install-script + vars: + OPERATOR_CONTROLLER_MANIFEST: "{{.OPERATOR_CONTROLLER_MANIFEST}}" - task: kind:create vars: KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}" - desc: "Run the operator in a fresh kind cluster" + KIND_EXTRA_FLAGS: "{{.KIND_EXTRA_FLAGS}}" diff --git a/.taskfile.kind.yaml b/.taskfile.kind.yaml index 8489b5642e..4b22d962f6 100644 --- a/.taskfile.kind.yaml +++ b/.taskfile.kind.yaml @@ -12,7 +12,7 @@ tasks: create: desc: "Create a fresh kind cluster" cmds: - - "{{.TOOLSBIN}}/kind create cluster --name {{.KIND_CLUSTER_NAME}}" + - "{{.TOOLSBIN}}/kind create cluster --name {{.KIND_CLUSTER_NAME}} {{.KIND_EXTRA_FLAGS}}" deps: - tools:kind - task: delete diff --git a/.taskfile.test.yaml b/.taskfile.test.yaml index 127856db7f..46a9293a94 100644 --- a/.taskfile.test.yaml +++ b/.taskfile.test.yaml @@ -44,8 +44,16 @@ tasks: The FOCUS variable can be used to filter tests by name. The PKGS variable can be used to filter tests by package. + vars: + GOCOVERDIR: "./coverage/unit" cmds: - - eval $({{.TOOLSBIN}}/setup-envtest use -p env {{.ENVTEST_VERSION}}) && {{.TOOLSBIN}}/ginkgo --tags {{.GO_BUILD_TAGS}} {{with .FOCUS}}-focus "{{.}}"{{end}} -coverprofile cover.out {{.PKGS}} + - rm -rf {{.GOCOVERDIR}} && mkdir -p {{.GOCOVERDIR}} && chmod 1777 {{.GOCOVERDIR}} + - defer: + task: rm-file + vars: + FILE: .ginkgo.coverprofile.out + - eval $({{.TOOLSBIN}}/setup-envtest use -p env {{.ENVTEST_VERSION}}) && {{.TOOLSBIN}}/ginkgo --coverprofile=.ginkgo.coverprofile.out --tags {{.GO_BUILD_TAGS}} --progress --trace {{with .FOCUS}}--focus "{{.}}"{{end}} {{.PKGS}} -- -test.gocoverdir="{{.ROOT_DIR}}/{{.GOCOVERDIR}}" + - go tool covdata percent -i={{.GOCOVERDIR}} deps: [tools:setup-envtest, tools:ginkgo] e2e: @@ -54,17 +62,41 @@ tasks: Run e2e tests. The FOCUS variable can be used to filter tests by name. + vars: + GOCOVERDIR: "./coverage/e2e" cmds: + - rm -rf {{.GOCOVERDIR}} && mkdir -p {{.GOCOVERDIR}} && chmod 1777 {{.GOCOVERDIR}} + - | + cat << EOF > ./kind-e2e.yaml + kind: Cluster + apiVersion: kind.x-k8s.io/v1alpha4 + nodes: + - role: control-plane + extraMounts: + - hostPath: {{.GOCOVERDIR}} + containerPath: /tmp/coverdata + EOF - defer: - task: kind:delete + task: rm-file vars: - KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}-e2e" - - "{{.TOOLSBIN}}/ginkgo --tags {{.GO_BUILD_TAGS}} -progress -trace {{with .FOCUS}}-focus '{{.}}'{{end}} ./test/e2e" - deps: - - tools:ginkgo + FILE: "./kind-e2e.yaml" - task: deploy:kind vars: + KUSTOMIZE_DIR: "config/e2e" + OPERATOR_CONTROLLER_MANIFEST: "operator-controller-e2e.yaml" KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}-e2e" + KIND_EXTRA_FLAGS: "--config ./kind-e2e.yaml" + GO_COVER: "true" + - defer: + task: kind:delete + vars: + KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}-e2e" + - "{{.TOOLSBIN}}/ginkgo --tags {{.GO_BUILD_TAGS}} --progress --trace {{with .FOCUS}}--focus '{{.}}'{{end}} ./test/e2e" + + # Delete the operator controller manager pod to write the coverage data to disk. + - kubectl delete --wait pod -n operator-controller-system -l control-plane=controller-manager + - go tool covdata percent -i={{.GOCOVERDIR}} + deps: [tools:ginkgo] sanity: desc: "Run sanity checks" @@ -78,3 +110,9 @@ tasks: cmds: - git diff --exit-code deps: [ style, build:generate ] + + rm-file: + cmds: + - rm -f {{.FILE}} + silent: true + internal: true diff --git a/.taskfile.tools.yaml b/.taskfile.tools.yaml index 28e65f6adb..17d77256e0 100644 --- a/.taskfile.tools.yaml +++ b/.taskfile.tools.yaml @@ -4,7 +4,7 @@ vars: CONTROLLER_GEN_VERSION: v0.11.3 GINKGO_VERSION: sh: go list -m -f {{ "{{.Version}}" }} github.com/onsi/ginkgo/v2 - GORELEASER_VERSION: main + GORELEASER_VERSION: v1.16.1 KIND_VERSION: v0.17.0 KUSTOMIZE_VERSION: v4.5.7 SETUP_ENVTEST_VERSION: latest diff --git a/Taskfile.dist.yaml b/Taskfile.dist.yaml index 3345cabfba..9a998879bc 100644 --- a/Taskfile.dist.yaml +++ b/Taskfile.dist.yaml @@ -57,6 +57,9 @@ tasks: GitHub changelog and release pipeline steps. By default, this is set to false. This should only be set to true when running the release task for a tagged release. + env: + GO_COVER: false + GO_BUILD_TAGS: "{{.GO_BUILD_TAGS}}" cmds: - task: build:manifest - task: build:install-script diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml index b751266167..352b2e3164 100644 --- a/config/default/manager_auth_proxy_patch.yaml +++ b/config/default/manager_auth_proxy_patch.yaml @@ -8,22 +8,6 @@ metadata: spec: template: spec: - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: kubernetes.io/arch - operator: In - values: - - amd64 - - arm64 - - ppc64le - - s390x - - key: kubernetes.io/os - operator: In - values: - - linux containers: - name: kube-rbac-proxy securityContext: diff --git a/config/e2e/kustomization.yaml b/config/e2e/kustomization.yaml new file mode 100644 index 0000000000..dc98d898ea --- /dev/null +++ b/config/e2e/kustomization.yaml @@ -0,0 +1,7 @@ +resources: +- ../default + +patchesStrategicMerge: + # Tweak the operator manifest to use configure volume mount and environment + # variables to facilitate coverage collection. + - manager_e2e_patch.yaml \ No newline at end of file diff --git a/config/e2e/manager_e2e_patch.yaml b/config/e2e/manager_e2e_patch.yaml new file mode 100644 index 0000000000..82c45184bf --- /dev/null +++ b/config/e2e/manager_e2e_patch.yaml @@ -0,0 +1,22 @@ +# This patch inject a sidecar container which is a HTTP proxy for the +# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + env: + - name: GOCOVERDIR + value: /tmp/coverdata + volumeMounts: + - mountPath: /tmp/coverdata + name: coverdata + volumes: + - name: coverdata + hostPath: + path: /tmp/coverdata diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 42a4350605..ee691a32b3 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -36,35 +36,26 @@ spec: labels: control-plane: controller-manager spec: - # TODO(user): Uncomment the following code to configure the nodeAffinity expression - # according to the platforms which are supported by your solution. - # It is considered best practice to support multiple architectures. You can - # build your manager image using the makefile target docker-buildx. - # affinity: - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: kubernetes.io/arch - # operator: In - # values: - # - amd64 - # - arm64 - # - ppc64le - # - s390x - # - key: kubernetes.io/os - # operator: In - # values: - # - linux + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - ppc64le + - s390x + - key: kubernetes.io/os + operator: In + values: + - linux securityContext: runAsNonRoot: true - # TODO(user): For common cases that do not require escalating privileges - # it is recommended to ensure that all your Pods/Containers are restrictive. - # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted - # Please uncomment the following code if your project does NOT have to work on old Kubernetes - # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). - # seccompProfile: - # type: RuntimeDefault + seccompProfile: + type: RuntimeDefault containers: - command: - /manager diff --git a/go.mod b/go.mod index b36c7b3850..507f5566fd 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/operator-framework/operator-controller -go 1.19 +go 1.20 require ( github.com/blang/semver/v4 v4.0.0 diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index a11e8671ac..6586eaeef0 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -6,6 +6,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/rest" @@ -14,7 +15,6 @@ import ( catsrcapi "github.com/operator-framework/api/pkg/operators/v1alpha1" operatorv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" - rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" ) var ( From 7c1b3b35da7e4e8d9ea7b5904dd4c66e9941a596 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Fri, 31 Mar 2023 22:48:31 -0400 Subject: [PATCH 3/3] determine project name from the root directory Signed-off-by: Joe Lanford --- .taskfile.build.yaml | 20 ++++++++++---------- .taskfile.deploy.yaml | 4 ++-- .taskfile.kind.yaml | 2 +- .taskfile.test.yaml | 6 +++--- Taskfile.dist.yaml | 7 ++++--- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/.taskfile.build.yaml b/.taskfile.build.yaml index 3b07b0c2a0..d568a82402 100644 --- a/.taskfile.build.yaml +++ b/.taskfile.build.yaml @@ -8,14 +8,14 @@ includes: vars: BIN: "{{.ROOT_DIR}}/bin" KUSTOMIZE_DIR: "config/default" - OPERATOR_CONTROLLER_MANIFEST: ./operator-controller.yaml + CONTROLLER_MANIFEST: ./{{.PROJECT}}.yaml OLMV0_VERSION: v0.24.0 CERT_MANAGER_VERSION: v1.9.0 RUKPAK_VERSION: v0.11.0 env: - IMAGE_REPO: quay.io/operator-framework/operator-controller + IMAGE_REPO: quay.io/operator-framework/{{.PROJECT}} IMAGE_TAG: devel tasks: @@ -58,7 +58,7 @@ tasks: GOARCH is taken from the environment to ensure a binary that will run on the local machine. GOOS is always set to `linux` for the docker build. - By default, the image is tagged as quay.io/operator-framework/operator-controller:devel. + By default, the image is tagged as quay.io/operator-framework/{{.PROJECT}}:devel. You can control the image repo and tag by setting the IMAGE_REPO and IMAGE_TAG environment variables. cmds: @@ -79,7 +79,7 @@ tasks: with the controller image set to the IMAGE_REPO and IMAGE_TAG environment variables. cmds: - cd config/manager && {{.TOOLSBIN}}/kustomize edit set image controller=$IMAGE_REPO:$IMAGE_TAG - - "{{.TOOLSBIN}}/kustomize build {{.KUSTOMIZE_DIR}} > {{.OPERATOR_CONTROLLER_MANIFEST}}" + - "{{.TOOLSBIN}}/kustomize build {{.KUSTOMIZE_DIR}} > {{.CONTROLLER_MANIFEST}}" deps: [tools:kustomize, generate] install-script: @@ -87,9 +87,9 @@ tasks: summary: | This task generates the install script that can be used to install the operator. - The OPERATOR_CONTROLLER_MANIFEST task variable is used to set the location that - will be used to `kubectl apply -f` the operator-controller manifest. By default, - this is set to `./operator-controller.yaml`. However this can be overridden during + The CONTROLLER_MANIFEST task variable is used to set the location that + will be used to `kubectl apply -f` the controller manifest. By default, + this is set to `./{{.PROJECT}}.yaml`. However this can be overridden during a release to reference the release manifest URL that is uploaded to GitHub during the release. silent: true @@ -113,8 +113,8 @@ tasks: kubectl wait --for=condition=Available --namespace=rukpak-system deployment/rukpak-webhooks --timeout=60s kubectl wait --for=condition=Available --namespace=crdvalidator-system deployment/crd-validation-webhook --timeout=60s - # Install operator-controller - kubectl apply -f {{.OPERATOR_CONTROLLER_MANIFEST}} - kubectl wait --for=condition=Available --namespace=operator-controller-system deployment/operator-controller-controller-manager --timeout=60s + # Install controller + kubectl apply -f {{.CONTROLLER_MANIFEST}} + kubectl wait --for=condition=Available --namespace={{.PROJECT}}-system deployment/{{.PROJECT}}-controller-manager --timeout=60s EOF - chmod +x ./install.sh diff --git a/.taskfile.deploy.yaml b/.taskfile.deploy.yaml index 265233f552..063e6af9c1 100644 --- a/.taskfile.deploy.yaml +++ b/.taskfile.deploy.yaml @@ -24,10 +24,10 @@ tasks: - task: build:manifest vars: KUSTOMIZE_DIR: "{{.KUSTOMIZE_DIR}}" - OPERATOR_CONTROLLER_MANIFEST: "{{.OPERATOR_CONTROLLER_MANIFEST}}" + CONTROLLER_MANIFEST: "{{.CONTROLLER_MANIFEST}}" - task: build:install-script vars: - OPERATOR_CONTROLLER_MANIFEST: "{{.OPERATOR_CONTROLLER_MANIFEST}}" + CONTROLLER_MANIFEST: "{{.CONTROLLER_MANIFEST}}" - task: kind:create vars: KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}" diff --git a/.taskfile.kind.yaml b/.taskfile.kind.yaml index 4b22d962f6..e849bcd559 100644 --- a/.taskfile.kind.yaml +++ b/.taskfile.kind.yaml @@ -1,7 +1,7 @@ version: '3' vars: - KIND_CLUSTER_NAME: "operator-controller" + KIND_CLUSTER_NAME: "{{.PROJECT}}" includes: tools: diff --git a/.taskfile.test.yaml b/.taskfile.test.yaml index 46a9293a94..64f25ddc3c 100644 --- a/.taskfile.test.yaml +++ b/.taskfile.test.yaml @@ -83,7 +83,7 @@ tasks: - task: deploy:kind vars: KUSTOMIZE_DIR: "config/e2e" - OPERATOR_CONTROLLER_MANIFEST: "operator-controller-e2e.yaml" + CONTROLLER_MANIFEST: "{{.PROJECT}}-e2e.yaml" KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}-e2e" KIND_EXTRA_FLAGS: "--config ./kind-e2e.yaml" GO_COVER: "true" @@ -93,8 +93,8 @@ tasks: KIND_CLUSTER_NAME: "{{.KIND_CLUSTER_NAME}}-e2e" - "{{.TOOLSBIN}}/ginkgo --tags {{.GO_BUILD_TAGS}} --progress --trace {{with .FOCUS}}--focus '{{.}}'{{end}} ./test/e2e" - # Delete the operator controller manager pod to write the coverage data to disk. - - kubectl delete --wait pod -n operator-controller-system -l control-plane=controller-manager + # Delete the controller manager pod to write the coverage data to disk. + - kubectl delete --wait pod -n {{.PROJECT}}-system -l control-plane=controller-manager - go tool covdata percent -i={{.GOCOVERDIR}} deps: [tools:ginkgo] diff --git a/Taskfile.dist.yaml b/Taskfile.dist.yaml index 9a998879bc..f65aeae7f5 100644 --- a/Taskfile.dist.yaml +++ b/Taskfile.dist.yaml @@ -1,11 +1,12 @@ version: '3' vars: + PROJECT: "{{base .ROOT_DIR}}" TOOLSBIN: "{{.ROOT_DIR}}/hack/tools/bin" GO_BUILD_TAGS: upstream env: - IMAGE_REPO: quay.io/operator-framework/operator-controller + IMAGE_REPO: quay.io/operator-framework/{{.PROJECT}} IMAGE_TAG: devel GORELEASER_ARGS: --snapshot --clean @@ -39,7 +40,7 @@ tasks: This task will run the operator in a kind cluster. The KIND_CLUSTER_NAME task variable is used to control the name of the - kind cluster. By default, this is set to "operator-controller". + kind cluster. By default, this is set to "{{.PROJECT}}". cmds: - task: deploy:kind vars: @@ -64,6 +65,6 @@ tasks: - task: build:manifest - task: build:install-script vars: - OPERATOR_CONTROLLER_MANIFEST: https://github.com/operator-framework/operator-controller/releases/download/$IMAGE_TAG/operator-controller.yaml + CONTROLLER_MANIFEST: https://github.com/operator-framework/{{.PROJECT}}/releases/download/$IMAGE_TAG/{{.PROJECT}}.yaml - "{{.TOOLSBIN}}/goreleaser release $GORELEASER_ARGS" deps: [tools:goreleaser]