diff --git a/.github/workflows/operator-framework-e2e.yaml b/.github/workflows/operator-developer-e2e.yaml similarity index 73% rename from .github/workflows/operator-framework-e2e.yaml rename to .github/workflows/operator-developer-e2e.yaml index a11d55499..d031b3feb 100644 --- a/.github/workflows/operator-framework-e2e.yaml +++ b/.github/workflows/operator-developer-e2e.yaml @@ -1,14 +1,14 @@ -name: operator-framework-e2e +name: operator-developer-e2e on: workflow_dispatch: pull_request: push: branches: - - operator-framework-e2e + - main jobs: - e2e-kind: + operator-developer-e2e: runs-on: ubuntu-latest steps: @@ -20,4 +20,4 @@ jobs: - name: Run the operator framework e2e test run: | - make operator-framework-e2e + make operator-developer-e2e diff --git a/Makefile b/Makefile index ed6f832b3..70f30a593 100644 --- a/Makefile +++ b/Makefile @@ -97,8 +97,8 @@ E2E_FLAGS ?= "" test-e2e: $(GINKGO) ## Run the e2e tests $(GINKGO) --tags $(GO_BUILD_TAGS) $(E2E_FLAGS) -trace -progress $(FOCUS) test/e2e -test-operator-framework-e2e: $(GINKGO) ## Run operator create, upgrade and delete tests - $(GINKGO) --tags $(GO_BUILD_TAGS) $(E2E_FLAGS) -trace -progress test/operator-e2e +test-operator-developer-e2e: $(GINKGO) ## Run operator create, upgrade and delete tests + $(GINKGO) --tags $(GO_BUILD_TAGS) $(E2E_FLAGS) -trace -progress test/operator-framework-e2e ENVTEST_VERSION = $(shell go list -m k8s.io/client-go | cut -d" " -f2 | sed 's/^v0\.\([[:digit:]]\{1,\}\)\.[[:digit:]]\{1,\}$$/1.\1.x/') UNIT_TEST_DIRS=$(shell go list ./... | grep -v /test/) @@ -108,8 +108,8 @@ test-unit: $(SETUP_ENVTEST) ## Run the unit tests e2e: KIND_CLUSTER_NAME=operator-controller-e2e e2e: run kind-load-test-artifacts test-e2e kind-cluster-cleanup ## Run e2e test suite on local kind cluster -operator-framework-e2e: KIND_CLUSTER_NAME=operator-controller-e2e ## Run operator-framework e2e on local kind cluster -operator-framework-e2e: run opm test-operator-framework-e2e kind-cluster-cleanup +operator-developer-e2e: KIND_CLUSTER_NAME=operator-controller-e2e ## Run operator-developer e2e on local kind cluster +operator-developer-e2e: run opm install-operator-sdk deploy-local-registry test-operator-developer-e2e stop-local-registry kind-cluster-cleanup kind-load: $(KIND) ## Loads the currently constructed image onto the cluster $(KIND) load docker-image $(IMG) --name $(KIND_CLUSTER_NAME) @@ -147,6 +147,25 @@ OPM = $(shell which opm) endif endif +.PHONY: install-operator-sdk +OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/v1.30.0 +export OS=$(shell go env GOOS) +export ARCH=$(shell go env GOARCH) +install-operator-sdk: ## Install operator-sdk + if [ ! -f ~/bin/operator-sdk ]; then \ + curl -LO $(OPERATOR_SDK_DL_URL)/operator-sdk_${OS}_${ARCH} ; \ + chmod +x operator-sdk_${OS}_${ARCH} ; \ + mv operator-sdk_$(OS)_$(ARCH) /usr/local/bin/operator-sdk ; \ + fi + +.PHONY: deploy-local-registry +deploy-local-registry: ## Deploy local docker registry + docker run -d -p 5000:5000 --restart=always --name local-registry registry:2 + +.PHONY: stop-local-registry +stop-local-registry: ## Stop and remove local registry + docker container stop local-registry && docker container rm -v local-registry + ##@ Build export VERSION ?= $(shell git describe --tags --always --dirty) diff --git a/go.mod b/go.mod index c7b6cc19c..74dac0e03 100644 --- a/go.mod +++ b/go.mod @@ -72,6 +72,8 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/h2non/filetype v1.1.1 // indirect github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c // indirect github.com/imdario/mergo v0.3.13 // indirect @@ -91,7 +93,10 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/operator-framework/api v0.17.3 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2 // indirect + github.com/operator-framework/api v0.17.4-0.20230223191600-0131a6301e42 // indirect + github.com/otiai10/copy v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect diff --git a/go.sum b/go.sum index beb2338aa..9d3ad237b 100644 --- a/go.sum +++ b/go.sum @@ -49,19 +49,63 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.9.6 h1:VwnDOgLeoi2du6dAznfmspNqTiwczvjv4K7NxuY9jsY= +github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= +github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= +github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -311,9 +355,23 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-air/gini v1.0.4 h1:lteMAxHKNOAjIqazL/klOJJmxq6YxxSuJ17MnMXny+s= github.com/go-air/gini v1.0.4/go.mod h1:dd8RvT1xcv6N1da33okvBd8DhMh1/A4siGy6ErjTljs= @@ -481,25 +539,67 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/h2non/filetype v1.1.1 h1:xvOwnXKAckvtLWsN398qS9QhlxlnVXBjXBydK2/UFB4= github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c h1:fEE5/5VNnYUoBOj2I9TP8Jc+a7lge3QWn9DKE7NCwfc= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= +github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d h1:A2/B900ip/Z20TzkLeGRNy1s6J2HmH9AmGt+dHyqb4I= github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d/go.mod h1:7HQupe4vyNxMKXmM5DFuwXHsqwMyglcYmZBtlDPIcZ8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -514,7 +614,11 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= @@ -527,6 +631,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= @@ -543,12 +648,39 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk= +github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -594,16 +726,56 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= -github.com/operator-framework/api v0.17.3 h1:wddE1SLKTNiIzwt28DbBIO+vPG2GOV6dkB9xBkDfT3o= -github.com/operator-framework/api v0.17.3/go.mod h1:34tb98EwTN5SZLkgoxwvRkhMJKLHUWHOrrcv1ZwvEeA= -github.com/operator-framework/catalogd v0.3.0 h1:3VETisrDiJdkpFvTObYQ6oW8J7ddpVdRryjRD7ugwCg= -github.com/operator-framework/catalogd v0.3.0/go.mod h1:CSP73BBkYb7Tr6sgUNxK1Gozc+qt7KyDLb3AS0vXo/0= -github.com/operator-framework/deppy v0.0.0-20230602120738-cbf2c66b141b h1:m7MhK8IJx9Abb0ULbUw8vXqGMP1S9bodLrKh5d6wk6k= -github.com/operator-framework/deppy v0.0.0-20230602120738-cbf2c66b141b/go.mod h1:9xVfBnKK/p6M/vQlsHqscslUtUYnK2is5D24liQBtoE= -github.com/operator-framework/operator-registry v1.26.3 h1:U+HTGgjAT5RCXU2WkDwa525wcqdo97BsO7WfMhwL5MA= -github.com/operator-framework/operator-registry v1.26.3/go.mod h1:DZcTzhAyZf/NLi2UwBQA1F/qh4FwgYBcgBx2yBz8I+Q= -github.com/operator-framework/rukpak v0.12.0 h1:qzM18RQZdqS00/6GLkEiTZf0pHtQ5bVg/DLzAmho+jQ= -github.com/operator-framework/rukpak v0.12.0/go.mod h1:evm7OWW3t0A0PcVUpAzhJrhv4A9GXURfynGloAtyJ5A= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/operator-framework/api v0.17.4-0.20230223191600-0131a6301e42 h1:d/Pnr19TnmIq3zQ6ebewC+5jt5zqYbRkvYd37YZENQY= +github.com/operator-framework/api v0.17.4-0.20230223191600-0131a6301e42/go.mod h1:l/cuwtPxkVUY7fzYgdust2m9tlmb8I4pOvbsUufRb24= +github.com/operator-framework/catalogd v0.4.1 h1:fEshy6DpYHwYxg37KX1sdbGl2aaYuN1taoKTQfD6JnA= +github.com/operator-framework/catalogd v0.4.1/go.mod h1:2RrJAnYicjjx9cLGNrRAknToTLv0GeHDaODi2/Iqp0I= +github.com/operator-framework/deppy v0.0.0-20230629133131-bb7b6ae7b266 h1:SQEUaAoRWNhr2poLH6z/RsEWZG7PppDWHsr5vAvJkJc= +github.com/operator-framework/deppy v0.0.0-20230629133131-bb7b6ae7b266/go.mod h1:6kgHMeS5vQt3gqWGgJIig1yT5uflBUsCc1orP+I3nbk= +github.com/operator-framework/operator-registry v1.27.1 h1:yU4atKR69XKH/GHlhgTdKTOAv4qRZUIFVHgrJE4FyiE= +github.com/operator-framework/operator-registry v1.27.1/go.mod h1:zVsP+QdutDReiSpASIYqbrixjoNEHZKAyBOgLz1jaXk= +github.com/operator-framework/rukpak v0.13.0 h1:QP0P9ybwtkFpfVOMY9z5v4+vRyBdoqAotv8RP/SZ0hw= +github.com/operator-framework/rukpak v0.13.0/go.mod h1:Y/TkS3v5h4zl83CBcB708Ure2uhU1da8NQi/hOcHGYM= +github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1 h1:BCmzIS3n71sGfHB5NMNDB3lHYPz8fWSkCAErHed//qc= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -662,7 +834,17 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -709,7 +891,36 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -775,6 +986,7 @@ go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQP go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -785,8 +997,11 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -861,8 +1076,11 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -920,6 +1138,10 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -966,8 +1188,11 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -979,6 +1204,7 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1187,14 +1413,23 @@ gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/test/operator-e2e/README.md b/test/operator-e2e/README.md deleted file mode 100644 index d1682430b..000000000 --- a/test/operator-e2e/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Cross-component E2E for operator framework - -This is a cross-component demo with all OLM v1 repositories. The ginkgo test does the following: -- Automates the creation of plain+v0 bundles and FBCs for a set of bundle manifest directories. -- Creates, upgrades and deletes a plain+v0 operator. - -## Objective -- Development on OLM v1 is split across multiple repositories, and the list of relevant repositories may grow over time. While we have demos showing improvements in functionality of components over time, it can be difficult to have a picture of the state of OLM v1 at any given time for someone not following its development closely. Having a single source to look for OLM v1 behavior can provide more clarity about the state of the project. -- With the scale of the OLM v1 project, it is useful to have a means to test components in the operator development + lifecycle pipeline together to create a more cohesive experience for all users. - -## Getting Started - -- Plain bundle manifests are taken as input. - - - The plain bundle manifest directory taken as input should follow the below directory structure: - ``` - bundles/ - └── plain-v0/ - ├── plain.v0.1.0/ - │ ├── manifests - │ └── Dockerfile - └── plain.v0.1.1/ - ├── manifests - └── Dockerfile - ``` - - The bundles should present in the testdata folder. - - The bundle paths and bundle image reference is hard coded in the test. - -- After the bundle image is created and loaded, the FBC is created by accepting the required information in a config file named `catalog_config.yaml` in the directory `test/operator-e2e/config`. - - - Example `catalog_config.yaml` file: - ``` - schema: catalog-config - packageName: plain - channelData: - - channelName: foo - channelEntries: - - entryVersion: 0.1.0 - replaces: null - skipRange: null - skips: - - null - bundleData: - - bundleImage: foobar:v0.1.0 - bundleVersion: 0.1.0 - ``` - - The generated FBC will be present in the directory structure: `testdata/catalogs/plainv0-test-catalog`. - - The Dockerfile is generated and the FBC image is built and loaded. - - The output catalog path, catalog name, catalog image reference are hard-coded in the test. - - The FBC generated is validated using opm. - -- The FBC image is then used to create an operator. - - Based on the catalog data, we hard code the package names and their version that is to be installed and upgraded. diff --git a/test/operator-e2e/config/catalog_config.yaml b/test/operator-e2e/config/catalog_config.yaml deleted file mode 100644 index 88d0d1fe1..000000000 --- a/test/operator-e2e/config/catalog_config.yaml +++ /dev/null @@ -1,32 +0,0 @@ -schema: catalog-config -packageName: plain -channelData: -- channelName: beta - channelEntries: - - entryVersion: 0.1.0 - replaces: null - skips: - - null - skipRange: null - - entryVersion: 0.1.1 - replaces: null - skips: - - 0.1.0 - skipRange: null -- channelName: foo - channelEntries: - - entryVersion: 0.1.0 - replaces: null - skips: - - null - skipRange: null - - entryVersion: 0.1.1 - replaces: 0.1.0 - skips: - - null - skipRange: null -bundleData: -- bundleImage: localhost/testdata/bundles/plain-v0/plain:v0.1.0 - bundleVersion: 0.1.0 -- bundleImage: localhost/testdata/bundles/plain-v0/plain:v0.1.1 - bundleVersion: 0.1.1 diff --git a/test/operator-e2e/config/read_config.go b/test/operator-e2e/config/read_config.go deleted file mode 100644 index 1b53bbd00..000000000 --- a/test/operator-e2e/config/read_config.go +++ /dev/null @@ -1,70 +0,0 @@ -package config - -import ( - "errors" - "fmt" - "os" - - "sigs.k8s.io/yaml" -) - -const ( - schemaName = "catalog-config" -) - -type ChannelEntry struct { - EntryVersion string `json:"entryVersion"` - Replaces string `json:"replaces,omitempty"` - Skips []string `json:"skips,omitempty"` - SkipRange string `json:"skipRange,omitempty"` -} - -type ChannelData struct { - ChannelName string `json:"channelName"` - ChannelEntries []ChannelEntry `json:"channelEntries"` -} - -type BundleData struct { - BundleImage string `json:"bundleImage"` - BundleVersion string `json:"bundleVersion"` -} - -type Config struct { - Schema string `json:"schema"` - PackageName string `json:"packageName"` - ChannelData []ChannelData `json:"channelData"` - BundleData []BundleData `json:"bundleData"` -} - -// Reads the catalog-config.yaml and maps it to the above structs -func ReadFile(f string) (*Config, error) { - b, err := readFile(f) - if err != nil { - return nil, err - } - - var c Config - err = yaml.Unmarshal(b, &c) - if err != nil { - return nil, err - } - if c.Schema != schemaName { - return nil, fmt.Errorf("invalid schema: %q should be %q: %v", c.Schema, schemaName, err) - } - if c.PackageName == "" { - return nil, errors.New("missing required package name") - } - if len(c.ChannelData) == 0 { - return nil, errors.New("missing required channel information") - } - if len(c.BundleData) == 0 { - return nil, errors.New("missing required bundle information") - } - - return &c, nil -} - -// overrideable func for mocking os.ReadFile -var readFile = func(file string) ([]byte, error) { - return os.ReadFile(file) -} diff --git a/test/operator-e2e/create_fbc.go b/test/operator-e2e/create_fbc.go deleted file mode 100644 index 3c787a4d1..000000000 --- a/test/operator-e2e/create_fbc.go +++ /dev/null @@ -1,146 +0,0 @@ -package operatore2e - -import ( - "bytes" - "encoding/json" - "fmt" - "os" - - "github.com/operator-framework/operator-registry/alpha/declcfg" - "github.com/operator-framework/operator-registry/alpha/property" - - "github.com/operator-framework/operator-controller/test/operator-e2e/config" -) - -const ( - SchemaPackage = "olm.package" - SchemaChannel = "olm.channel" - SchemaBundle = "olm.bundle" - SchemaBundleMediatype = "olm.bundle.mediatype" - BundleMediatype = "plain+v0" -) - -// Reads the catalog-config and creates the FBC by calling functions for forming the package, channel and bundles. -func CreateFBC(configFilePath string) (*declcfg.DeclarativeConfig, error) { - config, err := config.ReadFile(configFilePath) - if err != nil { - return nil, err - } - - dPackage := formPackage(*config) - dChannel := formChannel(*config) - dBundle := formBundle(*config) - - fbc := declcfg.DeclarativeConfig{ - Packages: []declcfg.Package{dPackage}, - Channels: dChannel, - Bundles: dBundle, - } - return &fbc, nil -} - -// Forms package schema for the FBC -func formPackage(config config.Config) declcfg.Package { - packageFormed := declcfg.Package{ - Schema: SchemaPackage, - Name: config.PackageName, - DefaultChannel: config.ChannelData[0].ChannelName, - } - return packageFormed -} - -// Forms channel schema for the FBC -func formChannel(config config.Config) []declcfg.Channel { - channelFormed := make([]declcfg.Channel, 0, len(config.ChannelData)) - for _, channel := range config.ChannelData { - channelEntries := formChannelEntries(config.PackageName, channel) - channelFormed = append(channelFormed, declcfg.Channel{ - Schema: SchemaChannel, - Name: channel.ChannelName, - Package: config.PackageName, - Entries: channelEntries, - }) - } - return channelFormed -} - -// Forms the uprade graph for the FBC -func formChannelEntries(pkgName string, channel config.ChannelData) []declcfg.ChannelEntry { - channelEntries := make([]declcfg.ChannelEntry, 0, len(channel.ChannelEntries)) - for _, channelEntry := range channel.ChannelEntries { - replace := "" - if channelEntry.Replaces != "" { - replace = pkgName + "." + channelEntry.Replaces - } - - skip := []string{} - if len(channelEntry.Skips) != 0 { - for _, s := range channelEntry.Skips { - if s != "" { - skip = append(skip, pkgName+"."+s) - } - } - } - channelEntries = append(channelEntries, declcfg.ChannelEntry{ - Name: pkgName + "." + channelEntry.EntryVersion, - Replaces: replace, - Skips: skip, - SkipRange: channelEntry.SkipRange, - }) - } - return channelEntries -} - -// Forms bundle schema for the FBC -func formBundle(config config.Config) []declcfg.Bundle { - bundleFormed := make([]declcfg.Bundle, 0, len(config.BundleData)) - for _, bundle := range config.BundleData { - var properties []property.Property - properties = append(properties, property.Property{ - Type: SchemaPackage, - Value: json.RawMessage(fmt.Sprintf(`{"packageName": "%s", "version": "%s"}`, config.PackageName, bundle.BundleVersion)), - }) - properties = append(properties, property.Property{ - Type: SchemaBundleMediatype, - Value: json.RawMessage(fmt.Sprintf(`"%s"`, BundleMediatype)), - }) - - bundleFormed = append(bundleFormed, declcfg.Bundle{ - Schema: SchemaBundle, - Name: config.PackageName + "." + bundle.BundleVersion, - Package: config.PackageName, - Image: bundle.BundleImage, - Properties: properties, - }) - } - return bundleFormed -} - -// Writes the formed FBC into catalog.yaml file -func WriteFBC(fbc declcfg.DeclarativeConfig, fbcFilePath, fbcFileName string) error { - var buf bytes.Buffer - err := declcfg.WriteYAML(fbc, &buf) - if err != nil { - return err - } - - _, err = os.Stat(fbcFilePath) - if os.IsNotExist(err) { - err := os.MkdirAll(fbcFilePath, 0755) - if err != nil { - return err - } - } - file, err := os.Create(fbcFilePath + "/" + fbcFileName) - if err != nil { - return err - } - defer file.Close() - - err = os.WriteFile(fbcFilePath+"/"+fbcFileName, buf.Bytes(), 0600) - if err != nil { - return err - } - - return nil -} diff --git a/test/operator-e2e/operator_test.go b/test/operator-e2e/operator_test.go deleted file mode 100644 index ab374879b..000000000 --- a/test/operator-e2e/operator_test.go +++ /dev/null @@ -1,509 +0,0 @@ -package operatore2e - -import ( - "context" - "fmt" - "io" - "os/exec" - "strings" - "testing" - "time" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "k8s.io/apimachinery/pkg/api/errors" - apimeta "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1" - rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" - - operatorv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" -) - -type BundleInfo struct { - BundleDirectory string - BundleImageRef string -} - -var ( - cfg *rest.Config - c client.Client - operatorCatalog *catalogd.Catalog - operator *operatorv1alpha1.Operator - err error - ctx context.Context - bundleInfo = []BundleInfo{ - { // The bundle directories of the plain bundles whose image is to be created and pushed along with the image reference - BundleImageRef: "localhost/testdata/bundles/plain-v0/plain:v0.1.0", - BundleDirectory: "plain.v0.1.0", - }, - { - BundleImageRef: "localhost/testdata/bundles/plain-v0/plain:v0.1.1", - BundleDirectory: "plain.v0.1.1", - }, - } -) - -const ( - plainBundlesPath = "../../testdata/bundles/plain-v0" - kindServer = "operator-controller-e2e" - - catalogPath = "../../testdata/catalogs" - catalogName = "plainv0-test-catalog" - catalogImageRef = "localhost/testdata/catalogs/plainv0-test-catalog:test" - fbcConfigFilePath = "config/catalog_config.yaml" - fbcFileName = "catalog.yaml" - opmPath = "../../bin/opm" - - operatorName = "plainv0-test-operator" - createPkgName = "plain" - createPkgVersion = "0.1.0" - updatePkgName = "plain" - updatePkgVersion = "0.1.1" - nameSpace = "rukpak-system" -) - -func TestOperatorFramework(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Operator Framework E2E Suite") -} - -var _ = BeforeSuite(func() { - - var err error - cfg = ctrl.GetConfigOrDie() - - scheme := runtime.NewScheme() - - err = catalogd.AddToScheme(scheme) - Expect(err).ToNot(HaveOccurred()) - - err = operatorv1alpha1.AddToScheme(scheme) - Expect(err).To(Not(HaveOccurred())) - - err = rukpakv1alpha1.AddToScheme(scheme) - Expect(err).To(Not(HaveOccurred())) - - c, err = client.New(cfg, client.Options{Scheme: scheme}) - Expect(err).To(Not(HaveOccurred())) - - ctx = context.Background() - -}) - -var _ = AfterSuite(func() { - Eventually(func(g Gomega) { - // Deleting the catalog object and checking if the deletion was successful - err = deleteAndCheckCatalogDeleted(operatorCatalog) - g.Expect(errors.IsNotFound(err)).To(BeTrue()) - }).Should(Succeed()) -}) - -var _ = Describe("Operator Framework E2E", func() { - When("Create and load plain+v0 bundle images onto a test environment", func() { - It("Create bundle images", func() { - By("By building required bundle images") - for _, bundle := range bundleInfo { - err = buildContainer(bundle.BundleImageRef, plainBundlesPath+"/"+bundle.BundleDirectory+"/Dockerfile", plainBundlesPath+"/"+bundle.BundleDirectory, GinkgoWriter) - Expect(err).To(Not(HaveOccurred())) - } - }) - - It("Load bundle images onto test environment", func() { - By("Loading bundle images") - var images []string - for _, info := range bundleInfo { - images = append(images, info.BundleImageRef) - } - err = pushLoadImages(GinkgoWriter, kindServer, images...) - Expect(err).To(Not(HaveOccurred())) - }) - - }) - When("Create FBC and validate FBC", func() { - It("Create a FBC", func() { - By("Forming the FBC content from catalog_config.yaml") - fbc, err := CreateFBC(fbcConfigFilePath) - Expect(err).To(Not(HaveOccurred())) - - By("Writing the FBC content to catalog.yaml file") - err = WriteFBC(*fbc, catalogPath+"/"+catalogName, fbcFileName) - Expect(err).To(Not(HaveOccurred())) - }) - It("Validate FBC", func() { - By("By validating the FBC using opm validate") - err = validateFBC(catalogPath + "/" + catalogName) - Expect(err).To(Not(HaveOccurred())) - }) - }) - When("Create docker file and FBC image and load the FBC image onto test environment", func() { - It("Create the docker file", func() { - By("By calling dockerfile create function") - err = generateDockerFile(catalogPath, catalogName, catalogName+".Dockerfile") - Expect(err).To(Not(HaveOccurred())) - }) - It("Create FBC image", func() { - By("By building FBC image") - err = buildContainer(catalogImageRef, catalogPath+"/"+catalogName+".Dockerfile", catalogPath, GinkgoWriter) - Expect(err).To(Not(HaveOccurred())) - }) - It("Load FBC image onto test environment", func() { - By("Loading FBC image") - err = pushLoadImages(GinkgoWriter, kindServer, catalogImageRef) - Expect(err).To(Not(HaveOccurred())) - }) - }) - When("A catalog object is created from the FBC image and deployed", func() { - It("Deploy catalog object with FBC image", func() { - By("Creating an operator catalog object") - operatorCatalog, err = createTestCatalog(ctx, catalogName, catalogImageRef) - Expect(err).ToNot(HaveOccurred()) - - By("Eventually checking if catalog unpacking is successful") - Eventually(func(g Gomega) { - err = checkCatalogUnpacked(operatorCatalog) - g.Expect(err).ToNot(HaveOccurred()) - }, 10*time.Second, 1).Should(Succeed()) - - By("Eventually checking if package is created") - Eventually(func(g Gomega) { - err = checkPackageCreated() - g.Expect(err).ToNot(HaveOccurred()) - }, 10*time.Second, 1).Should(Succeed()) - - By("Eventually checking if bundle metadata is created") - Eventually(func(g Gomega) { - err = checkBundleMetadataCreated() - g.Expect(err).ToNot(HaveOccurred()) - }).Should(Succeed()) - - }) - }) - When("An operator is installed from an operator catalog", func() { - It("Create an operator object and install it", func() { - By("By creating an operator object") - operator, err = createOperator(ctx, operatorName, createPkgName, createPkgVersion) - Expect(err).ToNot(HaveOccurred()) - - By("Eventually reporting a successful resolution and bundle path") - Eventually(func(g Gomega) { - err = checkResolutionAndBundlePath(operator) - g.Expect(err).ToNot(HaveOccurred()) - }, 10*time.Second, 1).Should(Succeed()) - - By("Eventually installing the operator successfully") - Eventually(func(g Gomega) { - err = checkOperatorInstalled(operator, createPkgVersion) - g.Expect(err).ToNot(HaveOccurred()) - }, 10*time.Second, 1).Should(Succeed()) - - By("Eventually installing the package successfully") - Eventually(func(g Gomega) { - err = checkPackageInstalled(operator) - g.Expect(err).ToNot(HaveOccurred()) - }, 10*time.Second, 1).Should(Succeed()) - - By("Eventually verifying the presence of relevant manifest on cluster from the bundle") - Eventually(func(g Gomega) { - err = checkManifestPresence(createPkgName, createPkgVersion) - g.Expect(err).ToNot(HaveOccurred()) - }).Should(Succeed()) - }) - }) - When("An operator is upgraded to a higher version", func() { - It("Upgrade to an higher version of the operator", func() { - operator, err = updateOperator(ctx, operatorName, updatePkgName, updatePkgVersion) - Expect(err).ToNot(HaveOccurred()) - - By("Eventually reporting a successful resolution and bundle path for the upgraded version") - Eventually(func(g Gomega) { - err = checkResolutionAndBundlePath(operator) - g.Expect(err).ToNot(HaveOccurred()) - }, 10*time.Second, 1).Should(Succeed()) - - By("Eventually upgrading the operator successfully") - Eventually(func(g Gomega) { - err = checkOperatorInstalled(operator, updatePkgVersion) - g.Expect(err).ToNot(HaveOccurred()) - }, 10*time.Second, 1).Should(Succeed()) - - By("Eventually upgrading the package successfully") - Eventually(func(g Gomega) { - err = checkPackageInstalled(operator) - g.Expect(err).ToNot(HaveOccurred()) - }, 10*time.Second, 1).Should(Succeed()) - - By("Eventually verifying the presence of relevant manifest on cluster from the bundle") - Eventually(func(g Gomega) { - err = checkManifestPresence(updatePkgName, updatePkgVersion) - g.Expect(err).ToNot(HaveOccurred()) - }).Should(Succeed()) - }) - }) - When("An operator is deleted", func() { - It("Delete and operator", func() { - operator, err = deleteOperator(ctx, operatorName) - Expect(err).ToNot(HaveOccurred()) - - By("Eventually the operator should not exists") - Eventually(func(g Gomega) { - err = checkOperatorDeleted(operator) - g.Expect(errors.IsNotFound(err)).To(BeTrue()) - }).Should(Succeed()) - }) - }) -}) - -func validateFBC(fbcDirPath string) error { - cmd := exec.Command(opmPath, "validate", fbcDirPath) - output, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("FBC validation failed: %s", output) - } - return nil -} - -func buildContainer(tag, dockerfilePath, dockerContext string, w io.Writer) error { - cmd := exec.Command("docker", "build", "-t", tag, "-f", dockerfilePath, dockerContext) - cmd.Stderr = w - cmd.Stdout = w - err := cmd.Run() - return err -} - -func pushLoadImages(w io.Writer, kindServerName string, images ...string) error { - for _, image := range images { - cmd := exec.Command("kind", "load", "docker-image", image, "--name", kindServerName) - cmd.Stderr = w - cmd.Stdout = w - err := cmd.Run() - if err != nil { - return err - } - } - return nil -} - -func checkConditionEquals(actualCond, expectedCond *metav1.Condition) error { - if actualCond == nil { - return fmt.Errorf("Expected condition %s to not be nil", expectedCond.Type) - } - if actualCond.Status != expectedCond.Status { - return fmt.Errorf("Expected status: %s, but got: %s", expectedCond.Status, actualCond.Status) - } - if actualCond.Reason != expectedCond.Reason { - return fmt.Errorf("Expected reason: %s but got: %s", expectedCond.Reason, actualCond.Reason) - } - if !strings.Contains(actualCond.Message, expectedCond.Message) { - return fmt.Errorf("Expected message: %s but got: %s", expectedCond.Message, actualCond.Message) - } - return nil -} - -func checkCatalogUnpacked(operatorCatalog *catalogd.Catalog) error { - err = c.Get(ctx, types.NamespacedName{Name: operatorCatalog.Name}, operatorCatalog) - if err != nil { - return err - } - cond := apimeta.FindStatusCondition(operatorCatalog.Status.Conditions, catalogd.TypeUnpacked) - expectedCond := &metav1.Condition{ - Type: catalogd.TypeUnpacked, - Status: metav1.ConditionTrue, - Reason: catalogd.ReasonUnpackSuccessful, - Message: "successfully unpacked the catalog image", - } - err = checkConditionEquals(cond, expectedCond) - return err -} - -func checkPackageCreated() error { - pList := &catalogd.PackageList{} - err = c.List(ctx, pList) - if err != nil { - return err - } - if len(pList.Items) == 0 { - return fmt.Errorf("Package is not created") - } - return nil -} - -func checkBundleMetadataCreated() error { - bmList := &catalogd.BundleMetadataList{} - err = c.List(ctx, bmList) - if err != nil { - return err - } - if len(bmList.Items) == 0 { - return fmt.Errorf("Bundle metadata is not created") - } - return nil -} - -func checkResolutionAndBundlePath(operator *operatorv1alpha1.Operator) error { - err = c.Get(ctx, types.NamespacedName{Name: operator.Name}, operator) - if err != nil { - return err - } - cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeResolved) - expectedCond := &metav1.Condition{ - Type: operatorv1alpha1.TypeResolved, - Status: metav1.ConditionTrue, - Reason: operatorv1alpha1.ReasonSuccess, - Message: "resolved to", - } - err = checkConditionEquals(cond, expectedCond) - if err != nil { - return err - } - if operator.Status.ResolvedBundleResource == "" { - return fmt.Errorf("Resoved Bundle Resource is not found") - } - return nil -} - -func checkOperatorInstalled(operator *operatorv1alpha1.Operator, operatorVersion string) error { - err = c.Get(ctx, types.NamespacedName{Name: operator.Name}, operator) - if err != nil { - return err - } - cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeInstalled) - expectedCond := &metav1.Condition{ - Type: operatorv1alpha1.TypeResolved, - Status: metav1.ConditionTrue, - Reason: operatorv1alpha1.ReasonSuccess, - Message: "installed from", - } - err = checkConditionEquals(cond, expectedCond) - if err != nil { - return err - } - if operator.Status.InstalledBundleResource == "" { - return fmt.Errorf("Installed Bundle Resource is not found") - } - if operator.Spec.Version != operatorVersion { - return fmt.Errorf("Expected operator version: %s but got: %s", operator.Spec.Version, operatorVersion) - } - return nil -} - -func checkPackageInstalled(operator *operatorv1alpha1.Operator) error { - bd := rukpakv1alpha1.BundleDeployment{} - err = c.Get(ctx, types.NamespacedName{Name: operator.Name}, &bd) - if err != nil { - return err - } - if len(bd.Status.Conditions) != 2 { - return fmt.Errorf("Two conditions for successful unpack and successful installation are not populated") - } - if bd.Status.Conditions[0].Reason != "UnpackSuccessful" { - return fmt.Errorf("Expected status condition reason for successful unpack is not populated") - } - if bd.Status.Conditions[1].Reason != "InstallationSucceeded" { - return fmt.Errorf("Expected status condition reason for successful installation is not populated") - } - return nil -} - -func checkManifestPresence(packageName, version string) error { - resources, _ := collectKubernetesObjects(packageName, version) - for _, resource := range resources { - gvk := schema.GroupVersionKind{ - Group: "", - Version: resource.APIVersion, - Kind: resource.Kind, - } - - obj := &unstructured.Unstructured{} - obj.SetGroupVersionKind(gvk) - err = c.Get(ctx, types.NamespacedName{Name: resource.Metadata.Name, Namespace: nameSpace}, obj) - if err != nil { - return err - } - } - return nil -} - -func checkOperatorDeleted(operator *operatorv1alpha1.Operator) error { - err = c.Get(ctx, types.NamespacedName{Name: operator.Name}, &operatorv1alpha1.Operator{}) - return err -} - -func deleteAndCheckCatalogDeleted(catalog *catalogd.Catalog) error { - err = c.Delete(ctx, operatorCatalog) - if err != nil { - return err - } - err = c.Get(ctx, types.NamespacedName{Name: catalog.Name}, &catalogd.Catalog{}) - return err -} - -func createTestCatalog(ctx context.Context, name, imageRef string) (*catalogd.Catalog, error) { - catalog := &catalogd.Catalog{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Spec: catalogd.CatalogSpec{ - Source: catalogd.CatalogSource{ - Type: catalogd.SourceTypeImage, - Image: &catalogd.ImageSource{ - Ref: imageRef, - }, - }, - }, - } - - err := c.Create(ctx, catalog) - return catalog, err -} - -func createOperator(ctx context.Context, operatorName, packageName, version string) (*operatorv1alpha1.Operator, error) { - operator := &operatorv1alpha1.Operator{ - ObjectMeta: metav1.ObjectMeta{ - Name: operatorName, - }, - Spec: operatorv1alpha1.OperatorSpec{ - PackageName: packageName, - Version: version, - }, - } - - err := c.Create(ctx, operator) - return operator, err -} - -func updateOperator(ctx context.Context, operatorName, packageName, version string) (*operatorv1alpha1.Operator, error) { - operator := &operatorv1alpha1.Operator{ - ObjectMeta: metav1.ObjectMeta{ - Name: operatorName, - }, - } - err := c.Get(ctx, types.NamespacedName{Name: operatorName}, operator) - if err != nil { - return nil, err - } - operator.Spec.PackageName = packageName - operator.Spec.Version = version - - err = c.Update(ctx, operator) - return operator, err -} - -func deleteOperator(ctx context.Context, operatorName string) (*operatorv1alpha1.Operator, error) { - err := c.Get(ctx, types.NamespacedName{Name: operatorName}, operator) - if err != nil { - return nil, err - } - - err = c.Delete(ctx, operator) - return operator, err -} diff --git a/test/operator-framework-e2e/README.md b/test/operator-framework-e2e/README.md new file mode 100644 index 000000000..90aff4e80 --- /dev/null +++ b/test/operator-framework-e2e/README.md @@ -0,0 +1,122 @@ +# Cross-component E2E for operator framework + +This is a cross-component demo with all OLM v1 repositories. The ginkgo test does the following: +- Automates the creation of `plain+v0` bundles and FBCs for a set of bundle manifest directories. +- Installs, upgrades and deletes a `plain+v0` operator. +- Uses operator-sdk to build `registry+v1` bundles and create catalogs to include the bundles. +- Installs, upgrades and deletes a `registry+v1` operator. + +## Objective +- Development on OLM v1 is split across multiple repositories, and the list of relevant repositories may grow over time. While we have demos showing improvements in functionality of components over time, it can be difficult to have a picture of the state of OLM v1 at any given time for someone not following its development closely. Having a single source to look for OLM v1 behavior can provide more clarity about the state of the project. +- With the scale of the OLM v1 project, it is useful to have a means to test components in the operator development + lifecycle pipeline together to create a more cohesive experience for all users. + +## Getting Started + +- Building operator-controller, deploying it into the cluster and rest of the configuration is done in the `MakeFile` of this repo under the target `operator-developer-e2e`. This includes: + + - Setting up a kind cluster. + - Installing the operator controller onto the cluster. + - Downloading the opm tool. + - Installing the operator-sdk. + - Setting up a local registry server for building and loading images. + +- The following structs defined are required as input for both plain+v0 and registry+v1 bundles: + - For getting bundle related inputs: + ``` + type BundleInfo struct { + baseFolderPath string + bundles []BundleContent + } + + type BundleContent struct { + bInputDir string + bundleVersion string + imageRef string + } + ``` + - `baseFolderPath` - Base path of the folder for the specific bundle type input data. + - `bundles` - Stores the data relevant to different versions of the bundle. + - `bInputDir` - The input directory containing the specific version of the bundle data. + - `bundleVersion` - The specific version of the bundle data. + - `imageRef` - This is formed. Stores the bundle image reference which will be of the format `localhost:5000/-bundle:v.` + - For getting catalog related inputs: + ``` + type CatalogDInfo struct { + baseFolderPath string + catalogDir string + operatorName string + desiredChannelName string + imageRef string + fbcFileName string + } + ``` + - `baseFolderPath` - Base path of the folder for the catalogs. + - `operatorName` - Name of the operator to be installed from the bundles. + - `desiredChannelName` - Desired channel name for the operator. + - `catalogDir` - This is formed. The directory to store the FBC. The formed value will be of the format: `-catalog` + - `imageRef` - This is formed. Stores the FBC image reference which will be of the format: `localhost:5000//:test` + - `fbcFileName` - Name of the FBC file. This is hard-coded as `catalog.yaml`. + - For getting information related to the install/upgrade action for operators: + ``` + type OperatorActionInfo struct { + installVersion string + upgradeVersion string + } + ``` + - `installVersion` - Version of the operator to be installed on the cluster. + - `upgradeVersion` - Version of the operator to be upgraded on the cluster. + +### Plain bundles +- Plain bundle manifests are taken as input. + + - The plain bundle manifest directory taken as input should follow the below directory structure: + ``` + bundles/ + └── plain-v0/ + ├── plain.v/ + │ ├── manifests + │ └── Dockerfile + └── plain.v/ + ├── manifests + └── Dockerfile + ``` + - The bundles should be present in the testdata folder. + +- After the bundle image is created and loaded, the FBC is formed by a custom routine by using the operatorName, desiredChannelName, bundle imageRefs and bundleVersions. + + - The generated FBC will be present in the file path: `testdata/catalogs/-catalog/catalog.yaml` and the Dockerfile will be formed in the file path: `testdata/catalogs/-catalog.Dockerfile` + - `Default channel` is not used in forming the FBC as it is not an OLMv1 concept. + - The package schema name will be the operatorName and the bundle name will be `.v`. + +- The catalog resource is then formed with the name `-catalog`. + +- The operator is then installed and has the name ``. + +### Registry Bundles + +- The registry+v1 bundles are formed using operator-sdk. + - The below input is used to form the bundle using operator-sdk. + ``` + type SdkProjectInfo struct { + projectName string + domainName string + group string + version string + kind string + } + ``` + - The generated CSV uses the default values. + - The bundle content is formed in the operator-sdk project directory in the folder `bundle`. This is moved to the folder path: `testdata/bundles/registry-v1/.v`. + - The generated Dockerfile has the name `bundle.Dockerfile`. + - The same project directory needs to be updated for forming a different version of the `bundle`. +- After the bundle image is created and loaded, the FBC is formed using `semver` and `opm` tool. + - The semver named `registry-semver.yaml` is formed by passing the bundle imageRefs. + - The generated FBC will be present in the file path: `testdata/catalogs/-catalog/catalog.yaml` and the Dockerfile will be formed in the file path: `testdata/catalogs/-catalog.Dockerfile` + - The package schema name will be the operator-sdk projectName. + +- The catalog resource is then formed with the name `-catalog`. + +- The operator is then installed and has the name ``. + + +- After the e2e workflow, all the files formed are cleared and the catalog is deleted. diff --git a/test/operator-framework-e2e/create_fbc_helper.go b/test/operator-framework-e2e/create_fbc_helper.go new file mode 100644 index 000000000..2fc430e3c --- /dev/null +++ b/test/operator-framework-e2e/create_fbc_helper.go @@ -0,0 +1,155 @@ +package operatore2e + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "strings" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/alpha/property" +) + +const ( + SchemaPackage = "olm.package" + SchemaChannel = "olm.channel" + SchemaBundle = "olm.bundle" + SchemaBundleMediatype = "olm.bundle.mediatype" + BundleMediatype = "plain+v0" +) + +// Forms the FBC declartive config and creates the FBC by calling functions for forming the package, channel and bundles. +func CreateFBC(operatorName, defaultChannel string, bundleRef, bundleVersions []string) *declcfg.DeclarativeConfig { + dPackage := formPackage(operatorName) + dChannel := formChannel(operatorName, defaultChannel, bundleVersions) + dBundle := formBundle(operatorName, bundleVersions, bundleRef) + + fbc := declcfg.DeclarativeConfig{ + Packages: []declcfg.Package{dPackage}, + Channels: []declcfg.Channel{dChannel}, + Bundles: dBundle, + } + return &fbc +} + +// Forms package schema for the FBC +func formPackage(pkgName string) declcfg.Package { + packageFormed := declcfg.Package{ + Schema: SchemaPackage, + Name: pkgName, + } + return packageFormed +} + +// Forms channel schema for the FBC +func formChannel(pkgName, channelName string, bundleVersions []string) declcfg.Channel { + channelEntries := formChannelEntries(pkgName, bundleVersions) + channelFormed := declcfg.Channel{ + Schema: SchemaChannel, + Name: channelName, + Package: pkgName, + Entries: channelEntries, + } + return channelFormed +} + +// Forms the uprade graph for the FBC +func formChannelEntries(pkgName string, bundleVersions []string) []declcfg.ChannelEntry { + channelEntries := make([]declcfg.ChannelEntry, 0, len(bundleVersions)) + for i, version := range bundleVersions { + replace := "" + if i != 0 { + replace = pkgName + ".v" + bundleVersions[i-1] + } + + channelEntries = append(channelEntries, declcfg.ChannelEntry{ + Name: pkgName + ".v" + version, + Replaces: replace, + }) + } + return channelEntries +} + +// Forms bundle schema for the FBC +func formBundle(pkgName string, versions, imageRefs []string) []declcfg.Bundle { + bundleFormed := make([]declcfg.Bundle, 0, len(imageRefs)) + for i := 0; i < len(imageRefs); i++ { + var properties []property.Property + properties = append(properties, property.Property{ + Type: SchemaPackage, + Value: json.RawMessage(fmt.Sprintf(`{"packageName": "%s", "version": "%s"}`, pkgName, versions[i])), + }) + properties = append(properties, property.Property{ + Type: SchemaBundleMediatype, + Value: json.RawMessage(fmt.Sprintf(`"%s"`, BundleMediatype)), + }) + + bundleFormed = append(bundleFormed, declcfg.Bundle{ + Schema: SchemaBundle, + Name: pkgName + ".v" + versions[i], + Package: pkgName, + Image: imageRefs[i], + Properties: properties, + }) + } + return bundleFormed +} + +// Writes the formed FBC into catalog.yaml file +func WriteFBC(fbc declcfg.DeclarativeConfig, fbcFilePath, fbcFileName string) error { + var buf bytes.Buffer + err := declcfg.WriteYAML(fbc, &buf) + if err != nil { + return err + } + + _, err = os.Stat(fbcFilePath) + if os.IsNotExist(err) { + err := os.MkdirAll(fbcFilePath, 0755) + if err != nil { + return err + } + } + file, err := os.Create(fbcFilePath + "/" + fbcFileName) + if err != nil { + return err + } + defer file.Close() + + err = os.WriteFile(fbcFilePath+"/"+fbcFileName, buf.Bytes(), 0600) + if err != nil { + return err + } + + return nil +} + +// Generates the semver using the bundle images passed +func generateOLMSemverFile(semverFileName string, bundleImages []string) error { + images := make([]string, 0, len(bundleImages)) + for _, bundleImage := range bundleImages { + images = append(images, fmt.Sprintf(" - image: %s", bundleImage)) + } + + fileContent := fmt.Sprintf(`schema: olm.semver +generatemajorchannels: false +generateminorchannels: false +stable: + bundles: +%s +`, strings.Join(images, "\n")) + + file, err := os.Create(semverFileName) + if err != nil { + return fmt.Errorf("error creating the semver yaml file %v : %v", semverFileName, err) + } + defer file.Close() + + _, err = file.WriteString(fileContent) + if err != nil { + return fmt.Errorf("error forming the semver yaml file %v : %v", semverFileName, err) + } + + return nil +} diff --git a/test/operator-e2e/generate_dockerfile.go b/test/operator-framework-e2e/generate_dockerfile.go similarity index 90% rename from test/operator-e2e/generate_dockerfile.go rename to test/operator-framework-e2e/generate_dockerfile.go index ff86d3ccb..4c10c054f 100644 --- a/test/operator-e2e/generate_dockerfile.go +++ b/test/operator-framework-e2e/generate_dockerfile.go @@ -6,7 +6,7 @@ import ( "text/template" ) -// generates Dockerfile and its contents for a given yaml file +// generates Dockerfile and its contents for a given set of yaml files func generateDockerFile(dockerFilePath, yamlFolderName, dockerFileName string) error { t, err := template.New("dockerfile").Parse(dockerfileTmpl) if err != nil { diff --git a/test/operator-framework-e2e/operator_framework_test.go b/test/operator-framework-e2e/operator_framework_test.go new file mode 100644 index 000000000..562b0c837 --- /dev/null +++ b/test/operator-framework-e2e/operator_framework_test.go @@ -0,0 +1,970 @@ +package operatore2e + +import ( + "context" + "encoding/json" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "reflect" + "strings" + "testing" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "k8s.io/apimachinery/pkg/api/errors" + apimeta "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1" + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" + + operatorv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" +) + +var ( + cfg *rest.Config + c client.Client + ctx context.Context +) + +type BundleInfo struct { + baseFolderPath string // Base path of the folder for the specific the bundle type input data + bundles []BundleContent // Stores the data relevant to different versions of the bundle +} + +type BundleContent struct { + bInputDir string // The input directory containing the specific version of bundle data + bundleVersion string // The specific version of the bundle data + imageRef string // Stores the bundle image reference +} + +type CatalogDInfo struct { + baseFolderPath string // Base path of the folder for the catalogs + catalogDir string // The folder storing the FBC + operatorName string // Name of the operator to be installed from the bundles + desiredChannelName string // Desired channel name for the operator + imageRef string // Stores the FBC image reference + fbcFileName string // Name of the FBC file +} + +type OperatorActionInfo struct { + installVersion string // Version of the operator to be installed on the cluster + upgradeVersion string // Version of the operator to be upgraded on the cluster +} + +type SdkProjectInfo struct { + projectName string + domainName string + group string + version string + kind string +} + +const ( + remoteRegistryRepo = "localhost:5000/" + kindServer = "operator-controller-e2e" + opmPath = "../../bin/opm" + deployedNameSpace = "rukpak-system" +) + +func TestOperatorFramework(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Operator Framework E2E Suite") +} + +var _ = BeforeSuite(func() { + + var err error + cfg = ctrl.GetConfigOrDie() + + scheme := runtime.NewScheme() + + err = catalogd.AddToScheme(scheme) + Expect(err).ToNot(HaveOccurred()) + + err = operatorv1alpha1.AddToScheme(scheme) + Expect(err).To(Not(HaveOccurred())) + + err = rukpakv1alpha1.AddToScheme(scheme) + Expect(err).To(Not(HaveOccurred())) + + c, err = client.New(cfg, client.Options{Scheme: scheme}) + Expect(err).To(Not(HaveOccurred())) + + ctx = context.Background() + +}) + +var _ = Describe("Operator Framework E2E for plain bundles", func() { + var ( + bundleInfo *BundleInfo + catalogDInfo *CatalogDInfo + operatorAction *OperatorActionInfo + operatorCatalog *catalogd.Catalog + operator *operatorv1alpha1.Operator + err error + ) + BeforeEach(func() { + bundleInfo = &BundleInfo{ + baseFolderPath: "../../testdata/bundles/plain-v0", + bundles: []BundleContent{ + { + bInputDir: "plain.v0.1.0", + bundleVersion: "0.1.0", + }, + { + bInputDir: "plain.v0.1.1", + bundleVersion: "0.1.1", + }, + }, + } + catalogDInfo = &CatalogDInfo{ + baseFolderPath: "../../testdata/catalogs", + fbcFileName: "catalog.yaml", + operatorName: "plain", + desiredChannelName: "beta", + } + operatorAction = &OperatorActionInfo{ + installVersion: "0.1.0", + upgradeVersion: "0.1.1", + } + for i, b := range bundleInfo.bundles { + bundleInfo.bundles[i].imageRef = remoteRegistryRepo + catalogDInfo.operatorName + "-bundle:v" + b.bundleVersion + } + catalogDInfo.catalogDir = catalogDInfo.operatorName + "-catalog" + catalogDInfo.imageRef = remoteRegistryRepo + catalogDInfo.catalogDir + ":test" + }) + When("Build and load plain+v0 bundle images into the test environment", func() { + It("Build the plain bundle images and load them", func() { + for _, b := range bundleInfo.bundles { + dockerContext := bundleInfo.baseFolderPath + "/" + b.bInputDir + dockerfilePath := dockerContext + "/Dockerfile" + err = buildPushLoadContainer(b.imageRef, dockerfilePath, dockerContext, kindServer, GinkgoWriter) + Expect(err).To(Not(HaveOccurred())) + } + }) + }) + When("Create the FBC", func() { + It("Create a FBC", func() { + By("Creating FBC for plain bundle using custom routine") + var imageRefs []string + var bundleVersions []string + for _, b := range bundleInfo.bundles { + imageRefs = append(imageRefs, b.imageRef) + bundleVersions = append(bundleVersions, b.bundleVersion) + } + fbc := CreateFBC(catalogDInfo.operatorName, catalogDInfo.desiredChannelName, imageRefs, bundleVersions) + err = WriteFBC(*fbc, catalogDInfo.baseFolderPath+"/"+catalogDInfo.catalogDir, catalogDInfo.fbcFileName) + Expect(err).To(Not(HaveOccurred())) + }) + }) + When("Build and load the FBC image into the test environment", func() { + It("Generate the docker file, build and load FBC image", func() { + By("Calling generate dockerfile function written") + err = generateDockerFile(catalogDInfo.baseFolderPath, catalogDInfo.catalogDir, catalogDInfo.catalogDir+".Dockerfile") + Expect(err).To(Not(HaveOccurred())) + + By("Building the catalog image and loading into the test environment") + dockerContext := catalogDInfo.baseFolderPath + dockerfilePath := dockerContext + "/" + catalogDInfo.catalogDir + ".Dockerfile" + err = buildPushLoadContainer(catalogDInfo.imageRef, dockerfilePath, dockerContext, kindServer, GinkgoWriter) + Expect(err).To(Not(HaveOccurred())) + }) + }) + When("Create a catalog object and check if the resources are created", func() { + It("Create catalog object for the FBC and check if catalog, packages and bundle metadatas are created", func() { + bundleVersions := make([]string, len(bundleInfo.bundles)) + for i, bundle := range bundleInfo.bundles { + bundleVersions[i] = bundle.bundleVersion + } + operatorCatalog, err = createCatalogCheckResources(operatorCatalog, catalogDInfo, bundleVersions) + Expect(err).To(Not(HaveOccurred())) + }) + }) + When("Install an operator and check if the operator operations succeed", func() { + It("Create an operator object and install it", func() { + By("Creating an operator object") + operator, err = createOperator(ctx, catalogDInfo.operatorName, operatorAction.installVersion) + Expect(err).ToNot(HaveOccurred()) + + By("Checking if the operator operations suceceded") + checkOperatorOperationsSuccess(operator, catalogDInfo.operatorName, operatorAction.installVersion, bundleInfo.baseFolderPath) + }) + }) + When("Upgrade an operator to higher version and check if the operator operations succeed", func() { + It("Upgrade to a higher version of the operator", func() { + By("Upgrading the operator") + operator, err = upgradeOperator(ctx, catalogDInfo.operatorName, operatorAction.upgradeVersion) + Expect(err).ToNot(HaveOccurred()) + + By("Checking if the operator operations succeeded") + checkOperatorOperationsSuccess(operator, catalogDInfo.operatorName, operatorAction.upgradeVersion, bundleInfo.baseFolderPath) + }) + }) + When("Delete an operator", func() { + It("Delete an operator", func() { + err = deleteOperator(ctx, catalogDInfo.operatorName) + Expect(err).ToNot(HaveOccurred()) + + By("Verifying the operator doesn't exist") + Eventually(func(g Gomega) { + err = checkOperatorDeleted(catalogDInfo.operatorName) + g.Expect(errors.IsNotFound(err)).To(BeTrue()) + }).Should(Succeed()) + }) + }) + When("Clearing up catalog object and other files formed for the test", func() { + It("Clearing up data generated for the test", func() { + //Deleting the catalog object and checking if the deletion was successful + Eventually(func(g Gomega) { + err = deleteAndCheckCatalogDeleted(operatorCatalog) + g.Expect(errors.IsNotFound(err)).To(BeTrue()) + }).Should(Succeed()) + + var toDelete []string + toDelete = append(toDelete, catalogDInfo.baseFolderPath+"/"+catalogDInfo.catalogDir) // delete the FBC formed + toDelete = append(toDelete, catalogDInfo.baseFolderPath+"/"+catalogDInfo.catalogDir+".Dockerfile") // delete the catalog Dockerfile generated + err = deleteFolderFile(toDelete) + Expect(err).ToNot(HaveOccurred()) + }) + }) +}) + +var _ = Describe("Operator Framework E2E for registry+v1 bundles", func() { + var ( + sdkInfo *SdkProjectInfo + bundleInfo *BundleInfo + catalogDInfo *CatalogDInfo + operatorAction *OperatorActionInfo + operatorCatalog *catalogd.Catalog + operator *operatorv1alpha1.Operator + semverFileName string + err error + ) + BeforeEach(func() { + sdkInfo = &SdkProjectInfo{ + projectName: "example-operator", + domainName: "example.com", + group: "cache", + version: "v1alpha1", + kind: "Memcached1", + } + bundleInfo = &BundleInfo{ + baseFolderPath: "../../testdata/bundles/registry-v1", + bundles: []BundleContent{ + { + bundleVersion: "0.1.0", + }, + { + bundleVersion: "0.1.1", + }, + }, + } + catalogDInfo = &CatalogDInfo{ + baseFolderPath: "../../testdata/catalogs", + fbcFileName: "catalog.yaml", + operatorName: "example-operator", + } + operatorAction = &OperatorActionInfo{ + installVersion: "0.1.0", + upgradeVersion: "0.1.1", + } + for i, b := range bundleInfo.bundles { + bundleInfo.bundles[i].bInputDir = sdkInfo.projectName + ".v" + b.bundleVersion + bundleInfo.bundles[i].imageRef = remoteRegistryRepo + sdkInfo.projectName + "-bundle:v" + b.bundleVersion + } + catalogDInfo.catalogDir = catalogDInfo.operatorName + "-catalog" + catalogDInfo.imageRef = remoteRegistryRepo + catalogDInfo.catalogDir + ":test" + + semverFileName = "registry-semver.yaml" + }) + + When("Build registry+v1 bundles with operator-sdk", func() { + It("Initialize new operator-sdk project and create new api and controller", func() { + err = sdkInitialize(sdkInfo) + Expect(err).NotTo(HaveOccurred()) + }) + It("Generate manifests and CSV for the operator", func() { + err = sdkGenerateManifestsCSV(sdkInfo) + Expect(err).NotTo(HaveOccurred()) + }) + It("Generate and build registry+v1 bundle", func() { + // Creates bundle structure for the specified bundle versions + // Bundle content is same for the bundles now + for _, b := range bundleInfo.bundles { + err = sdkComplete(sdkInfo, bundleInfo.baseFolderPath, b) + Expect(err).NotTo(HaveOccurred()) + } + }) + }) + When("Create FBC and validate FBC", func() { + It("Create a FBC", func() { + sdkCatalogFile := filepath.Join(catalogDInfo.baseFolderPath, catalogDInfo.catalogDir, catalogDInfo.fbcFileName) + By("Forming the semver yaml file") + bundleImageRefs := make([]string, len(bundleInfo.bundles)) + for i, bundle := range bundleInfo.bundles { + bundleImageRefs[i] = bundle.imageRef + } + err := generateOLMSemverFile(semverFileName, bundleImageRefs) + Expect(err).ToNot(HaveOccurred()) + + By("Forming the FBC using semver") + cmd := exec.Command(opmPath, "alpha", "render-template", "semver", semverFileName, "-o", "yaml", "--use-http") + output, err := cmd.CombinedOutput() + Expect(err).ToNot(HaveOccurred()) + + By("Saving the output under catalogs in testdata") + err = os.MkdirAll(filepath.Dir(sdkCatalogFile), os.ModePerm) + Expect(err).ToNot(HaveOccurred()) + + file, err := os.Create(sdkCatalogFile) + Expect(err).ToNot(HaveOccurred()) + defer file.Close() + _, err = file.Write(output) + Expect(err).ToNot(HaveOccurred()) + }) + It("Validate FBC", func() { + By("By validating the FBC using opm validate") + err = validateFBC(catalogDInfo.baseFolderPath + "/" + catalogDInfo.catalogDir) + Expect(err).To(Not(HaveOccurred())) + }) + }) + When("Generate docker file and FBC image and load the FBC image into test environment", func() { + It("Create the docker file", func() { + By("By using opm generate tool") + dockerFolderPath := catalogDInfo.baseFolderPath + "/" + catalogDInfo.catalogDir + cmd := exec.Command(opmPath, "generate", "dockerfile", dockerFolderPath) + err = cmd.Run() + Expect(err).ToNot(HaveOccurred()) + + By("Building the catalog image and loading into the test environment") + dockerContext := catalogDInfo.baseFolderPath + dockerFilePath := dockerContext + "/" + catalogDInfo.catalogDir + ".Dockerfile" + err = buildPushLoadContainer(catalogDInfo.imageRef, dockerFilePath, dockerContext, kindServer, GinkgoWriter) + Expect(err).To(Not(HaveOccurred())) + }) + }) + When("Create a catalog object and check if the resources are created", func() { + It("Create catalog object for the FBC and check if catalog, packages and bundle metadatas are created", func() { + bundleVersions := make([]string, len(bundleInfo.bundles)) + for i, bundle := range bundleInfo.bundles { + bundleVersions[i] = bundle.bundleVersion + } + operatorCatalog, err = createCatalogCheckResources(operatorCatalog, catalogDInfo, bundleVersions) + Expect(err).To(Not(HaveOccurred())) + }) + }) + When("Install an operator and check if the operator operations succeed", func() { + It("Create an operator object and install it", func() { + By("Creating an operator object") + operator, err = createOperator(ctx, catalogDInfo.operatorName, operatorAction.installVersion) + Expect(err).ToNot(HaveOccurred()) + + By("Checking if the operator operations succeeded") + checkOperatorOperationsSuccess(operator, catalogDInfo.operatorName, operatorAction.installVersion, bundleInfo.baseFolderPath) + }) + }) + When("Upgrade an operator to higher version and check if the operator operations succeed", func() { + It("Upgrade to a higher version of the operator", func() { + By("Upgrading the operator") + operator, err = upgradeOperator(ctx, catalogDInfo.operatorName, operatorAction.upgradeVersion) + Expect(err).ToNot(HaveOccurred()) + + By("Checking if the operator operations succeeded") + checkOperatorOperationsSuccess(operator, catalogDInfo.operatorName, operatorAction.upgradeVersion, bundleInfo.baseFolderPath) + }) + }) + When("An operator is deleted", func() { + It("Delete and operator", func() { + err = deleteOperator(ctx, catalogDInfo.operatorName) + Expect(err).ToNot(HaveOccurred()) + + By("Eventually the operator should not exists") + Eventually(func(g Gomega) { + err = checkOperatorDeleted(catalogDInfo.operatorName) + g.Expect(errors.IsNotFound(err)).To(BeTrue()) + }).Should(Succeed()) + }) + }) + When("Clearing up catalog object and other files formed for the test", func() { + It("Clearing up data generated for the test", func() { + //Deleting the catalog object and checking if the deletion was successful + Eventually(func(g Gomega) { + err = deleteAndCheckCatalogDeleted(operatorCatalog) + g.Expect(errors.IsNotFound(err)).To(BeTrue()) + }).Should(Succeed()) + + var toDelete []string + for _, b := range bundleInfo.bundles { + toDelete = append(toDelete, bundleInfo.baseFolderPath+"/"+b.bInputDir) // delete the registry+v1 bundles formed + } + toDelete = append(toDelete, sdkInfo.projectName) //delete the sdk project directory + toDelete = append(toDelete, semverFileName) // delete the semver yaml formed + toDelete = append(toDelete, catalogDInfo.baseFolderPath+"/"+catalogDInfo.catalogDir) // delete the FBC formed + toDelete = append(toDelete, catalogDInfo.baseFolderPath+"/"+catalogDInfo.catalogDir+".Dockerfile") // delete the catalog Dockerfile generated + err = deleteFolderFile(toDelete) + Expect(err).ToNot(HaveOccurred()) + }) + }) +}) + +func sdkInitialize(sdkInfo *SdkProjectInfo) error { + // Create new project for the operator + err := os.Mkdir(sdkInfo.projectName, 0755) + if err != nil { + return fmt.Errorf("Error creating the sdk project %v:%v", sdkInfo.projectName, err) + } + + // Initialize the operator-sdk project + domain := "--domain=" + sdkInfo.domainName + cmd := exec.Command("operator-sdk", "init", domain) + cmd.Dir = sdkInfo.projectName + err = cmd.Run() + if err != nil { + return fmt.Errorf("Error initializing the operator-sdk project %v:%v", sdkInfo.projectName, err) + } + + // Create new API and controller + group := "--group=" + sdkInfo.group + version := "--version=" + sdkInfo.version + kind := "--kind=" + sdkInfo.kind + cmd = exec.Command("operator-sdk", "create", "api", group, version, kind, "--resource", "--controller") + cmd.Dir = sdkInfo.projectName + err = cmd.Run() + if err != nil { + return fmt.Errorf("Error creating new API and controller for the operator-sdk project %v:%v", sdkInfo.projectName, err) + } + + // Checking if the API was created in the expected path + apiFilePath := filepath.Join(sdkInfo.projectName, "api", sdkInfo.version, strings.ToLower(sdkInfo.kind)+"_types.go") + Expect(apiFilePath).To(BeAnExistingFile()) + + // Checking if the controller was created in the expected path") + controllerFilePath := filepath.Join(sdkInfo.projectName, "controllers", strings.ToLower(sdkInfo.kind)+"_controller.go") + Expect(controllerFilePath).To(BeAnExistingFile()) + + return nil +} + +func sdkGenerateManifestsCSV(sdkInfo *SdkProjectInfo) error { + // Update the generated code for the resources + cmd := exec.Command("make", "generate") + cmd.Dir = sdkInfo.projectName + err := cmd.Run() + if err != nil { + return fmt.Errorf("Error updating generated code for the operator-sdk project %v:%v", sdkInfo.projectName, err) + } + + // Generate and update the CRD manifests + cmd = exec.Command("make", "manifests") + cmd.Dir = sdkInfo.projectName + err = cmd.Run() + if err != nil { + return fmt.Errorf("Error generating and updating crd manifests for the operator-sdk project %v:%v", sdkInfo.projectName, err) + } + + // Checking if CRD manifests are generated + crdFilePath := filepath.Join(sdkInfo.projectName, "config", "crd", "bases", sdkInfo.group+"."+sdkInfo.domainName+"_"+strings.ToLower(sdkInfo.kind)+"s.yaml") + Expect(crdFilePath).To(BeAnExistingFile()) + + // Generate CSV for the bundle with default values + cmd = exec.Command("operator-sdk", "generate", "kustomize", "manifests", "--interactive=false") + cmd.Dir = sdkInfo.projectName + err = cmd.Run() + if err != nil { + return fmt.Errorf("Error generating CSV for the operator-sdk project %v:%v", sdkInfo.projectName, err) + } + + // Checking if CRD manifests are generated + csvFilePath := filepath.Join(sdkInfo.projectName, "config", "manifests", "bases", sdkInfo.projectName+".clusterserviceversion.yaml") + Expect(csvFilePath).To(BeAnExistingFile()) + + return nil +} + +func sdkComplete(sdkInfo *SdkProjectInfo, rootBundlePath string, bundleData BundleContent) error { + // Copy CRDs and other supported kinds, generate metadata, and in bundle format + bundleGenFlags := "BUNDLE_GEN_FLAGS=-q --overwrite=false --version " + bundleData.bundleVersion + " $(BUNDLE_METADATA_OPTS)" + cmd := exec.Command("make", "bundle", bundleGenFlags) + cmd.Dir = sdkInfo.projectName + err := cmd.Run() + if err != nil { + return fmt.Errorf("Error generating bundle format for the bundle %v:%v", bundleData.bInputDir, err) + } + + // Check if bundle manifests are created + bundleManifestPath := filepath.Join(sdkInfo.projectName, "bundle", "manifests") + Expect(bundleManifestPath).To(BeAnExistingFile()) + + // Check if bundle metadata is created + bundleMetadataPath := filepath.Join(sdkInfo.projectName, "bundle", "metadata") + Expect(bundleMetadataPath).To(BeAnExistingFile()) + + // Build the bundle image + bundleImg := "BUNDLE_IMG=" + bundleData.imageRef + cmd = exec.Command("make", "bundle-build", bundleImg) + cmd.Dir = sdkInfo.projectName + err = cmd.Run() + if err != nil { + return fmt.Errorf("Error building bundle image %v with tag %v :%v", bundleData.imageRef, bundleData.bundleVersion, err) + } + + // Push the bundle image + cmd = exec.Command("make", "bundle-push", bundleImg) + cmd.Dir = sdkInfo.projectName + err = cmd.Run() + if err != nil { + return fmt.Errorf("Error pushing bundle image %v with tag %v :%v", bundleData.imageRef, bundleData.bundleVersion, err) + } + + // Load the bundle image into test environment + err = loadImages(GinkgoWriter, kindServer, bundleData.imageRef) + if err != nil { + return err + } + + // Move the bundle structure into correct testdata folder for bundles + err = moveFolderContents(sdkInfo.projectName+"/"+"bundle", rootBundlePath+"/"+bundleData.bInputDir) + Expect(err).NotTo(HaveOccurred()) + Expect(rootBundlePath + "/" + bundleData.bInputDir).To(BeAnExistingFile()) + + // Move the generated dockerfile to correct path + err = os.Rename(sdkInfo.projectName+"/"+"bundle.Dockerfile", rootBundlePath+"/"+bundleData.bInputDir+"/"+"bundle.Dockerfile") + Expect(err).NotTo(HaveOccurred()) + + return nil +} + +// buildPushLoadContainer function builds a Docker container image using the Docker +// command-line tool, pushes to a container registry and loads into a kind cluster. +// +// The function takes the following arguments and returns back the error if any: +// `tag`: container image tag/name. +// `dockerfilePath`: path to the Dockerfile that defines the container image. +// `dockerContext`: context directory containing the files and resources referenced by the Dockerfile. +// `w`: Writer to which the standard output and standard error will be redirected. +func buildPushLoadContainer(tag, dockerfilePath, dockerContext, kindServer string, w io.Writer) error { + cmd := exec.Command("docker", "build", "-t", tag, "-f", dockerfilePath, dockerContext) + cmd.Stderr = w + cmd.Stdout = w + err := cmd.Run() + if err != nil { + return fmt.Errorf("Error building Docker container image %s : %v", tag, err) + } + + cmd = exec.Command("docker", "push", tag) + cmd.Stderr = w + cmd.Stdout = w + err = cmd.Run() + if err != nil { + return fmt.Errorf("Error pushing Docker container image: %s to the registry: %v", tag, err) + } + + err = loadImages(w, kindServer, tag) + return err +} + +// loadImages loads container images into a Kubernetes kind cluster +// +// The function takes the `Writer` to which the standard output and standard error will be redirected, +// the kind cluster to which the image is to be loaded, the container image to be loaded. +// +// and returns back the error if any +func loadImages(w io.Writer, kindServerName string, images ...string) error { + for _, image := range images { + cmd := exec.Command("kind", "load", "docker-image", image, "--name", kindServerName) + cmd.Stderr = w + cmd.Stdout = w + err := cmd.Run() + if err != nil { + return fmt.Errorf("Error loading the container image %s into the cluster %s : %v", image, kindServerName, err) + } + } + return nil +} + +// Validates the FBC using opm tool +func validateFBC(fbcDirPath string) error { + cmd := exec.Command(opmPath, "validate", fbcDirPath) + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("FBC validation failed: %s", output) + } + return nil +} + +// Creates catalog instance +func createTestCatalog(ctx context.Context, name, imageRef string) (*catalogd.Catalog, error) { + catalog := &catalogd.Catalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: catalogd.CatalogSpec{ + Source: catalogd.CatalogSource{ + Type: catalogd.SourceTypeImage, + Image: &catalogd.ImageSource{ + Ref: imageRef, + }, + }, + }, + } + + err := c.Create(ctx, catalog) + return catalog, err +} + +// Creates the operator opName for the version +func createOperator(ctx context.Context, opName, version string) (*operatorv1alpha1.Operator, error) { + operator := &operatorv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{ + Name: opName, + }, + Spec: operatorv1alpha1.OperatorSpec{ + PackageName: opName, + Version: version, + }, + } + + err := c.Create(ctx, operator) + return operator, err +} + +// Upgrades the operator opName for the version +func upgradeOperator(ctx context.Context, opName, version string) (*operatorv1alpha1.Operator, error) { + operator := &operatorv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{ + Name: opName, + }, + } + err := c.Get(ctx, types.NamespacedName{Name: opName}, operator) + if err != nil { + return nil, err + } + operator.Spec.PackageName = opName + operator.Spec.Version = version + + err = c.Update(ctx, operator) + return operator, err +} + +// Deletes the operator opName +func deleteOperator(ctx context.Context, opName string) error { + operator := &operatorv1alpha1.Operator{} + err := c.Get(ctx, types.NamespacedName{Name: opName}, operator) + if err != nil { + return fmt.Errorf("Error deleting the operator %v for the version %v : %v", opName, operator.Spec.Version, err) + } + + err = c.Delete(ctx, operator) + return err +} + +// Checks if the expected condition and actual condition for a resource matches +func checkConditionEquals(actualCond, expectedCond *metav1.Condition) error { + if actualCond == nil { + return fmt.Errorf("Expected condition %s to not be nil", expectedCond.Type) + } + if actualCond.Status != expectedCond.Status { + return fmt.Errorf("Expected status: %s, but got: %s", expectedCond.Status, actualCond.Status) + } + if actualCond.Reason != expectedCond.Reason { + return fmt.Errorf("Expected reason: %s but got: %s", expectedCond.Reason, actualCond.Reason) + } + if !strings.Contains(actualCond.Message, expectedCond.Message) { + return fmt.Errorf("Expected message: %s but got: %s", expectedCond.Message, actualCond.Message) + } + return nil +} + +// Checks if the catalog resource is successfully unpacked +func checkCatalogUnpacked(operatorCatalog *catalogd.Catalog) error { + err := c.Get(ctx, types.NamespacedName{Name: operatorCatalog.Name}, operatorCatalog) + if err != nil { + return fmt.Errorf("Error retrieving catalog %v:%v", operatorCatalog.Name, err) + } + + cond := apimeta.FindStatusCondition(operatorCatalog.Status.Conditions, catalogd.TypeUnpacked) + expectedCond := &metav1.Condition{ + Type: catalogd.TypeUnpacked, + Status: metav1.ConditionTrue, + Reason: catalogd.ReasonUnpackSuccessful, + Message: "successfully unpacked the catalog image", + } + err = checkConditionEquals(cond, expectedCond) + if err != nil { + return fmt.Errorf("Status conditions for the catalog instance %v is not as expected:%v", operatorCatalog.Name, err) + } + return nil +} + +// Creates catalog instance and check if catalog unpackging is successul and if the packages and bundle metadatas are formed +func createCatalogCheckResources(operatorCatalog *catalogd.Catalog, catalogDInfo *CatalogDInfo, bundleVersions []string) (*catalogd.Catalog, error) { + operatorCatalog, err := createTestCatalog(ctx, catalogDInfo.catalogDir, catalogDInfo.imageRef) + if err != nil { + return nil, fmt.Errorf("Error creating catalog %v : %v", catalogDInfo.catalogDir, err) + } + + // checking if catalog unpacking is successful + Eventually(func(g Gomega) { + err = checkCatalogUnpacked(operatorCatalog) + g.Expect(err).ToNot(HaveOccurred()) + }, 20*time.Second, 1).Should(Succeed()) + + // checking if the packages are created + Eventually(func(g Gomega) { + err = checkPackageCreated(operatorCatalog, catalogDInfo.operatorName) + g.Expect(err).ToNot(HaveOccurred()) + }, 20*time.Second, 1).Should(Succeed()) + + // checking if the bundle metadatas are created + By("Eventually checking if bundle metadata is created") + Eventually(func(g Gomega) { + err = checkBundleMetadataCreated(operatorCatalog, catalogDInfo.operatorName, bundleVersions) + g.Expect(err).ToNot(HaveOccurred()) + }).Should(Succeed()) + return operatorCatalog, nil +} + +// Checks if the operator operator succeeds following operator install or upgrade +func checkOperatorOperationsSuccess(operator *operatorv1alpha1.Operator, pkgName, opVersion, bundlePath string) { + // checking for a successful resolution and bundle path + Eventually(func(g Gomega) { + err := checkResolutionAndBundlePath(operator) + g.Expect(err).ToNot(HaveOccurred()) + }, 15*time.Second, 1).Should(Succeed()) + + // checking for a successful operator installation + Eventually(func(g Gomega) { + err := checkOperatorInstalled(operator, opVersion) + g.Expect(err).ToNot(HaveOccurred()) + }, 15*time.Second, 1).Should(Succeed()) + + // checking for a successful package installation + Eventually(func(g Gomega) { + err := checkPackageInstalled(operator) + g.Expect(err).ToNot(HaveOccurred()) + }, 15*time.Second, 1).Should(Succeed()) + + // verifying the presence of relevant manifest from the bundle on cluster + Eventually(func(g Gomega) { + err := checkManifestPresence(bundlePath, pkgName, opVersion) + g.Expect(err).ToNot(HaveOccurred()) + }).Should(Succeed()) +} + +// Checks if the packages are created from the catalog. +// The expected pkgName is taken as input and is compared against the packages collected whose catalog name +// matches the catalog under consideration. +func checkPackageCreated(operatorCatalog *catalogd.Catalog, pkgName string) error { + var pkgCollected string + pList := &catalogd.PackageList{} + err := c.List(ctx, pList) + if err != nil { + return fmt.Errorf("Error retrieving the packages after %v catalog instance creation: %v", operatorCatalog.Name, err) + } + for _, pack := range pList.Items { + if pack.Spec.Catalog.Name == operatorCatalog.Name { + pkgCollected = pack.Spec.Name + } + } + if pkgCollected != pkgName { + return fmt.Errorf("Package %v for the catalog %v is not created", pkgName, operatorCatalog.Name) + } + return nil +} + +// Checks if the bundle metadatas are created from the catalog. +// The expected pkgNames and their versions are taken as input. This is then compared against the collected bundle versions. +// The collected bundle versions are formed by reading the version from "olm.package" property type whose catalog name +// matches the catalog name and pkgName matches the pkgName under consideration. +func checkBundleMetadataCreated(operatorCatalog *catalogd.Catalog, pkgName string, versions []string) error { + type Package struct { + PackageName string `json:"packageName"` + Version string `json:"version"` + } + var pkgValue Package + collectedBundleVersions := make([]string, 0) + bmList := &catalogd.BundleMetadataList{} + err := c.List(ctx, bmList) + if err != nil { + return fmt.Errorf("Error retrieving the bundle metadata after %v catalog instance creation: %v", operatorCatalog.Name, err) + } + + for _, bm := range bmList.Items { + if bm.Spec.Catalog.Name == operatorCatalog.Name { + for _, prop := range bm.Spec.Properties { + if prop.Type == "olm.package" { + err := json.Unmarshal(prop.Value, &pkgValue) + if err == nil && pkgValue.PackageName == pkgName { + collectedBundleVersions = append(collectedBundleVersions, pkgValue.Version) + } + } + } + } + } + if !reflect.DeepEqual(collectedBundleVersions, versions) { + return fmt.Errorf("Package %v for the catalog %v is not created", pkgName, operatorCatalog.Name) + } + + return nil +} + +// Checks for a successful resolution and bundle path for the operator +func checkResolutionAndBundlePath(operator *operatorv1alpha1.Operator) error { + err := c.Get(ctx, types.NamespacedName{Name: operator.Name}, operator) + if err != nil { + return fmt.Errorf("Error retrieving operator %v:%v", operator.Name, err) + } + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeResolved) + expectedCond := &metav1.Condition{ + Type: operatorv1alpha1.TypeResolved, + Status: metav1.ConditionTrue, + Reason: operatorv1alpha1.ReasonSuccess, + Message: "resolved to", + } + err = checkConditionEquals(cond, expectedCond) + if err != nil { + return fmt.Errorf("Status conditions for the operator %v for the version %v is not as expected:%v", operator.Name, operator.Spec.Version, err) + } + if operator.Status.ResolvedBundleResource == "" { + return fmt.Errorf("Resoved Bundle Resource is not found for the operator %v for the version %v", operator.Name, operator.Spec.Version) + } + return nil +} + +// Checks if the operator installation succeeded +func checkOperatorInstalled(operator *operatorv1alpha1.Operator, operatorVersion string) error { + err := c.Get(ctx, types.NamespacedName{Name: operator.Name}, operator) + if err != nil { + return fmt.Errorf("Error retrieving operator %v:%v", operator.Name, err) + } + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeInstalled) + expectedCond := &metav1.Condition{ + Type: operatorv1alpha1.TypeResolved, + Status: metav1.ConditionTrue, + Reason: operatorv1alpha1.ReasonSuccess, + Message: "installed from", + } + err = checkConditionEquals(cond, expectedCond) + if err != nil { + return fmt.Errorf("Status conditions for the operator %v for the version %v is not as expected:%v", operator.Name, operator.Spec.Version, err) + } + if operator.Status.InstalledBundleResource == "" { + return fmt.Errorf("Installed Bundle Resource is not found for the operator %v for the version %v", operator.Name, operator.Spec.Version) + } + if operator.Spec.Version != operatorVersion { + return fmt.Errorf("Expected operator version: %s for the operator %v, but got: %s", operator.Spec.Version, operator.Name, operatorVersion) + } + return nil +} + +// Checks if bundle deployment succeeded +func checkPackageInstalled(operator *operatorv1alpha1.Operator) error { + bd := rukpakv1alpha1.BundleDeployment{} + err := c.Get(ctx, types.NamespacedName{Name: operator.Name}, &bd) + if err != nil { + return fmt.Errorf("Error retrieving the bundle deployments for the operator %v:%v", operator.Name, err) + } + if len(bd.Status.Conditions) != 2 { + return fmt.Errorf("Two conditions for successful unpack and successful installation for the operater %v for version %v are not populated", operator.Name, operator.Spec.Version) + } + if bd.Status.Conditions[0].Reason != "UnpackSuccessful" { + return fmt.Errorf("Expected status condition reason for successful unpack is not populated for the operater %v for version %v are not populated", operator.Name, operator.Spec.Version) + } + if bd.Status.Conditions[1].Reason != "InstallationSucceeded" { + return fmt.Errorf("Expected status condition reason for successful installation is not populated for the operater %v for version %v are not populated", operator.Name, operator.Spec.Version) + } + return nil +} + +// Checks the presence of operator manifests for the operator +func checkManifestPresence(bundlePath, operatorName, version string) error { + resources, err := collectKubernetesObjects(bundlePath, operatorName, version) + if err != nil { + return err + } + for _, resource := range resources { + if resource.Kind == "ClusterServiceVersion" { + continue + } + gvk := schema.GroupVersionKind{ + Group: "", + Version: resource.APIVersion, + Kind: resource.Kind, + } + + obj := &unstructured.Unstructured{} + obj.SetGroupVersionKind(gvk) + err = c.Get(ctx, types.NamespacedName{Name: resource.Metadata.Name, Namespace: deployedNameSpace}, obj) + if err != nil { + return fmt.Errorf("Error retrieving the resources %v from the namespace %v: %v", resource.Metadata.Name, deployedNameSpace, err) + } + } + return nil +} + +// Checks if the operator was successfully deleted +func checkOperatorDeleted(opName string) error { + err := c.Get(ctx, types.NamespacedName{Name: opName}, &operatorv1alpha1.Operator{}) + return err +} + +// Deletes the catalog and checks if the deletion was successful +func deleteAndCheckCatalogDeleted(catalog *catalogd.Catalog) error { + err := c.Delete(ctx, catalog) + if err != nil { + return fmt.Errorf("Error deleting the catalog instance: %v", err) + } + err = c.Get(ctx, types.NamespacedName{Name: catalog.Name}, &catalogd.Catalog{}) + return err +} + +// Moves the content from currentPath to newPath +func moveFolderContents(currentPath, newPath string) error { + files, err := os.ReadDir(currentPath) + if err != nil { + return fmt.Errorf("Failed to read the folder %s: %v", currentPath, err) + } + + for _, file := range files { + oldPath := filepath.Join(currentPath, file.Name()) + newFilePath := filepath.Join(newPath, file.Name()) + + err = os.MkdirAll(filepath.Dir(newFilePath), os.ModePerm) + if err != nil { + return fmt.Errorf("Failed to create directory for file %s: %v", file.Name(), err) + } + + err = os.Rename(oldPath, newFilePath) + if err != nil { + return fmt.Errorf("Failed to move file %s: %v", file.Name(), err) + } + } + + return nil +} + +// Delete the folders or file in the collection array +func deleteFolderFile(collection []string) error { + for _, c := range collection { + err := os.RemoveAll(c) + if err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("Error deleting %v:%v", c, err) + } + } + } + return nil +} diff --git a/test/operator-e2e/read_manifests.go b/test/operator-framework-e2e/read_manifests.go similarity index 91% rename from test/operator-e2e/read_manifests.go rename to test/operator-framework-e2e/read_manifests.go index e5c6d4f1f..9a5df09a2 100644 --- a/test/operator-e2e/read_manifests.go +++ b/test/operator-framework-e2e/read_manifests.go @@ -9,8 +9,6 @@ import ( "sigs.k8s.io/yaml" ) -const bundlePath = "bundles/plain-v0" - type Object struct { Kind string `yaml:"kind"` APIVersion string `yaml:"apiVersion"` @@ -20,7 +18,7 @@ type Object struct { } // collects the Kubernetes objects present in the bundle manifest folder for a particular package and its version -func collectKubernetesObjects(packageName, version string) ([]Object, error) { +func collectKubernetesObjects(bundlePath, packageName, version string) ([]Object, error) { objects := []Object{} bundleManifestPath := filepath.Join(bundlePath, packageName+".v"+version, "manifests")