From fbffa1dcacf33e0e02ba48b161ad2a30a7887104 Mon Sep 17 00:00:00 2001 From: kevinrizza Date: Thu, 21 May 2020 12:15:53 -0400 Subject: [PATCH 1/2] Remove registry dependency * Remove all references to operator-framework/operator-registry * Update the type serialization and validation to use a new external api type for operator bundle, which now explicitly parses the public CRD and CSV types * Redefine the serialization functions to simply provide the types without explicitly running validation against them --- cmd/operator-verify/manifests/cmd.go | 7 +- go.mod | 24 +- go.sum | 365 +----------------- pkg/internal/bundle.go | 139 ------- pkg/manifests/bundle.go | 22 ++ pkg/manifests/bundleloader.go | 177 +++++++++ pkg/manifests/bundlemeta.go | 37 ++ pkg/manifests/directory.go | 42 +- pkg/manifests/directory_test.go | 31 ++ pkg/manifests/packagemanifest.go | 32 ++ pkg/manifests/packagemanifestloader.go | 132 +++++++ ...dbackups.etcd.database.coreos.com.crd.yaml | 13 + ...clusters.etcd.database.coreos.com.crd.yaml | 16 + ...operator.v0.9.4.clusterserviceversion.yaml | 309 +++++++++++++++ ...restores.etcd.database.coreos.com.crd.yaml | 13 + ...dbackups.etcd.database.coreos.com.crd.yaml | 13 + ...clusters.etcd.database.coreos.com.crd.yaml | 16 + ...operator.v0.9.2.clusterserviceversion.yaml | 305 +++++++++++++++ ...restores.etcd.database.coreos.com.crd.yaml | 13 + ...dbackups.etcd.database.coreos.com.crd.yaml | 13 + ...clusters.etcd.database.coreos.com.crd.yaml | 16 + ...operator.v0.9.4.clusterserviceversion.yaml | 309 +++++++++++++++ ...restores.etcd.database.coreos.com.crd.yaml | 13 + .../testdata/valid_package/package.yaml | 5 + pkg/validation/doc.go | 2 +- pkg/validation/errors/error.go | 4 +- pkg/validation/internal/bundle.go | 66 ++++ pkg/validation/internal/bundle_test.go | 51 +++ pkg/validation/internal/csv.go | 25 -- pkg/validation/internal/csv_test.go | 14 +- pkg/validation/internal/manifests.go | 206 ---------- pkg/validation/internal/package_manifest.go | 9 +- .../internal/package_manifest_test.go | 30 +- .../internal/testdata/noInstallMode.csv.yaml | 283 ++++++++++++++ ...dbackups.etcd.database.coreos.com.crd.yaml | 13 + ...operator.v0.9.4.clusterserviceversion.yaml | 309 +++++++++++++++ ...restores.etcd.database.coreos.com.crd.yaml | 13 + ...dbackups.etcd.database.coreos.com.crd.yaml | 13 + ...clusters.etcd.database.coreos.com.crd.yaml | 16 + ...operator.v0.9.2.clusterserviceversion.yaml | 305 +++++++++++++++ ...restores.etcd.database.coreos.com.crd.yaml | 13 + ...dbackups.etcd.database.coreos.com.crd.yaml | 13 + ...clusters.etcd.database.coreos.com.crd.yaml | 16 + ...operator.v0.9.4.clusterserviceversion.yaml | 309 +++++++++++++++ ...restores.etcd.database.coreos.com.crd.yaml | 13 + .../testdata/invalid_package/package.yaml | 4 + ...dbackups.etcd.database.coreos.com.crd.yaml | 13 + ...clusters.etcd.database.coreos.com.crd.yaml | 16 + ...operator.v0.9.4.clusterserviceversion.yaml | 309 +++++++++++++++ ...restores.etcd.database.coreos.com.crd.yaml | 13 + ...dbackups.etcd.database.coreos.com.crd.yaml | 13 + ...clusters.etcd.database.coreos.com.crd.yaml | 16 + ...operator.v0.9.2.clusterserviceversion.yaml | 305 +++++++++++++++ ...restores.etcd.database.coreos.com.crd.yaml | 13 + ...dbackups.etcd.database.coreos.com.crd.yaml | 13 + ...clusters.etcd.database.coreos.com.crd.yaml | 16 + ...operator.v0.9.4.clusterserviceversion.yaml | 309 +++++++++++++++ ...restores.etcd.database.coreos.com.crd.yaml | 13 + .../testdata/valid_package/package.yaml | 5 + pkg/validation/validation.go | 7 +- pkg/validation/validation_test.go | 61 +++ vendor/modules.txt | 6 - 62 files changed, 4115 insertions(+), 802 deletions(-) delete mode 100644 pkg/internal/bundle.go create mode 100644 pkg/manifests/bundle.go create mode 100644 pkg/manifests/bundleloader.go create mode 100644 pkg/manifests/bundlemeta.go create mode 100644 pkg/manifests/directory_test.go create mode 100644 pkg/manifests/packagemanifest.go create mode 100644 pkg/manifests/packagemanifestloader.go create mode 100644 pkg/manifests/testdata/valid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/manifests/testdata/valid_bundle/etcdclusters.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/manifests/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml create mode 100644 pkg/manifests/testdata/valid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/manifests/testdata/valid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/manifests/testdata/valid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/manifests/testdata/valid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml create mode 100644 pkg/manifests/testdata/valid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/manifests/testdata/valid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/manifests/testdata/valid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/manifests/testdata/valid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml create mode 100644 pkg/manifests/testdata/valid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/manifests/testdata/valid_package/package.yaml create mode 100644 pkg/validation/internal/bundle.go create mode 100644 pkg/validation/internal/bundle_test.go delete mode 100644 pkg/validation/internal/manifests.go create mode 100644 pkg/validation/internal/testdata/noInstallMode.csv.yaml create mode 100644 pkg/validation/testdata/invalid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/invalid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml create mode 100644 pkg/validation/testdata/invalid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/invalid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/invalid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/invalid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml create mode 100644 pkg/validation/testdata/invalid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/invalid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/invalid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/invalid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml create mode 100644 pkg/validation/testdata/invalid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/invalid_package/package.yaml create mode 100644 pkg/validation/testdata/valid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/valid_bundle/etcdclusters.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml create mode 100644 pkg/validation/testdata/valid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/valid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/valid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/valid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml create mode 100644 pkg/validation/testdata/valid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/valid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/valid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/valid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml create mode 100644 pkg/validation/testdata/valid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml create mode 100644 pkg/validation/testdata/valid_package/package.yaml create mode 100644 pkg/validation/validation_test.go diff --git a/cmd/operator-verify/manifests/cmd.go b/cmd/operator-verify/manifests/cmd.go index eccdd0970..afe594645 100644 --- a/cmd/operator-verify/manifests/cmd.go +++ b/cmd/operator-verify/manifests/cmd.go @@ -5,6 +5,7 @@ import ( "os" "github.com/operator-framework/api/pkg/manifests" + "github.com/operator-framework/api/pkg/validation" "github.com/operator-framework/api/pkg/validation/errors" log "github.com/sirupsen/logrus" @@ -24,7 +25,11 @@ validation library.`, if len(args) != 1 { log.Fatalf("command %s requires exactly one argument", cmd.CommandPath()) } - _, _, results := manifests.GetManifestsDir(args[0]) + bundle, err := manifests.GetBundleFromDir(args[0]) + if err != nil { + log.Fatalf("Error generating bundle from directory %s", err.Error()) + } + results := validation.AllValidators.Validate(bundle) nonEmptyResults := []errors.ManifestResult{} for _, result := range results { if result.HasError() || result.HasWarn() { diff --git a/go.mod b/go.mod index 92f529c57..b9f195884 100644 --- a/go.mod +++ b/go.mod @@ -3,31 +3,27 @@ module github.com/operator-framework/api go 1.13 require ( - github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect - github.com/bitly/go-simplejson v0.5.0 // indirect github.com/blang/semver v3.5.0+incompatible - github.com/bshuster-repo/logrus-logstash-hook v0.4.1 // indirect - github.com/bugsnag/bugsnag-go v1.5.3 // indirect - github.com/bugsnag/panicwrap v1.2.0 // indirect - github.com/garyburd/redigo v1.6.0 // indirect github.com/ghodss/yaml v1.0.0 github.com/go-bindata/go-bindata/v3 v3.1.3 - github.com/gofrs/uuid v3.2.0+incompatible // indirect - github.com/gorilla/handlers v1.4.2 // indirect + github.com/google/go-cmp v0.4.0 // indirect + github.com/imdario/mergo v0.3.8 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/mikefarah/yq/v2 v2.4.1 - github.com/operator-framework/operator-registry v1.12.1 - github.com/pkg/errors v0.9.1 + github.com/onsi/ginkgo v1.12.0 // indirect + github.com/onsi/gomega v1.9.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/client_golang v1.1.0 // indirect + github.com/prometheus/procfs v0.0.5 // indirect github.com/sirupsen/logrus v1.4.2 github.com/spf13/cobra v0.0.6 github.com/stretchr/testify v1.5.1 - github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 // indirect - github.com/yvasiyarov/gorelic v0.0.7 // indirect - github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9 // indirect + golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271 // indirect + golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 // indirect k8s.io/api v0.18.2 k8s.io/apiextensions-apiserver v0.18.2 k8s.io/apimachinery v0.18.2 k8s.io/client-go v0.18.2 - rsc.io/letsencrypt v0.0.3 // indirect sigs.k8s.io/controller-runtime v0.6.0 sigs.k8s.io/controller-tools v0.3.0 ) diff --git a/go.sum b/go.sum index 1fdbe8c07..6d37c24a8 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,5 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -bou.ke/monkey v1.0.1 h1:zEMLInw9xvNakzUUPjfS4Ds6jYPqCFx3m7bRmG5NH2U= -bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= @@ -16,15 +12,8 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 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/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZpg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0= 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/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -33,72 +22,29 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= 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/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6 h1:uZuxRZCz65cG1o6K/xUqImNcYKtmk9ylqaH0itMSvzA= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= -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/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= -github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/bugsnag/bugsnag-go v1.5.3 h1:yeRUT3mUE13jL1tGwvoQsKdVbAsQx9AJ+fqahKveP04= -github.com/bugsnag/bugsnag-go v1.5.3/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA= -github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2 h1:ForxmXkA6tPIvffbrDAcPUIB32QgXkt2XFj+F0UxetA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c h1:8ahmSVELW1wghbjerVAyuEYD5+Dio66RYvSS0iGfL1M= -github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de h1:dlfGmNcE3jDAecLqwKPMNX6nk2qh1c1Vg1/YTzpOOF4= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd h1:JNn81o/xG+8NEo3bC/vx9pbi/g2WI8mtP2/nXzu297Y= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= @@ -106,81 +52,41 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= -github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= -github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= -github.com/cznic/internal v0.0.0-20180608152220-f44710a21d00/go.mod h1:olo7eAdKwJdXxb55TKGLiJ6xt1H0/tiiRCWKVLmtjY4= -github.com/cznic/lldb v1.1.0/go.mod h1:FIZVUmYUVhPwRiPzL8nD/mpFcJ/G7SSXjjXYG4uRI3A= -github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= -github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE= -github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= -github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= -github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8= -github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= -github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= -github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492 h1:FwssHbCDJD025h+BchanCwE1Q8fyMgqDr2mOQAWOLGw= -github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce h1:KXS1Jg+ddGcWA8e1N7cupxaHHZhit5rB9tfDU+mfjyY= -github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= -github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= -github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= -github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc= -github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= 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= @@ -259,26 +165,15 @@ github.com/go-openapi/validate v0.19.2 h1:ky5l57HjyVRrsJfd2+Ro5Z9PjGuKbsmftwyMtk github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5 h1:QhCBKRYqZR+SKo4gl1lPhPahope8/RLt6EVgY8X80w0= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/flect v0.2.0 h1:EWCvMGGxOjsgwlWaP+f4+Hh6yrrte7JeFL2S6b+0hdM= github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= -github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k= -github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8= @@ -287,7 +182,6 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -295,12 +189,6 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= -github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8= -github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -308,9 +196,6 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= @@ -324,35 +209,18 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= -github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= -github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -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.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= -github.com/gorilla/mux v1.7.4/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/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 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 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= 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-health-probe v0.2.1-0.20181220223928-2bf0a5b182db/go.mod h1:uBKkC2RbarFsvS5jMJHpVhTLvGlGQj9JJwkaePE3FWI= -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 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -362,18 +230,11 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= -github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -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/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/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= @@ -382,8 +243,6 @@ github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46O github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -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/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0 h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -399,10 +258,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= @@ -421,159 +276,91 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= -github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/mikefarah/yaml/v2 v2.4.0 h1:eYqfooY0BnvKTJxr7+ABJs13n3dg9n347GScDaU2Lww= github.com/mikefarah/yaml/v2 v2.4.0/go.mod h1:ahVqZF4n1W4NqwvVnZzC4es67xsW9uR/RRf2RRxieJU= github.com/mikefarah/yq/v2 v2.4.1 h1:tajDonaFK6WqitSZExB6fKlWQy/yCkptqxh2AXEe3N4= github.com/mikefarah/yq/v2 v2.4.1/go.mod h1:i8SYf1XdgUvY2OFwSqGAtWOOgimD2McJ6iutoxRm4k0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 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= -github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34= github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 h1:yN8BPXVwMBAm3Cuvh1L5XE8XpvYRMdsVLd82ILprhUU= -github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7 h1:Dliu5QO+4JYWu/yMshaMU7G3JN2POGpwjJN7gjy10Go= -github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7/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/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/operator-framework/api v0.1.1/go.mod h1:yzNYR7qyJqRGOOp+bT6Z/iYSbSPNxeh3Si93Gx/3OBY= -github.com/operator-framework/operator-registry v1.5.3 h1:az83WDwgB+tHsmVn+tFq72yQBbaUAye8e4+KkDQmzLs= -github.com/operator-framework/operator-registry v1.5.3/go.mod h1:agrQlkWOo1q8U1SAaLSS2WQ+Z9vswNT2M2HFib9iuLY= -github.com/operator-framework/operator-registry v1.12.1 h1:JWk8s6LPwyJ16qQzOhALS0hycmmzUGteGQSCbfsPeBY= -github.com/operator-framework/operator-registry v1.12.1/go.mod h1:rf4b/h77GUv1+geiej2KzGRQr8iBLF4dXNwr5AuGkrQ= -github.com/otiai10/copy v1.0.1 h1:gtBjD8aq4nychvRZ2CyJvFWAw0aja+VHazDdruZKGZA= -github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc= -github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc= -github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776 h1:o59bHXu8Ejas8Kq6pjoVJQ9/neN66SM8AKh6wI42BBs= -github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4= -github.com/otiai10/mint v1.2.3 h1:PsrRBmrxR68kyNu6YlqYHbNlItc5vOkuS6LBEsNttVA= -github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw= -github.com/otiai10/mint v1.2.4 h1:DxYL0itZyPaR5Z9HILdxSoHx+gNs6Yx+neOGS3IVUk0= -github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M= -github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 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/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -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 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -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/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -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.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 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= @@ -581,7 +368,6 @@ github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -591,8 +377,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= @@ -601,109 +387,65 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/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/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -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/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= -github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= -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-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 h1:p7OofyZ509h8DmPLh8Hn+EIIZm/xYhdZHJ9GnXHdr6U= -github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.7 h1:4DTF1WOM2ZZS/xMOkTFBOcb6XiHu/PKn3rVo6dbewQE= -github.com/yvasiyarov/gorelic v0.0.7/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9 h1:AsFN8kXcCVkUFHyuzp1FtYbzp1nCO/H6+1uPSGEyPzM= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= -go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -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-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/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-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68= -golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI= @@ -711,9 +453,7 @@ golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271 h1:N66aaryRB3Ax92gH0v3hp1QYZ3zWWCCUR/j8Ifh45Ss= golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -730,27 +470,18 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= @@ -766,63 +497,41 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh338oozWyiFsBRHtrflcws= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191030203535-5e247c9ad0a0 h1:s5lp4ug7qHzUccgyFdjsX7OZDzHXRaePrF3B3vmUiuM= golang.org/x/tools v0.0.0-20191030203535-5e247c9ad0a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f h1:kDxGY2VmgABOe55qheT/TFqUMtcTHnomIPS1iv3G4Ms= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= -gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= @@ -830,7 +539,6 @@ google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -841,12 +549,11 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 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/imdario/mergo.v0 v0.3.7 h1:QDotlIZtaO/p+Um0ok18HRTpq5i5/SAk/qprsor+9c8= gopkg.in/imdario/mergo.v0 v0.3.7/go.mod h1:9qPP6AGrlC1G2PTNXko614FwGZvorN7MiBU0Eppok+U= -gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 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 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE= gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= @@ -865,84 +572,39 @@ gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966 h1:B0J02caTR6tpSJozBJyiAzT6C gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48= -k8s.io/api v0.16.7/go.mod h1:oUAiGRgo4t+5yqcxjOu5LoHT3wJ8JSbgczkaFYS5L7I= -k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8= k8s.io/api v0.18.2 h1:wG5g5ZmSVgm5B+eHMIbI9EGATS2L8Z72rda19RIEgY8= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= -k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY= -k8s.io/apiextensions-apiserver v0.16.7/go.mod h1:6xYRp4trGp6eT5WZ6tPi/TB2nfWQCzwUvBlpg8iswe0= -k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo= k8s.io/apiextensions-apiserver v0.18.2 h1:I4v3/jAuQC+89L3Z7dDgAiN4EOjN6sbm6iBqQwHTah8= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= -k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4= -k8s.io/apimachinery v0.16.7/go.mod h1:Xk2vD2TRRpuWYLQNM6lT9R7DSFZUYG03SarNkbGrnKE= -k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.18.2 h1:44CmtbmkzVDAhCpRVSiP2R5PPrC2RtlIv/MoB8xpdRA= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= -k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg= -k8s.io/apiserver v0.16.7/go.mod h1:/5zSatF30/L9zYfMTl55jzzOnx7r/gGv5a5wtRp8yAw= -k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw= k8s.io/apiserver v0.18.2 h1:fwKxdTWwwYhxvtjo0UUfX+/fsitsNtfErPNegH2x9ic= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= -k8s.io/cli-runtime v0.18.0/go.mod h1:1eXfmBsIJosjn9LjEBUd2WVPoPAY9XGTqTFcPMIBsUQ= -k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk= -k8s.io/client-go v0.16.7/go.mod h1:9kEMEeuy2LdsHHXoU2Skqh+SDso+Yhkxd/0tltvswDE= -k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8= k8s.io/client-go v0.18.2 h1:aLB0iaD4nmwh7arT2wIn+lMnAq7OswjaejkQ8p9bBYE= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= -k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE= -k8s.io/code-generator v0.16.7/go.mod h1:wFdrXdVi/UC+xIfLi+4l9elsTT/uEF61IfcN2wOLULQ= -k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= -k8s.io/component-base v0.0.0-20190918160511-547f6c5d7090/go.mod h1:933PBGtQFJky3TEwYx4aEPZ4IxqhWh3R6DCmzqIn1hA= -k8s.io/component-base v0.16.7/go.mod h1:ikdyfezOFMu5O0qJjy/Y9eXwj+fV3pVwdmt0ulVcIR0= -k8s.io/component-base v0.18.0/go.mod h1:u3BCg0z1uskkzrnAKFzulmYaEpZF7XC9Pf/uFyb1v2c= k8s.io/component-base v0.18.2 h1:SJweNZAGcUvsypLGNPNGeJ9UgPZQ6+bW+gEHe8uyh/Y= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.4.0 h1:lCJCxf/LIowc2IGS9TPjWDyXY4nOmdGdfcwwDQCOURQ= -k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf h1:EYm5AW/UUDbnmnI+gK0TJDVK9qPLhM+sRHYanNKw0EQ= -k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c h1:/KUFqjjqAcY4Us6luF5RDNZ16KJtb49HfR3ZHB9qYXM= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= -k8s.io/kubectl v0.18.0/go.mod h1:LOkWx9Z5DXMEg5KtOjHhRiC1fqJPLyCr3KtQgEolCkU= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/metrics v0.18.0/go.mod h1:8aYTW18koXqjLVKL7Ds05RPMX9ipJZI3mywYvBOxXd4= -k8s.io/utils v0.0.0-20190801114015-581e00157fb1 h1:+ySTxfHnfzZb9ys375PXNlLhkJPLKgHajBU0N62BDvE= -k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= -modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= -modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= -modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= -rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= -rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7 h1:uuHDyjllyzRyCIvvn0OBjiRB0SgBZGqHNYAmjR7fO50= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/controller-runtime v0.6.0 h1:Fzna3DY7c4BIP6KwfSlrfnj20DJ+SeMBK8HSFvOk9NM= sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo= sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPhJ4= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= -sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= -sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= -sigs.k8s.io/structured-merge-diff v1.0.2 h1:WiMoyniAVAYm03w+ImfF9IE2G23GLR/SwDnQyaNZvPk= -sigs.k8s.io/structured-merge-diff v1.0.2/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= @@ -950,4 +612,3 @@ sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/pkg/internal/bundle.go b/pkg/internal/bundle.go deleted file mode 100644 index c4976e9a8..000000000 --- a/pkg/internal/bundle.go +++ /dev/null @@ -1,139 +0,0 @@ -package manifests - -import ( - "encoding/json" - - "github.com/blang/semver" - operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" - "github.com/operator-framework/operator-registry/pkg/registry" - "github.com/operator-framework/operator-registry/pkg/sqlite" - "github.com/pkg/errors" -) - -// TODO: use internal version of registry.Bundle/registry.PackageManifest so -// operator-registry can use validation library. - -// manifestsLoad loads a manifests directory from disk. -type manifestsLoad struct { - dir string - pkg registry.PackageManifest - bundles map[string]*registry.Bundle -} - -// Ensure manifestsLoad implements registry.Load. -var _ registry.Load = &manifestsLoad{} - -// populate uses operator-registry's sqlite.NewSQLLoaderForDirectory to load -// l.dir's manifests. Note that this method does not call any functions that -// use SQL drivers. -func (l *manifestsLoad) populate() error { - loader := sqlite.NewSQLLoaderForDirectory(l, l.dir) - if err := loader.Populate(); err != nil { - return errors.Wrapf(err, "error getting bundles from manifests dir %q", l.dir) - } - return nil -} - -// AddOperatorBundle adds a bundle to l. -func (l *manifestsLoad) AddOperatorBundle(bundle *registry.Bundle) error { - csvRaw, err := bundle.ClusterServiceVersion() - if err != nil { - return errors.Wrap(err, "error getting bundle CSV") - } - csvSpec := operatorsv1alpha1.ClusterServiceVersionSpec{} - if err := json.Unmarshal(csvRaw.Spec, &csvSpec); err != nil { - return errors.Wrap(err, "error unmarshaling CSV spec") - } - bundle.Name = csvSpec.Version.String() - l.bundles[csvSpec.Version.String()] = bundle - return nil -} - -// AddOperatorBundle adds the package manifest to l. -func (l *manifestsLoad) AddPackageChannels(pkg registry.PackageManifest) error { - l.pkg = pkg - return nil -} - -// AddBundleSemver is a no-op to implement the registry.Load interface. -func (l *manifestsLoad) AddBundleSemver(pkg *registry.Package, bundle *registry.Bundle) error { - return nil -} - -// AddBundlePackageChannels is a no-op to implement the registry.Load interface. -func (*manifestsLoad) AddBundlePackageChannels(registry.PackageManifest, *registry.Bundle) error { - return nil -} - -// RmPemoveckageNas a no-op to implement the registry.Load interface. -func (l *manifestsLoad) RemovePackage(packageName string) error { - return nil -} - -// ClearNonDefaultBundles is a no-op to implement the registry.Load interface. -func (l *manifestsLoad) ClearNonHeadBundles() error { - return nil -} - -// ManifestsStore knows how to query for an operator's package manifest and -// related bundles. -type ManifestsStore interface { - // GetPackageManifest returns the ManifestsStore's registry.PackageManifest. - // The returned object is assumed to be valid. - GetPackageManifest() registry.PackageManifest - // GetBundles returns the ManifestsStore's set of registry.Bundle. These - // bundles are unique by CSV version, since only one operator type should - // exist in one manifests dir. - // The returned objects are assumed to be valid. - GetBundles() []*registry.Bundle - // GetBundleForVersion returns the ManifestsStore's registry.Bundle for a - // given version string. An error should be returned if the passed version - // does not exist in the store. - // The returned object is assumed to be valid. - GetBundleForVersion(string) (*registry.Bundle, error) -} - -// manifests implements ManifestsStore -type manifests struct { - pkg registry.PackageManifest - bundles map[string]*registry.Bundle -} - -// ManifestsStoreForDir populates a ManifestsStore from the metadata in dir. -// Each bundle and the package manifest are statically validated, and will -// return an error if any are not valid. -func ManifestsStoreForDir(dir string) (ManifestsStore, error) { - load := &manifestsLoad{ - dir: dir, - bundles: map[string]*registry.Bundle{}, - } - if err := load.populate(); err != nil { - return nil, err - } - return &manifests{ - pkg: load.pkg, - bundles: load.bundles, - }, nil -} - -func (l manifests) GetPackageManifest() registry.PackageManifest { - return l.pkg -} - -func (l manifests) GetBundles() (bundles []*registry.Bundle) { - for _, bundle := range l.bundles { - bundles = append(bundles, bundle) - } - return bundles -} - -func (l manifests) GetBundleForVersion(version string) (*registry.Bundle, error) { - if _, err := semver.Parse(version); err != nil { - return nil, errors.Wrapf(err, "error getting bundle for version %q", version) - } - bundle, ok := l.bundles[version] - if !ok { - return nil, errors.Errorf("bundle for version %q does not exist", version) - } - return bundle, nil -} diff --git a/pkg/manifests/bundle.go b/pkg/manifests/bundle.go new file mode 100644 index 000000000..723ae94b7 --- /dev/null +++ b/pkg/manifests/bundle.go @@ -0,0 +1,22 @@ +package manifests + +import ( + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" +) + +type Bundle struct { + Name string + Objects []*unstructured.Unstructured + Package string + Channels []string + DefaultChannel string + BundleImage string + CSV *operatorsv1alpha1.ClusterServiceVersion + V1beta1CRDs []*apiextensionsv1beta1.CustomResourceDefinition + V1CRDs []*apiextensionsv1.CustomResourceDefinition + Dependencies []*Dependency +} diff --git a/pkg/manifests/bundleloader.go b/pkg/manifests/bundleloader.go new file mode 100644 index 000000000..040d7239c --- /dev/null +++ b/pkg/manifests/bundleloader.go @@ -0,0 +1,177 @@ +package manifests + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/yaml" + + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" +) + +// bundleLoader loads a bundle directory from disk +type bundleLoader struct { + dir string + bundle *Bundle +} + +func NewBundleLoader(dir string) bundleLoader { + return bundleLoader{ + dir: dir, + } +} + +func (b *bundleLoader) LoadBundle() error { + errs := make([]error, 0) + if err := filepath.Walk(b.dir, collectWalkErrs(b.LoadBundleWalkFunc, &errs)); err != nil { + errs = append(errs, err) + } + + return utilerrors.NewAggregate(errs) +} + +// collectWalkErrs calls the given walk func and appends any non-nil, non skip dir error returned to the given errors slice. +func collectWalkErrs(walk filepath.WalkFunc, errs *[]error) filepath.WalkFunc { + return func(path string, f os.FileInfo, err error) (walkErr error) { + if walkErr = walk(path, f, err); walkErr != nil && walkErr != filepath.SkipDir { + *errs = append(*errs, walkErr) + return nil + } + + return walkErr + } +} + +func (b *bundleLoader) LoadBundleWalkFunc(path string, f os.FileInfo, err error) error { + if f == nil { + return fmt.Errorf("invalid file: %v", f) + } + + if f.IsDir() { + if strings.HasPrefix(f.Name(), ".") { + return filepath.SkipDir + } + return nil + } + + if strings.HasPrefix(f.Name(), ".") { + return nil + } + + fileReader, err := os.Open(path) + if err != nil { + return fmt.Errorf("unable to load file %s: %s", path, err) + } + + decoder := yaml.NewYAMLOrJSONDecoder(fileReader, 30) + csv := unstructured.Unstructured{} + + if err = decoder.Decode(&csv); err != nil { + return nil + } + + if csv.GetKind() != operatorsv1alpha1.ClusterServiceVersionKind { + return nil + } + + var errs []error + bundle, err := loadBundle(csv.GetName(), filepath.Dir(path)) + if err != nil { + errs = append(errs, fmt.Errorf("error loading objs in directory: %s", err)) + } + + if bundle == nil || bundle.CSV == nil { + errs = append(errs, fmt.Errorf("no bundle csv found")) + return utilerrors.NewAggregate(errs) + } + + b.bundle = bundle + + return utilerrors.NewAggregate(errs) +} + +// loadBundle takes the directory that a CSV is in and assumes the rest of the objects in that directory +// are part of the bundle. +func loadBundle(csvName string, dir string) (*Bundle, error) { + files, err := ioutil.ReadDir(dir) + if err != nil { + return nil, err + } + + var errs []error + bundle := &Bundle{ + Name: csvName, + } + for _, f := range files { + if f.IsDir() { + continue + } + + if strings.HasPrefix(f.Name(), ".") { + continue + } + + path := filepath.Join(dir, f.Name()) + fileReader, err := os.Open(path) + if err != nil { + errs = append(errs, fmt.Errorf("unable to load file %s: %s", path, err)) + continue + } + + decoder := yaml.NewYAMLOrJSONDecoder(fileReader, 30) + obj := &unstructured.Unstructured{} + if err = decoder.Decode(obj); err != nil { + continue + } + + bundle.Objects = append(bundle.Objects, obj) + + switch kind := obj.GetKind(); kind { + case "ClusterServiceVersion": + if bundle.CSV != nil { + return nil, fmt.Errorf("invalid bundle: contains multiple CSVs") + } + csv := operatorsv1alpha1.ClusterServiceVersion{} + err := runtime.DefaultUnstructuredConverter.FromUnstructured( + obj.UnstructuredContent(), + &csv) + if err != nil { + return nil, fmt.Errorf("unable to parse CSV %s: %s", f.Name(), err.Error()) + } + bundle.CSV = &csv + case "CustomResourceDefinition": + version := obj.GetAPIVersion() + if version == apiextensionsv1beta1.SchemeGroupVersion.String() { + crd := apiextensionsv1beta1.CustomResourceDefinition{} + err := runtime.DefaultUnstructuredConverter.FromUnstructured( + obj.UnstructuredContent(), + &crd) + if err != nil { + return nil, fmt.Errorf("unable to parse CRD %s: %s", f.Name(), err.Error()) + } + bundle.V1beta1CRDs = append(bundle.V1beta1CRDs, &crd) + } else if version == apiextensionsv1.SchemeGroupVersion.String() { + crd := apiextensionsv1.CustomResourceDefinition{} + err := runtime.DefaultUnstructuredConverter.FromUnstructured( + obj.UnstructuredContent(), + &crd) + if err != nil { + return nil, fmt.Errorf("unable to parse CRD %s: %s", f.Name(), err.Error()) + } + bundle.V1CRDs = append(bundle.V1CRDs, &crd) + } else { + return nil, fmt.Errorf("unsupported CRD version %s for %s", version, f.Name()) + } + } + } + + return bundle, utilerrors.NewAggregate(errs) +} diff --git a/pkg/manifests/bundlemeta.go b/pkg/manifests/bundlemeta.go new file mode 100644 index 000000000..da2403e3d --- /dev/null +++ b/pkg/manifests/bundlemeta.go @@ -0,0 +1,37 @@ +package manifests + +// AnnotationsFile holds annotation information about a bundle +type AnnotationsFile struct { + // annotations is a list of annotations for a given bundle + Annotations Annotations `json:"annotations" yaml:"annotations"` +} + +// Annotations is a list of annotations for a given bundle +type Annotations struct { + // PackageName is the name of the overall package, ala `etcd`. + PackageName string `json:"operators.operatorframework.io.bundle.package.v1" yaml:"operators.operatorframework.io.bundle.package.v1"` + + // Channels are a comma separated list of the declared channels for the bundle, ala `stable` or `alpha`. + Channels string `json:"operators.operatorframework.io.bundle.channels.v1" yaml:"operators.operatorframework.io.bundle.channels.v1"` + + // DefaultChannelName is, if specified, the name of the default channel for the package. The + // default channel will be installed if no other channel is explicitly given. If the package + // has a single channel, then that channel is implicitly the default. + DefaultChannelName string `json:"operators.operatorframework.io.bundle.channel.default.v1" yaml:"operators.operatorframework.io.bundle.channel.default.v1"` +} + +// DependenciesFile holds dependency information about a bundle +type DependenciesFile struct { + // Dependencies is a list of dependencies for a given bundle + Dependencies []Dependency `json:"dependencies" yaml:"dependencies"` +} + +// Dependencies is a list of dependencies for a given bundle +type Dependency struct { + // The type of dependency. It can be `olm.package` for operator-version based + // dependency or `olm.gvk` for gvk based dependency. This field is required. + Type string `json:"type" yaml:"type"` + + // The value of the dependency (either GVKDependency or PackageDependency) + Value string `json:"value" yaml:"value"` +} diff --git a/pkg/manifests/directory.go b/pkg/manifests/directory.go index e910b55df..7ff68319a 100644 --- a/pkg/manifests/directory.go +++ b/pkg/manifests/directory.go @@ -1,31 +1,27 @@ package manifests -import ( - "fmt" +// GetManifestsDir parses all bundles and a package manifest from a directory +func GetManifestsDir(dir string) (*PackageManifest, []*Bundle, error) { + loader := NewPackageManifestLoader(dir) - internal "github.com/operator-framework/api/pkg/internal" - "github.com/operator-framework/api/pkg/validation" - "github.com/operator-framework/api/pkg/validation/errors" + err := loader.LoadPackage() + if err != nil { + return nil, nil, err + } + + return loader.pkg, loader.bundles, nil +} - "github.com/operator-framework/operator-registry/pkg/registry" -) +// GetBundleFromDir takes a raw directory containg an Operator Bundle and +// serializes its component files (CSVs, CRDs, other native kube manifests) +// and returns it as a Bundle +func GetBundleFromDir(dir string) (*Bundle, error) { + loader := NewBundleLoader(dir) -// GetManifestsDir parses all bundles and a package manifest from dir, which -// are returned if found along with any errors or warnings encountered while -// parsing/validating found manifests. -func GetManifestsDir(dir string) (registry.PackageManifest, []*registry.Bundle, []errors.ManifestResult) { - manifests, err := internal.ManifestsStoreForDir(dir) + err := loader.LoadBundle() if err != nil { - result := errors.ManifestResult{} - result.Add(errors.ErrInvalidParse(fmt.Sprintf("parse manifests from %q", dir), err)) - return registry.PackageManifest{}, nil, []errors.ManifestResult{result} - } - pkg := manifests.GetPackageManifest() - bundles := manifests.GetBundles() - objs := []interface{}{} - for _, obj := range bundles { - objs = append(objs, obj) + return nil, err } - results := validation.AllValidators.Validate(objs...) - return pkg, bundles, results + + return loader.bundle, nil } diff --git a/pkg/manifests/directory_test.go b/pkg/manifests/directory_test.go new file mode 100644 index 000000000..c408db7d2 --- /dev/null +++ b/pkg/manifests/directory_test.go @@ -0,0 +1,31 @@ +package manifests + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestGetBundleDir(t *testing.T) { + bundle, err := GetBundleFromDir("./testdata/valid_bundle") + require.NoError(t, err) + require.Equal(t, "etcdoperator.v0.9.4", bundle.Name) + require.NotNil(t, bundle.CSV) + require.Equal(t, 3, len(bundle.V1beta1CRDs)) + require.Equal(t, 4, len(bundle.Objects)) +} + +func TestGetPackage(t *testing.T) { + pkg, bundles, err := GetManifestsDir("./testdata/valid_package") + require.NoError(t, err) + require.NotNil(t, pkg) + require.Equal(t, "etcd", pkg.PackageName) + require.Equal(t, 2, len(bundles)) + require.Equal(t, "etcdoperator.v0.9.2", bundles[0].Name) + require.NotNil(t, bundles[0].CSV) + require.Equal(t, 3, len(bundles[0].V1beta1CRDs)) + require.Equal(t, "etcdoperator.v0.9.4", bundles[1].Name) + require.NotNil(t, bundles[1].CSV) + require.Equal(t, 2, len(bundles[1].V1beta1CRDs)) + require.Equal(t, 1, len(bundles[1].V1CRDs)) +} diff --git a/pkg/manifests/packagemanifest.go b/pkg/manifests/packagemanifest.go new file mode 100644 index 000000000..5a8fe2e9d --- /dev/null +++ b/pkg/manifests/packagemanifest.go @@ -0,0 +1,32 @@ +package manifests + +// PackageManifest holds information about a package, which is a reference to one (or more) +// channels under a single package. +type PackageManifest struct { + // PackageName is the name of the overall package, ala `etcd`. + PackageName string `json:"packageName" yaml:"packageName"` + + // Channels are the declared channels for the package, ala `stable` or `alpha`. + Channels []PackageChannel `json:"channels" yaml:"channels"` + + // DefaultChannelName is, if specified, the name of the default channel for the package. The + // default channel will be installed if no other channel is explicitly given. If the package + // has a single channel, then that channel is implicitly the default. + DefaultChannelName string `json:"defaultChannel" yaml:"defaultChannel"` +} + +// IsEmpty returns true if the PackageManifest instance is equal to the zero value +func (p *PackageManifest) IsEmpty() bool { + return p.PackageName == "" && len(p.Channels) == 0 && p.DefaultChannelName == "" +} + +// PackageChannel defines a single channel under a package, pointing to a version of that +// package. +type PackageChannel struct { + // Name is the name of the channel, e.g. `alpha` or `stable` + Name string `json:"name" yaml:"name"` + + // CurrentCSVName defines a reference to the CSV holding the version of this package currently + // for the channel. + CurrentCSVName string `json:"currentCSV" yaml:"currentCSV"` +} diff --git a/pkg/manifests/packagemanifestloader.go b/pkg/manifests/packagemanifestloader.go new file mode 100644 index 000000000..7428d1dff --- /dev/null +++ b/pkg/manifests/packagemanifestloader.go @@ -0,0 +1,132 @@ +package manifests + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/yaml" + + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" +) + +// bundleLoader loads a bundle directory from disk +type packageManifestLoader struct { + dir string + bundles []*Bundle + pkg *PackageManifest +} + +func NewPackageManifestLoader(dir string) packageManifestLoader { + return packageManifestLoader{ + dir: dir, + } +} + +func (p *packageManifestLoader) LoadPackage() error { + errs := make([]error, 0) + if err := filepath.Walk(p.dir, collectWalkErrs(p.LoadPackagesWalkFunc, &errs)); err != nil { + errs = append(errs, err) + } + + if err := filepath.Walk(p.dir, collectWalkErrs(p.LoadBundleWalkFunc, &errs)); err != nil { + errs = append(errs, err) + } + + return utilerrors.NewAggregate(errs) +} + +// LoadPackagesWalkFunc attempts to unmarshal the file at the given path into a PackageManifest resource. +// If unmarshaling is successful, the PackageManifest is added to the loader's store. +func (p *packageManifestLoader) LoadPackagesWalkFunc(path string, f os.FileInfo, err error) error { + if f == nil { + return fmt.Errorf("invalid file: %v", f) + } + + if f.IsDir() { + if strings.HasPrefix(f.Name(), ".") { + return filepath.SkipDir + } + return nil + } + + if strings.HasPrefix(f.Name(), ".") { + return nil + } + + fileReader, err := os.Open(path) + if err != nil { + return fmt.Errorf("unable to load package from file %s: %s", path, err) + } + + decoder := yaml.NewYAMLOrJSONDecoder(fileReader, 30) + manifest := PackageManifest{} + if err = decoder.Decode(&manifest); err != nil { + if err != nil { + return fmt.Errorf("could not decode contents of file %s into package: %s", path, err) + } + } + + if manifest.IsEmpty() { + return nil + } + + if p.pkg != nil { + return fmt.Errorf("multiple package manifest files found in directory") + } + + p.pkg = &manifest + + return nil +} + +func (p *packageManifestLoader) LoadBundleWalkFunc(path string, f os.FileInfo, err error) error { + if f == nil { + return fmt.Errorf("invalid file: %v", f) + } + + if f.IsDir() { + if strings.HasPrefix(f.Name(), ".") { + return filepath.SkipDir + } + return nil + } + + if strings.HasPrefix(f.Name(), ".") { + return nil + } + + fileReader, err := os.Open(path) + if err != nil { + return fmt.Errorf("unable to load file %s: %s", path, err) + } + + decoder := yaml.NewYAMLOrJSONDecoder(fileReader, 30) + csv := unstructured.Unstructured{} + + if err = decoder.Decode(&csv); err != nil { + return nil + } + + if csv.GetKind() != operatorsv1alpha1.ClusterServiceVersionKind { + return nil + } + + var errs []error + bundle, err := loadBundle(csv.GetName(), filepath.Dir(path)) + if err != nil { + errs = append(errs, fmt.Errorf("error loading objs in directory: %s", err)) + } + + if bundle == nil || bundle.CSV == nil { + errs = append(errs, fmt.Errorf("no bundle csv found")) + return utilerrors.NewAggregate(errs) + } + + p.bundles = append(p.bundles, bundle) + + return utilerrors.NewAggregate(errs) +} diff --git a/pkg/manifests/testdata/valid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml b/pkg/manifests/testdata/valid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5afc088b9 --- /dev/null +++ b/pkg/manifests/testdata/valid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdbackups.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdBackup + listKind: EtcdBackupList + plural: etcdbackups + singular: etcdbackup + scope: Namespaced + version: v1beta2 diff --git a/pkg/manifests/testdata/valid_bundle/etcdclusters.etcd.database.coreos.com.crd.yaml b/pkg/manifests/testdata/valid_bundle/etcdclusters.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..01111e5c5 --- /dev/null +++ b/pkg/manifests/testdata/valid_bundle/etcdclusters.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,16 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdclusters.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdCluster + listKind: EtcdClusterList + plural: etcdclusters + shortNames: + - etcdclus + - etcd + singular: etcdcluster + scope: Namespaced + version: v1beta2 diff --git a/pkg/manifests/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml b/pkg/manifests/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml new file mode 100644 index 000000000..56f414d66 --- /dev/null +++ b/pkg/manifests/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml @@ -0,0 +1,309 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdCluster\",\n \"metadata\": {\n \"name\": \"example\"\ + \n },\n \"spec\": {\n \"size\": 3,\n \"version\": \"3.2.13\"\ + \n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdRestore\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-restore\"\ + \n },\n \"spec\": {\n \"etcdCluster\": {\n \"name\": \"example-etcd-cluster\"\ + \n },\n \"backupStorageType\": \"S3\",\n \"s3\": {\n \"\ + path\": \"\",\n \"awsSecret\": \"\"\n \ + \ }\n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdBackup\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-backup\"\ + \n },\n \"spec\": {\n \"etcdEndpoints\": [\"\"\ + ],\n \"storageType\":\"S3\",\n \"s3\": {\n \"path\": \"\"\ + ,\n \"awsSecret\": \"\"\n }\n }\n }\n]\n" + capabilities: Full Lifecycle + categories: Database + containerImage: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + createdAt: 2019-02-28 01:03:00 + description: Create and maintain highly-available etcd clusters on Kubernetes + repository: https://github.com/coreos/etcd-operator + tectonic-visibility: ocs + name: etcdoperator.v0.9.4 + namespace: placeholder +spec: + customresourcedefinitions: + owned: + - description: Represents a cluster of etcd nodes. + displayName: etcd Cluster + kind: EtcdCluster + name: etcdclusters.etcd.database.coreos.com + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: Limits describes the minimum/maximum amount of compute resources + required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podStatuses + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Service + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: The target version of the etcd cluster, after upgrading. + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to backup an etcd cluster. + displayName: etcd Backup + kind: EtcdBackup + name: etcdbackups.etcd.database.coreos.com + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - urn:alm:descriptor:etcd:endpoint + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to restore an etcd cluster from a backup. + displayName: etcd Restore + kind: EtcdRestore + name: etcdrestores.etcd.database.coreos.com + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - urn:alm:descriptor:io.kubernetes:EtcdCluster + - urn:alm:descriptor:text + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + description: "The etcd Operater creates and maintains highly-available etcd clusters\ + \ on Kubernetes, allowing engineers to easily deploy and manage etcd clusters\ + \ for their applications.\n\netcd is a distributed key value store that provides\ + \ a reliable way to store data across a cluster of machines. It\xE2\u20AC\u2122\ + s open-source and available on GitHub. etcd gracefully handles leader elections\ + \ during network partitions and will tolerate machine failure, including the leader.\n\ + \n\n### Reading and writing to etcd\n\nCommunicate with etcd though its command\ + \ line utility `etcdctl` via port forwarding:\n\n $ kubectl --namespace default\ + \ port-forward service/example-client 2379:2379\n $ etcdctl --endpoints http://127.0.0.1:2379\ + \ get /\n\nOr directly to the API using the automatically generated Kubernetes\ + \ Service:\n\n $ etcdctl --endpoints http://example-client.default.svc:2379\ + \ get /\n\nBe sure to secure your etcd cluster (see Common Configurations) before\ + \ exposing it outside of the namespace or cluster.\n\n\n### Supported Features\n\ + \n* **High availability** - Multiple instances of etcd are networked together\ + \ and secured. Individual failures or networking issues are transparently handled\ + \ to keep your cluster up and running.\n\n* **Automated updates** - Rolling out\ + \ a new etcd version works like all Kubernetes rolling updates. Simply declare\ + \ the desired version, and the etcd service starts a safe rolling update to the\ + \ new version automatically.\n\n* **Backups included** - Create etcd backups and\ + \ restore them through the etcd Operator.\n\n### Common Configurations\n\n* **Configure\ + \ TLS** - Specify [static TLS certs](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md)\ + \ as Kubernetes secrets.\n\n* **Set Node Selector and Affinity** - [Spread your\ + \ etcd Pods](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-node-selector-and-anti-affinity-across-nodes)\ + \ across Nodes and availability zones.\n\n* **Set Resource Limits** - [Set the\ + \ Kubernetes limit and request](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-resource-requirement)\ + \ values for your etcd Pods.\n\n* **Customize Storage** - [Set a custom StorageClass](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#custom-persistentvolumeclaim-definition)\ + \ that you would like to use.\n" + displayName: etcd + icon: + - base64data: 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 + mediatype: image/png + install: + spec: + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + labels: + name: etcd-operator-alm-owned + name: etcd-operator-alm-owned + spec: + containers: + - command: + - etcd-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-operator + - command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-backup-operator + - command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-restore-operator + serviceAccountName: etcd-operator + permissions: + - rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + verbs: + - '*' + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + serviceAccountName: etcd-operator + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: false + type: AllNamespaces + keywords: + - etcd + - key value + - database + - coreos + - open source + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + maintainers: + - email: etcd-dev@googlegroups.com + name: etcd Community + maturity: alpha + provider: + name: CNCF + replaces: etcdoperator.v0.9.2 + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + version: 0.9.4 diff --git a/pkg/manifests/testdata/valid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml b/pkg/manifests/testdata/valid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5b851cd12 --- /dev/null +++ b/pkg/manifests/testdata/valid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdrestores.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdRestore + listKind: EtcdRestoreList + plural: etcdrestores + singular: etcdrestore + scope: Namespaced + version: v1beta2 diff --git a/pkg/manifests/testdata/valid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml b/pkg/manifests/testdata/valid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5afc088b9 --- /dev/null +++ b/pkg/manifests/testdata/valid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdbackups.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdBackup + listKind: EtcdBackupList + plural: etcdbackups + singular: etcdbackup + scope: Namespaced + version: v1beta2 diff --git a/pkg/manifests/testdata/valid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml b/pkg/manifests/testdata/valid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..01111e5c5 --- /dev/null +++ b/pkg/manifests/testdata/valid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,16 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdclusters.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdCluster + listKind: EtcdClusterList + plural: etcdclusters + shortNames: + - etcdclus + - etcd + singular: etcdcluster + scope: Namespaced + version: v1beta2 diff --git a/pkg/manifests/testdata/valid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml b/pkg/manifests/testdata/valid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml new file mode 100644 index 000000000..efc209da6 --- /dev/null +++ b/pkg/manifests/testdata/valid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml @@ -0,0 +1,305 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdCluster\",\n \"metadata\": {\n \"name\": \"example\"\ + \n },\n \"spec\": {\n \"size\": 3,\n \"version\": \"3.2.13\"\ + \n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdRestore\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-restore\"\ + \n },\n \"spec\": {\n \"etcdCluster\": {\n \"name\": \"example-etcd-cluster\"\ + \n },\n \"backupStorageType\": \"S3\",\n \"s3\": {\n \"\ + path\": \"\",\n \"awsSecret\": \"\"\n \ + \ }\n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdBackup\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-backup\"\ + \n },\n \"spec\": {\n \"etcdEndpoints\": [\"\"\ + ],\n \"storageType\":\"S3\",\n \"s3\": {\n \"path\": \"\"\ + ,\n \"awsSecret\": \"\"\n }\n }\n }\n]\n" + capabilities: Full Lifecycle + categories: Database + description: Creates and maintain highly-available etcd clusters on Kubernetes + tectonic-visibility: ocs + name: etcdoperator.v0.9.2 + namespace: placeholder +spec: + customresourcedefinitions: + owned: + - description: Represents a cluster of etcd nodes. + displayName: etcd Cluster + kind: EtcdCluster + name: etcdclusters.etcd.database.coreos.com + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: Limits describes the minimum/maximum amount of compute resources + required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podStatuses + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Service + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: The target version of the etcd cluster, after upgrading. + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to backup an etcd cluster. + displayName: etcd Backup + kind: EtcdBackup + name: etcdbackups.etcd.database.coreos.com + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - urn:alm:descriptor:etcd:endpoint + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to restore an etcd cluster from a backup. + displayName: etcd Restore + kind: EtcdRestore + name: etcdrestores.etcd.database.coreos.com + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - urn:alm:descriptor:io.kubernetes:EtcdCluster + - urn:alm:descriptor:text + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + description: "The etcd Operater creates and maintains highly-available etcd clusters\ + \ on Kubernetes, allowing engineers to easily deploy and manage etcd clusters\ + \ for their applications.\n\netcd is a distributed key value store that provides\ + \ a reliable way to store data across a cluster of machines. It\xE2\u20AC\u2122\ + s open-source and available on GitHub. etcd gracefully handles leader elections\ + \ during network partitions and will tolerate machine failure, including the leader.\n\ + \n\n### Reading and writing to etcd\n\nCommunicate with etcd though its command\ + \ line utility `etcdctl` via port forwarding:\n\n $ kubectl --namespace default\ + \ port-forward service/example-client 2379:2379\n $ etcdctl --endpoints http://127.0.0.1:2379\ + \ get /\n\nOr directly to the API using the automatically generated Kubernetes\ + \ Service:\n\n $ etcdctl --endpoints http://example-client.default.svc:2379\ + \ get /\n\nBe sure to secure your etcd cluster (see Common Configurations) before\ + \ exposing it outside of the namespace or cluster.\n\n\n### Supported Features\n\ + \n* **High availability** - Multiple instances of etcd are networked together\ + \ and secured. Individual failures or networking issues are transparently handled\ + \ to keep your cluster up and running.\n\n* **Automated updates** - Rolling out\ + \ a new etcd version works like all Kubernetes rolling updates. Simply declare\ + \ the desired version, and the etcd service starts a safe rolling update to the\ + \ new version automatically.\n\n* **Backups included** - Create etcd backups and\ + \ restore them through the etcd Operator.\n\n### Common Configurations\n\n* **Configure\ + \ TLS** - Specify [static TLS certs](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md)\ + \ as Kubernetes secrets.\n\n* **Set Node Selector and Affinity** - [Spread your\ + \ etcd Pods](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-node-selector-and-anti-affinity-across-nodes)\ + \ across Nodes and availability zones.\n\n* **Set Resource Limits** - [Set the\ + \ Kubernetes limit and request](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-resource-requirement)\ + \ values for your etcd Pods.\n\n* **Customize Storage** - [Set a custom StorageClass](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#custom-persistentvolumeclaim-definition)\ + \ that you would like to use.\n" + displayName: etcd + icon: + - base64data: iVBORw0KGgoAAAANSUhEUgAAAOEAAADZCAYAAADWmle6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAEKlJREFUeNrsndt1GzkShmEev4sTgeiHfRYdgVqbgOgITEVgOgLTEQydwIiKwFQCayoCU6+7DyYjsBiBFyVVz7RkXvqCSxXw/+f04XjGQ6IL+FBVuL769euXgZ7r39f/G9iP0X+u/jWDNZzZdGI/Ftama1jjuV4BwmcNpbAf1Fgu+V/9YRvNAyzT2a59+/GT/3hnn5m16wKWedJrmOCxkYztx9Q+py/+E0GJxtJdReWfz+mxNt+QzS2Mc0AI+HbBBwj9QViKbH5t64DsP2fvmGXUkWU4WgO+Uve2YQzBUGd7r+zH2ZG/tiUQc4QxKwgbwFfVGwwmdLL5wH78aPC/ZBem9jJpCAX3xtcNASSNgJLzUPSQyjB1zQNl8IQJ9MIU4lx2+Jo72ysXYKl1HSzN02BMa/vbZ5xyNJIshJzwf3L0dQhJw4Sih/SFw9Tk8sVeghVPoefaIYCkMZCKbrcP9lnZuk0uPUjGE/KE8JQry7W2tgfuC3vXgvNV+qSQbyFtAtyWk7zWiYevvuUQ9QEQCvJ+5mmu6dTjz1zFHLFj8Eb87MtxaZh/IQFIHom+9vgTWwZxAQjT9X4vtbEVPojwjiV471s00mhAckpwGuCn1HtFtRDaSh6y9zsL+LNBvCG/24ThcxHObdlWc1v+VQJe8LcO0jwtuF8BwnAAUgP9M8JPU2Me+Oh12auPGT6fHuTePE3bLDy+x9pTLnhMn+07TQGh//Bz1iI0c6kvtqInjvPZcYR3KsPVmUsPYt9nFig9SCY8VQNhpPBzn952bbgcsk2EvM89wzh3UEffBbyPqvBUBYQ8ODGPFOLsa7RF096WJ69L+E4EmnpjWu5o4ChlKaRTKT39RMMaVPEQRsz/nIWlDN80chjdJlSd1l0pJCAMVZsniobQVuxceMM9OFoaMd9zqZtjMEYYDW38Drb8Y0DYPLShxn0pvIFuOSxd7YCPet9zk452wsh54FJoeN05hcgSQoG5RR0Qh9Q4E4VvL4wcZq8UACgaRFEQKgSwWrkr5WFnGxiHSutqJGlXjBgIOayhwYBTA0ER0oisIVSUV0AAMT0IASCUO4hRIQSAEECMCCEPwqyQA0JCQBzEGjWNAqHiUVAoXUWbvggOIQCEAOJzxTjoaQ4AIaE64/aZridUsBYUgkhB15oGg1DBIl8IqirYwV6hPSGBSFteMCUBSVXwfYixBmamRubeMyjzMJQBDDowE3OesDD+zwqFoDqiEwXoXJpljB+PvWJGy75BKF1FPxhKygJuqUdYQGlLxNEXkrYyjQ0GbaAwEnUIlLRNvVjQDYUAsJB0HKLE4y0AIpQNgCIhBIhQTgCKhZBBpAN/v6LtQI50JfUgYOnnjmLUFHKhjxbAmdTCaTiBm3ovLPqG2urWAij6im0Nd9aTN9ygLUEt9LgSRnohxUPIKxlGaE+/6Y7znFf0yX+GnkvFFWmarkab2o9PmTeq8sbd2a7DaysXz7i64VeznN4jCQhN9gdDbRiuWrfrsq0mHIrlaq+hlotCtd3Um9u0BYWY8y5D67wccJoZjFca7iUs9VqZcfsZwTd1sbWGG+OcYaTnPAP7rTQVVlM4Sg3oGvB1tmNh0t/HKXZ1jFoIMwCQjtqbhNxUmkGYqgZEDZP11HN/S3gAYRozf0l8C5kKEKUvW0t1IfeWG/5MwgheZTT1E0AEhDkAePQO+Ig2H3DncAkQM4cwUQCD530dU4B5Yvmi2LlDqXfWrxMCcMth51RToRMNUXFnfc2KJ0+Ryl0VNOUwlhh6NoxK5gnViTgQpUG4SqSyt5z3zRJpuKmt3Q1614QaCBPaN6je+2XiFcWAKOXcUfIYKRyL/1lb7pe5VxSxxjQ6hImshqGRt5GWZVKO6q2wHwujfwDtIvaIdexj8Cm8+a68EqMfox6x/voMouZF4dHnEGNeCDMwT6vdNfekH1MafMk4PI06YtqLVGl95aEM9Z5vAeCTOA++YLtoVJRrsqNCaJ6WRmkdYaNec5BT/lcTRMqrhmwfjbpkj55+OKp8IEbU/JLgPJE6Wa3TTe9sHS+ShVD5QIyqIxMEwKh12olC6mHIed5ewEop80CNlfIOADYOT2nd6ZXCop+Ebqchc0JqxKcKASxChycJgUh1rnHA5ow9eTrhqNI7JWiAYYwBGGdpyNLoGw0Pkh96h1BpHihyywtATDM/7Hk2fN9EnH8BgKJCU4ooBkbXFMZJiPbrOyecGl3zgQDQL4hk10IZiOe+5w99Q/gBAEIJgPhJM4QAEEoFREAIAAEiIASAkD8Qt4AQAEIAERAGFlX4CACKAXGVM4ivMwWwCLFAlyeoaa70QePKm5Dlp+/n+ye/5dYgva6YsUaVeMa+tzNFeJtWwc+udbJ0Fg399kLielQJ5Ze61c2+7ytA6EZetiPxZC6tj22yJCv6jUwOyj/zcbqAxOMyAKEbfeHtNa7DtYXptjsk2kJxR+eIeim/tHNofUKYy8DMrQcAKWz6brpvzyIAlpwPhQ49l6b7skJf5Z+YTOYQc4FwLDxvoTDwaygQK+U/kVr+ytSFBG01Q3gnJJR4cNiAhx4HDub8/b5DULXlj6SVZghFiE+LdvE9vo/o8Lp1RmH5hzm0T6wdbZ6n+D6i44zDRc3ln6CpAEJfXiRU45oqLz8gFAThWsh7ughrRibc0QynHgZpNJa/ENJ+loCwu/qOGnFIjYR/n7TfgycULhcQhu6VC+HfF+L3BoAQ4WiZTw1M+FPCnA2gKC6/FAhXgDC+ojQGh3NuWsvfF1L/D5ohlCKtl1j2ldu9a/nPAKFwN56Bst10zCG0CPleXN/zXPgHQZXaZaBgrbzyY5V/mUA+6F0hwtGN9rwu5DVZPuwWqfxdFz1LWbJ2lwKEa+0Qsm4Dl3fp+Pu0lV97PgwIPfSsS+UQhj5Oo+vvFULazRIQyvGEcxPuNLCth2MvFsrKn8UOilAQShkh7TTczYNMoS6OdP47msrPi82lXKGWhCdMZYS0bFy+vcnGAjP1CIfvgbKNA9glecEH9RD6Ol4wRuWyN/G9MHnksS6o/GPf5XcwNSUlHzQhDuAKtWJmkwKElU7lylP5rgIcsquh/FI8YZCDpkJBuE4FQm7Icw8N+SrUGaQKyi8FwiDt1ve5o+Vu7qYHy/psgK8cvh+FTYuO77bhEC7GuaPiys/L1X4IgXDL+e3M5+ovLxBy5VLuIebw1oqcHoPfoaMJUsHays878r8KbDc3xtPx/84gZPBG/JwaufrsY/SRG/OY3//8QMNdsvdZCFtbW6f8pFuf5bflILAlX7O+4fdfugKyFYS8T2zAsXthdG0VurPGKwI06oF5vkBgHWkNp6ry29+lsPZMU3vijnXFNmoclr+6+Ou/FIb8yb30sS8YGjmTqCLyQsi5N/6ZwKs0Yenj68pfPjF6N782Dp2FzV9CTyoSeY8mLK16qGxIkLI8oa1n8tz9juP40DlK0epxYEbojbq+9QfurBeVIlCO9D2396bxiV4lkYQ3hOAFw2pbhqMGISkkQOMcQ9EqhDmGZZdo92JC0YHRNTfoSg+5e0IT+opqCKHoIU+4ztQIgBD1EFNrQAgIpYSil9lDmPHqkROPt+JC6AgPquSuumJmg0YARVCuneDfvPVeJokZ6pIXDkNxQtGzTF9/BQjRG0tQznfb74RwCQghpALBtIQnfK4zhxdyQvVCUeknMIT3hLyY+T5jo0yABqKPQNpUNw/09tGZod5jgCaYFxyYvJcNPkv9eof+I3pnCFEHIETjSM8L9tHZHYCQT9PaZGycU6yg8S4akDnJ+P03L0+t23XGzCLzRgII/Wqa+fv/xlfvmKvMUOcOrlCDdoei1MGdZm6G5VEIfRzzjd4aQs69n699Rx7ewhvCGzr2gmTPs8zNsJOrXt24FbkhhOjCfT4ICA/rPbyhUy94Dks0gJCX1NzCZui9YUd3oei+c257TalFbgg19ILHrlrL2gvWgXAL26EX76gZTNASQnad8Ibwhl284NhgXpB0c+jKhWO3Ms1hP9ihJYB9eMF6qd1BCPk0qA1s+LimFIu7m4nsdQIzPK4VbQ8hYvrnuSH2G9b2ggP78QmWqBdF9Vx8SSY6QYdUW7BTA1schZATyhvY8lHvcRbNUS9YGFy2U+qmzh2YPVc0I7yAOFyHfRpyUwtCSzOdPXMHmz7qDIM0e0V2wZTEk+6Ym6N63eBLp/b5Bts+2cKCSJ/LuoZO3ANSiE5hKAZjnvNSS4931jcw9jpwT0feV/qSJ1pVtCyfHKDkvK8Ejx7pUxGh2xFNSwx8QTi2H9ceC0/nni64MS/5N5dG39pDqvRV+WgGk71c9VFXF9b+xYvOw/d61iv7m3MvEHryhvecwC52jSSx4VIIgwnMNT/UsTxIgpPt3K/ARj15CptwL3Zd/ceDSATj2DGQjbxgWwhdeMMte7zpy5On9vymRm/YxBYljGVjKWF9VJf7I1+sex3wY8w/V1QPTborW/72gkdsRDaZMJBdbdHIC7aCkAu9atlLbtnrzerMnyToDaGwelOnk3/hHSem/ZK7e/t7jeeR20LYBgqa8J80gS8jbwi5F02Uj1u2NYJxap8PLkJfLxA2hIJyvnHX/AfeEPLpBfe0uSFHbnXaea3Qd5d6HcpYZ8L6M7lnFwMQ3MNg+RxUR1+6AshtbsVgfXTEg1sIGax9UND2p7f270wdG3eK9gXVGHdw2k5sOyZv+Nbs39Z308XR9DqWb2J+PwKDhuKHPobfuXf7gnYGHdCs7bhDDadD4entDug7LWNsnRNW4mYqwJ9dk+GGSTPBiA2j0G8RWNM5upZtcG4/3vMfP7KnbK2egx6CCnDPhRn7NgD3cghLIad5WcM2SO38iqHvvMOosyeMpQ5zlVCaaj06GVs9xUbHdiKoqrHWgquFEFMWUEWfXUxJAML23hAHFOctmjZQffKD2pywkhtSGHKNtpitLroscAeE7kCkSsC60vxEl6yMtL9EL5HKGCMszU5bk8gdkklAyEn5FO0yK419rIxBOIqwFMooDE0tHEVYijAUECIshRCGIhxFWIowFJ5QkEYIS5PTJrUwNGlPyN6QQPyKtpuM1E/K5+YJDV/MiA3AaehzqgAm7QnZG9IGYKo8bHnSK7VblLL3hOwNHziPuEGOqE5brrdR6i+atCfckyeWD47HkAkepRGLY/e8A8J0gCwYSNypF08bBm+e6zVz2UL4AshhBUjML/rXLefqC82bcQFhGC9JDwZ1uuu+At0S5gCETYHsV4DUeD9fDN2Zfy5OXaW2zAwQygCzBLJ8cvaW5OXKC1FxfTggFAHmoAJnSiOw2wps9KwRWgJCLaEswaj5NqkLwAYIU4BxqTSXbHXpJdRMPZgAOiAMqABCNGYIEEJutEK5IUAIwYMDQgiCACEEAcJs1Vda7gGqDhCmoiEghAAhBAHCrKXVo2C1DCBMRlp37uMIEECoX7xrX3P5C9QiINSuIcoPAUI0YkAICLNWgfJDh4T9hH7zqYH9+JHAq7zBqWjwhPAicTVCVQJCNF50JghHocahKK0X/ZnQKyEkhSdUpzG8OgQI42qC94EQjsYLRSmH+pbgq73L6bYkeEJ4DYTYmeg1TOBFc/usTTp3V9DdEuXJ2xDCUbXhaXk0/kAYmBvuMB4qkC35E5e5AMKkwSQgyxufyuPy6fMMgAFCSI73LFXU/N8AmEL9X4ABACNSKMHAgb34AAAAAElFTkSuQmCC + mediatype: image/png + install: + spec: + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + labels: + name: etcd-operator-alm-owned + name: etcd-operator-alm-owned + spec: + containers: + - command: + - etcd-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2 + name: etcd-operator + - command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2 + name: etcd-backup-operator + - command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2 + name: etcd-restore-operator + serviceAccountName: etcd-operator + permissions: + - rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + verbs: + - '*' + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + serviceAccountName: etcd-operator + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: false + type: AllNamespaces + keywords: + - etcd + - key value + - database + - coreos + - open source + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + maintainers: + - email: etcd-dev@googlegroups.com + name: etcd Community + maturity: alpha + provider: + name: CNCF + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + version: 0.9.2 diff --git a/pkg/manifests/testdata/valid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml b/pkg/manifests/testdata/valid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5b851cd12 --- /dev/null +++ b/pkg/manifests/testdata/valid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdrestores.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdRestore + listKind: EtcdRestoreList + plural: etcdrestores + singular: etcdrestore + scope: Namespaced + version: v1beta2 diff --git a/pkg/manifests/testdata/valid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml b/pkg/manifests/testdata/valid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..d3d6a6533 --- /dev/null +++ b/pkg/manifests/testdata/valid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: etcdbackups.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdBackup + listKind: EtcdBackupList + plural: etcdbackups + singular: etcdbackup + scope: Namespaced + version: v1beta2 diff --git a/pkg/manifests/testdata/valid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml b/pkg/manifests/testdata/valid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..01111e5c5 --- /dev/null +++ b/pkg/manifests/testdata/valid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,16 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdclusters.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdCluster + listKind: EtcdClusterList + plural: etcdclusters + shortNames: + - etcdclus + - etcd + singular: etcdcluster + scope: Namespaced + version: v1beta2 diff --git a/pkg/manifests/testdata/valid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml b/pkg/manifests/testdata/valid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml new file mode 100644 index 000000000..56f414d66 --- /dev/null +++ b/pkg/manifests/testdata/valid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml @@ -0,0 +1,309 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdCluster\",\n \"metadata\": {\n \"name\": \"example\"\ + \n },\n \"spec\": {\n \"size\": 3,\n \"version\": \"3.2.13\"\ + \n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdRestore\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-restore\"\ + \n },\n \"spec\": {\n \"etcdCluster\": {\n \"name\": \"example-etcd-cluster\"\ + \n },\n \"backupStorageType\": \"S3\",\n \"s3\": {\n \"\ + path\": \"\",\n \"awsSecret\": \"\"\n \ + \ }\n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdBackup\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-backup\"\ + \n },\n \"spec\": {\n \"etcdEndpoints\": [\"\"\ + ],\n \"storageType\":\"S3\",\n \"s3\": {\n \"path\": \"\"\ + ,\n \"awsSecret\": \"\"\n }\n }\n }\n]\n" + capabilities: Full Lifecycle + categories: Database + containerImage: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + createdAt: 2019-02-28 01:03:00 + description: Create and maintain highly-available etcd clusters on Kubernetes + repository: https://github.com/coreos/etcd-operator + tectonic-visibility: ocs + name: etcdoperator.v0.9.4 + namespace: placeholder +spec: + customresourcedefinitions: + owned: + - description: Represents a cluster of etcd nodes. + displayName: etcd Cluster + kind: EtcdCluster + name: etcdclusters.etcd.database.coreos.com + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: Limits describes the minimum/maximum amount of compute resources + required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podStatuses + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Service + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: The target version of the etcd cluster, after upgrading. + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to backup an etcd cluster. + displayName: etcd Backup + kind: EtcdBackup + name: etcdbackups.etcd.database.coreos.com + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - urn:alm:descriptor:etcd:endpoint + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to restore an etcd cluster from a backup. + displayName: etcd Restore + kind: EtcdRestore + name: etcdrestores.etcd.database.coreos.com + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - urn:alm:descriptor:io.kubernetes:EtcdCluster + - urn:alm:descriptor:text + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + description: "The etcd Operater creates and maintains highly-available etcd clusters\ + \ on Kubernetes, allowing engineers to easily deploy and manage etcd clusters\ + \ for their applications.\n\netcd is a distributed key value store that provides\ + \ a reliable way to store data across a cluster of machines. It\xE2\u20AC\u2122\ + s open-source and available on GitHub. etcd gracefully handles leader elections\ + \ during network partitions and will tolerate machine failure, including the leader.\n\ + \n\n### Reading and writing to etcd\n\nCommunicate with etcd though its command\ + \ line utility `etcdctl` via port forwarding:\n\n $ kubectl --namespace default\ + \ port-forward service/example-client 2379:2379\n $ etcdctl --endpoints http://127.0.0.1:2379\ + \ get /\n\nOr directly to the API using the automatically generated Kubernetes\ + \ Service:\n\n $ etcdctl --endpoints http://example-client.default.svc:2379\ + \ get /\n\nBe sure to secure your etcd cluster (see Common Configurations) before\ + \ exposing it outside of the namespace or cluster.\n\n\n### Supported Features\n\ + \n* **High availability** - Multiple instances of etcd are networked together\ + \ and secured. Individual failures or networking issues are transparently handled\ + \ to keep your cluster up and running.\n\n* **Automated updates** - Rolling out\ + \ a new etcd version works like all Kubernetes rolling updates. Simply declare\ + \ the desired version, and the etcd service starts a safe rolling update to the\ + \ new version automatically.\n\n* **Backups included** - Create etcd backups and\ + \ restore them through the etcd Operator.\n\n### Common Configurations\n\n* **Configure\ + \ TLS** - Specify [static TLS certs](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md)\ + \ as Kubernetes secrets.\n\n* **Set Node Selector and Affinity** - [Spread your\ + \ etcd Pods](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-node-selector-and-anti-affinity-across-nodes)\ + \ across Nodes and availability zones.\n\n* **Set Resource Limits** - [Set the\ + \ Kubernetes limit and request](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-resource-requirement)\ + \ values for your etcd Pods.\n\n* **Customize Storage** - [Set a custom StorageClass](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#custom-persistentvolumeclaim-definition)\ + \ that you would like to use.\n" + displayName: etcd + icon: + - base64data: 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 + mediatype: image/png + install: + spec: + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + labels: + name: etcd-operator-alm-owned + name: etcd-operator-alm-owned + spec: + containers: + - command: + - etcd-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-operator + - command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-backup-operator + - command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-restore-operator + serviceAccountName: etcd-operator + permissions: + - rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + verbs: + - '*' + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + serviceAccountName: etcd-operator + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: false + type: AllNamespaces + keywords: + - etcd + - key value + - database + - coreos + - open source + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + maintainers: + - email: etcd-dev@googlegroups.com + name: etcd Community + maturity: alpha + provider: + name: CNCF + replaces: etcdoperator.v0.9.2 + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + version: 0.9.4 diff --git a/pkg/manifests/testdata/valid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml b/pkg/manifests/testdata/valid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5b851cd12 --- /dev/null +++ b/pkg/manifests/testdata/valid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdrestores.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdRestore + listKind: EtcdRestoreList + plural: etcdrestores + singular: etcdrestore + scope: Namespaced + version: v1beta2 diff --git a/pkg/manifests/testdata/valid_package/package.yaml b/pkg/manifests/testdata/valid_package/package.yaml new file mode 100644 index 000000000..cec7bc072 --- /dev/null +++ b/pkg/manifests/testdata/valid_package/package.yaml @@ -0,0 +1,5 @@ +channels: +- currentCSV: etcdoperator.v0.9.4 + name: singlenamespace-alpha +defaultChannel: singlenamespace-alpha +packageName: etcd diff --git a/pkg/validation/doc.go b/pkg/validation/doc.go index 079e4510a..5ab90e996 100644 --- a/pkg/validation/doc.go +++ b/pkg/validation/doc.go @@ -8,7 +8,7 @@ // by exported functions for missing mandatory and optional fields, // respectively. Each Error implements the error interface. // -// Manifest and Bundle format: https://github.com/operator-framework/operator-registry/#manifest-format +// Bundle format: https://github.com/operator-framework/operator-registry/#manifest-format // ClusterServiceVersion documentation: https://github.com/operator-framework/operator-lifecycle-manager/blob/master/Documentation/design/building-your-csv.md // Package manifest documentation: https://github.com/operator-framework/operator-lifecycle-manager#discovery-catalogs-and-automated-upgrades // CustomResourceDefinition documentation: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ diff --git a/pkg/validation/errors/error.go b/pkg/validation/errors/error.go index f1469f1c8..33e6f253c 100644 --- a/pkg/validation/errors/error.go +++ b/pkg/validation/errors/error.go @@ -42,9 +42,7 @@ func (r ManifestResult) HasWarn() bool { // https://godoc.org/k8s.io/apimachinery/pkg/util/validation/field // Error is an implementation of the 'error' interface, which represents a -// warning or an error in a yaml file. Error type is taken as is from -// https://github.com/operator-framework/operator-registry/blob/master/vendor/k8s.io/apimachinery/pkg/util/validation/field/errors.go#L31 -// to maintain compatibility with upstream. +// warning or an error in a yaml file. type Error struct { // Type is the ErrorType string constant that represents the kind of // error, ex. "MandatoryStructMissing", "I/O". diff --git a/pkg/validation/internal/bundle.go b/pkg/validation/internal/bundle.go new file mode 100644 index 000000000..318b35b94 --- /dev/null +++ b/pkg/validation/internal/bundle.go @@ -0,0 +1,66 @@ +package internal + +import ( + "fmt" + + "github.com/operator-framework/api/pkg/manifests" + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/api/pkg/validation/errors" + interfaces "github.com/operator-framework/api/pkg/validation/interfaces" +) + +var BundleValidator interfaces.Validator = interfaces.ValidatorFunc(validateBundles) + +func validateBundles(objs ...interface{}) (results []errors.ManifestResult) { + for _, obj := range objs { + switch v := obj.(type) { + case *manifests.Bundle: + results = append(results, validateBundle(v)) + } + } + return results +} + +func validateBundle(bundle *manifests.Bundle) (result errors.ManifestResult) { + result = validateOwnedCRDs(bundle, bundle.CSV) + result.Name = bundle.CSV.Spec.Version.String() + return result +} + +func validateOwnedCRDs(bundle *manifests.Bundle, csv *operatorsv1alpha1.ClusterServiceVersion) (result errors.ManifestResult) { + ownedCrdNames := getOwnedCustomResourceDefintionNames(csv) + crdNames, err := getBundleCRDNames(bundle) + if err != (errors.Error{}) { + result.Add(err) + return result + } + + // validating names + for _, crdName := range ownedCrdNames { + if _, ok := crdNames[crdName]; !ok { + result.Add(errors.ErrInvalidBundle(fmt.Sprintf("owned CRD %q not found in bundle %q", crdName, bundle.Name), crdName)) + } else { + delete(crdNames, crdName) + } + } + // CRDs not defined in the CSV present in the bundle + for crdName := range crdNames { + result.Add(errors.WarnInvalidBundle(fmt.Sprintf("owned CRD %q is present in bundle %q but not defined in CSV", crdName, bundle.Name), crdName)) + } + return result +} + +func getOwnedCustomResourceDefintionNames(csv *operatorsv1alpha1.ClusterServiceVersion) (names []string) { + for _, ownedCrd := range csv.Spec.CustomResourceDefinitions.Owned { + names = append(names, ownedCrd.Name) + } + return names +} + +func getBundleCRDNames(bundle *manifests.Bundle) (map[string]struct{}, errors.Error) { + crdNames := map[string]struct{}{} + for _, crd := range bundle.V1beta1CRDs { + crdNames[crd.GetName()] = struct{}{} + } + return crdNames, errors.Error{} +} diff --git a/pkg/validation/internal/bundle_test.go b/pkg/validation/internal/bundle_test.go new file mode 100644 index 000000000..f19286126 --- /dev/null +++ b/pkg/validation/internal/bundle_test.go @@ -0,0 +1,51 @@ +package internal + +import ( + "testing" + + "github.com/operator-framework/api/pkg/manifests" + + "github.com/stretchr/testify/require" +) + +func TestValidateBundle(t *testing.T) { + var table = []struct { + description string + directory string + hasError bool + errString string + }{ + { + description: "registryv1 bundle/valid bundle", + directory: "./testdata/valid_bundle", + hasError: false, + }, + { + description: "registryv1 bundle/valid bundle", + directory: "./testdata/invalid_bundle", + hasError: true, + errString: `owned CRD "etcdclusters.etcd.database.coreos.com" not found in bundle`, + }, + { + description: "registryv1 bundle/valid bundle", + directory: "./testdata/invalid_bundle_2", + hasError: true, + errString: `owned CRD "etcdclusters.etcd.database.coreos.com" is present in bundle "etcdoperator.v0.9.4" but not defined in CSV`, + }, + } + + for _, tt := range table { + // Validate the bundle object + bundle, err := manifests.GetBundleFromDir(tt.directory) + require.NoError(t, err) + + results := BundleValidator.Validate(bundle) + + if len(results) > 0 { + require.Equal(t, results[0].HasError(), tt.hasError) + if results[0].HasError() { + require.Contains(t, results[0].Errors[0].Error(), tt.errString) + } + } + } +} diff --git a/pkg/validation/internal/csv.go b/pkg/validation/internal/csv.go index 39674708b..7e4d4863a 100644 --- a/pkg/validation/internal/csv.go +++ b/pkg/validation/internal/csv.go @@ -1,7 +1,6 @@ package internal import ( - "encoding/json" "fmt" "io" "reflect" @@ -12,7 +11,6 @@ import ( "github.com/blang/semver" "github.com/operator-framework/api/pkg/operators/v1alpha1" - "github.com/operator-framework/operator-registry/pkg/registry" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" k8svalidation "k8s.io/apimachinery/pkg/util/validation" @@ -26,22 +24,11 @@ func validateCSVs(objs ...interface{}) (results []errors.ManifestResult) { switch v := obj.(type) { case *v1alpha1.ClusterServiceVersion: results = append(results, validateCSV(v)) - case *registry.ClusterServiceVersion: - results = append(results, validateCSVRegistry(v)) } } return results } -func validateCSVRegistry(bcsv *registry.ClusterServiceVersion) (result errors.ManifestResult) { - csv, err := bundleCSVToCSV(bcsv) - if err != (errors.Error{}) { - result.Add(err) - return result - } - return validateCSV(csv) -} - // Iterates over the given CSV. Returns a ManifestResult type object. func validateCSV(csv *v1alpha1.ClusterServiceVersion) errors.ManifestResult { result := errors.ManifestResult{Name: csv.GetName()} @@ -187,15 +174,3 @@ func validateInstallModes(csv *v1alpha1.ClusterServiceVersion) (errs []errors.Er } return errs } - -func bundleCSVToCSV(bcsv *registry.ClusterServiceVersion) (*v1alpha1.ClusterServiceVersion, errors.Error) { - spec := v1alpha1.ClusterServiceVersionSpec{} - if err := json.Unmarshal(bcsv.Spec, &spec); err != nil { - return nil, errors.ErrInvalidParse(fmt.Sprintf("converting bundle CSV %q", bcsv.GetName()), err) - } - return &v1alpha1.ClusterServiceVersion{ - TypeMeta: bcsv.TypeMeta, - ObjectMeta: bcsv.ObjectMeta, - Spec: spec, - }, errors.Error{} -} diff --git a/pkg/validation/internal/csv_test.go b/pkg/validation/internal/csv_test.go index feb99567b..41f4ad0d5 100644 --- a/pkg/validation/internal/csv_test.go +++ b/pkg/validation/internal/csv_test.go @@ -5,10 +5,10 @@ import ( "path/filepath" "testing" + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/api/pkg/validation/errors" "github.com/ghodss/yaml" - "github.com/operator-framework/operator-registry/pkg/registry" ) func TestValidateCSV(t *testing.T) { @@ -24,15 +24,13 @@ func TestValidateCSV(t *testing.T) { }, { validatorFuncTest{ - description: "data type mismatch", + description: "invalid install modes", wantErr: true, errors: []errors.Error{ - errors.ErrInvalidParse( - `converting bundle CSV "etcdoperator.v0.9.0"`, - "json: cannot unmarshal string into Go struct field ClusterServiceVersionSpec.maintainers of type []v1alpha1.Maintainer"), + errors.ErrInvalidCSV("install modes not found", "etcdoperator.v0.9.0"), }, }, - filepath.Join("testdata", "dataTypeMismatch.csv.yaml"), + filepath.Join("testdata", "noInstallMode.csv.yaml"), }, } for _, c := range cases { @@ -40,11 +38,11 @@ func TestValidateCSV(t *testing.T) { if err != nil { t.Fatalf("Error reading CSV path %s: %v", c.csvPath, err) } - csv := registry.ClusterServiceVersion{} + csv := operatorsv1alpha1.ClusterServiceVersion{} if err = yaml.Unmarshal(b, &csv); err != nil { t.Fatalf("Error unmarshalling CSV at path %s: %v", c.csvPath, err) } - result := validateCSVRegistry(&csv) + result := validateCSV(&csv) c.check(t, result) } } diff --git a/pkg/validation/internal/manifests.go b/pkg/validation/internal/manifests.go deleted file mode 100644 index 4b65d1318..000000000 --- a/pkg/validation/internal/manifests.go +++ /dev/null @@ -1,206 +0,0 @@ -package internal - -import ( - "fmt" - - "github.com/operator-framework/api/pkg/validation/errors" - interfaces "github.com/operator-framework/api/pkg/validation/interfaces" - - "github.com/blang/semver" - "github.com/operator-framework/operator-registry/pkg/registry" -) - -const skipPackageAnnotationKey = "olm.skipRange" - -var PackageUpdateGraphValidator interfaces.Validator = interfaces.ValidatorFunc(validatePackageUpdateGraphs) - -func validatePackageUpdateGraphs(objs ...interface{}) (results []errors.ManifestResult) { - var pkg *registry.PackageManifest - bundles := []*registry.Bundle{} - for _, obj := range objs { - switch v := obj.(type) { - case *registry.PackageManifest: - if pkg == nil { - pkg = v - } - case *registry.Bundle: - bundles = append(bundles, v) - } - } - if pkg != nil && len(bundles) > 0 { - results = append(results, validatePackageUpdateGraph(pkg, bundles)) - } - return results -} - -func validatePackageUpdateGraph(pkg *registry.PackageManifest, bundles []*registry.Bundle) (result errors.ManifestResult) { - // Collect all CSV names and ensure no duplicates. We will use these names - // to check whether a spec.replaces references an existing CSV in bundles. - csvNameMap := map[string]struct{}{} - for _, bundle := range bundles { - csv, err := bundle.ClusterServiceVersion() - if err != nil { - result.Add(errors.ErrInvalidParse("error getting bundle CSV", err)) - return result - } - if _, seenCSV := csvNameMap[csv.GetName()]; seenCSV { - result.Add(errors.ErrInvalidCSV("duplicate CSV in bundle set", csv.GetName())) - return result - } else { - csvNameMap[csv.GetName()] = struct{}{} - } - } - - // Check that all CSV fields follow package graph invariants. - replacesGraph, replacesSet := map[string]string{}, map[string]struct{}{} - for _, bundle := range bundles { - // We already know each CSV in bundles can be marshalled correctly. - csv, _ := bundle.ClusterServiceVersion() - - // spec.replaces, if present: - // - Must be a valid Kubernetes resource name. - // - Should reference the name of a CSV defined by another bundle. - replaces, err := csv.GetReplaces() - if err != nil { - result.Add(errors.ErrInvalidParse("error getting spec.replaces from bundle CSV", err)) - return result - } - replacesGraph[csv.GetName()] = replaces - if replaces != "" { - if _, seen := replacesSet[replaces]; seen { - result.Add(errors.ErrInvalidCSV( - fmt.Sprintf("spec.replaces %q referenced by more than one CSV", replaces), - csv.GetName())) - return result - } - replacesSet[replaces] = struct{}{} - - if _, _, err = parseCSVNameFormat(replaces); err != nil { - result.Add(errors.ErrInvalidCSV(fmt.Sprintf("spec.replaces %s", err), csv.GetName())) - } - if csv.GetName() == replaces { - result.Add(errors.ErrInvalidCSV( - "spec.replaces field cannot match its own metadata.name.", csv.GetName())) - } - if _, replacesInBundles := csvNameMap[replaces]; !replacesInBundles { - result.Add(errors.WarnInvalidCSV( - fmt.Sprintf("spec.replaces %q CSV is not present in manifests", replaces), - csv.GetName())) - } - } - - // spec.skips, if present: - // - Must contain valid Kubernetes resource names. - // - Must not contain an element matching spec.replaces. - skips, err := csv.GetSkips() - if err != nil { - result.Add(errors.ErrInvalidParse("error getting spec.skips from bundle CSV", err)) - return result - } - for i, skip := range skips { - if _, _, err = parseCSVNameFormat(skip); err != nil { - result.Add(errors.ErrInvalidCSV( - fmt.Sprintf("spec.skips[%d] %s", i, err), csv.GetName())) - } - if skip == replaces && replaces != "" { - result.Add(errors.ErrInvalidCSV( - fmt.Sprintf("spec.skips[%d] %q cannot match spec.replaces", i, skip), - csv.GetName())) - } - } - - // metadata.annotations["olm.skipRange"], if present: - // - Must be a valid semver range. - // - Must not be inclusive of its CSV’s version. - skipRange, rerr := parseSkipRange(csv) - if rerr != (errors.Error{}) { - result.Add(rerr) - return result - } - if skipRange != nil { - csvVerStr, err := csv.GetVersion() - if err != nil { - result.Add(errors.ErrInvalidParse("error getting spec.version from bundle CSV", err)) - } - csvVer, err := semver.Parse(csvVerStr) - if err != nil { - result.Add(errors.ErrInvalidParse("error parsing spec.version", err)) - } - if skipRange(csvVer) { - result.Add(errors.ErrInvalidCSV( - fmt.Sprintf("metadata.annotations[\"%s\"] range contains the CSV's version", - skipPackageAnnotationKey), - csv.GetName())) - } - } - } - - // Ensure no spec.replaces reference parent CSV's. - result.Add(checkReplacesGraphForCycles(replacesGraph)...) - // Ensure all channels reference existing CSV's. - result.Add(checkChannelInBundle(pkg, replacesGraph)...) - return result -} - -func parseSkipRange(csv *registry.ClusterServiceVersion) (semver.Range, errors.Error) { - if csv.GetAnnotations() != nil { - if skipRangeStr, ok := csv.GetAnnotations()[skipPackageAnnotationKey]; ok { - skipRange, err := semver.ParseRange(skipRangeStr) - if err != nil { - return nil, errors.ErrInvalidCSV( - fmt.Sprintf("metadata.annotations[\"%s\"] %q is an invalid semantic version range", - skipPackageAnnotationKey, skipRangeStr), - csv.GetName()) - } - return skipRange, errors.Error{} - } - } - return nil, errors.Error{} -} - -// checkReplacesGraphForCycles ensures no cycles occur in spec.replaces -// references. No spec.replaces should reference a parent CSV in the graph. -func checkReplacesGraphForCycles(graph map[string]string) (errs []errors.Error) { - for csvName, replaces := range graph { - currReplaces := replaces - currCSVName := csvName - for { - newReplaces, ok := graph[currReplaces] - if ok { - if newReplaces == "" { - break - } - if newReplaces == csvName { - errs = append(errs, errors.ErrInvalidCSV( - fmt.Sprintf("spec.replaces %q references a parent in CSV replace chain", - newReplaces), - currReplaces)) - break - } - currCSVName = currReplaces - currReplaces = newReplaces - } else { - errs = append(errs, errors.ErrInvalidCSV( - fmt.Sprintf("spec.replaces %q does not map to a CSV in bundles", - currReplaces), - currCSVName)) - break - } - } - } - return errs -} - -// checkChannelInBundle ensures that each package channel's currentCSV exists -// in one bundle. -func checkChannelInBundle(pkg *registry.PackageManifest, csvNames map[string]string) (errs []errors.Error) { - for _, channel := range pkg.Channels { - if _, csvExists := csvNames[channel.CurrentCSVName]; !csvExists { - errs = append(errs, errors.ErrInvalidPackageManifest( - fmt.Sprintf("currentCSV %q for channel name %q not found in bundle", - channel.CurrentCSVName, channel.Name), - pkg.PackageName)) - } - } - return errs -} diff --git a/pkg/validation/internal/package_manifest.go b/pkg/validation/internal/package_manifest.go index a4dfd6ce6..05317bcce 100644 --- a/pkg/validation/internal/package_manifest.go +++ b/pkg/validation/internal/package_manifest.go @@ -3,10 +3,9 @@ package internal import ( "fmt" + "github.com/operator-framework/api/pkg/manifests" "github.com/operator-framework/api/pkg/validation/errors" interfaces "github.com/operator-framework/api/pkg/validation/interfaces" - - "github.com/operator-framework/operator-registry/pkg/registry" ) var PackageManifestValidator interfaces.Validator = interfaces.ValidatorFunc(validatePackageManifests) @@ -14,20 +13,20 @@ var PackageManifestValidator interfaces.Validator = interfaces.ValidatorFunc(val func validatePackageManifests(objs ...interface{}) (results []errors.ManifestResult) { for _, obj := range objs { switch v := obj.(type) { - case *registry.PackageManifest: + case *manifests.PackageManifest: results = append(results, validatePackageManifest(v)) } } return results } -func validatePackageManifest(pkg *registry.PackageManifest) errors.ManifestResult { +func validatePackageManifest(pkg *manifests.PackageManifest) errors.ManifestResult { result := errors.ManifestResult{Name: pkg.PackageName} result.Add(validateChannels(pkg)...) return result } -func validateChannels(pkg *registry.PackageManifest) (errs []errors.Error) { +func validateChannels(pkg *manifests.PackageManifest) (errs []errors.Error) { if pkg.PackageName == "" { errs = append(errs, errors.ErrInvalidPackageManifest("packageName empty", pkg.PackageName)) } diff --git a/pkg/validation/internal/package_manifest_test.go b/pkg/validation/internal/package_manifest_test.go index 835f074f3..0b79ce4b5 100644 --- a/pkg/validation/internal/package_manifest_test.go +++ b/pkg/validation/internal/package_manifest_test.go @@ -3,8 +3,8 @@ package internal import ( "testing" + "github.com/operator-framework/api/pkg/manifests" "github.com/operator-framework/api/pkg/validation/errors" - "github.com/operator-framework/operator-registry/pkg/registry" ) func TestValidatePackageManifest(t *testing.T) { @@ -12,14 +12,14 @@ func TestValidatePackageManifest(t *testing.T) { cases := []struct { validatorFuncTest - pkg *registry.PackageManifest + pkg *manifests.PackageManifest }{ { validatorFuncTest{ description: "successful validation", }, - ®istry.PackageManifest{ - Channels: []registry.PackageChannel{ + &manifests.PackageManifest{ + Channels: []manifests.PackageChannel{ {Name: "foo", CurrentCSVName: "bar"}, }, DefaultChannelName: "foo", @@ -30,8 +30,8 @@ func TestValidatePackageManifest(t *testing.T) { validatorFuncTest{ description: "successful validation no default channel with only one channel", }, - ®istry.PackageManifest{ - Channels: []registry.PackageChannel{ + &manifests.PackageManifest{ + Channels: []manifests.PackageChannel{ {Name: "foo", CurrentCSVName: "bar"}, }, PackageName: "test-package", @@ -45,8 +45,8 @@ func TestValidatePackageManifest(t *testing.T) { errors.ErrInvalidPackageManifest("default channel is empty but more than one channel exists", pkgName), }, }, - ®istry.PackageManifest{ - Channels: []registry.PackageChannel{ + &manifests.PackageManifest{ + Channels: []manifests.PackageChannel{ {Name: "foo", CurrentCSVName: "bar"}, {Name: "foo2", CurrentCSVName: "baz"}, }, @@ -61,8 +61,8 @@ func TestValidatePackageManifest(t *testing.T) { errors.ErrInvalidPackageManifest(`default channel "baz" not found in the list of declared channels`, pkgName), }, }, - ®istry.PackageManifest{ - Channels: []registry.PackageChannel{ + &manifests.PackageManifest{ + Channels: []manifests.PackageChannel{ {Name: "foo", CurrentCSVName: "bar"}, }, DefaultChannelName: "baz", @@ -77,7 +77,7 @@ func TestValidatePackageManifest(t *testing.T) { errors.ErrInvalidPackageManifest("channels empty", pkgName), }, }, - ®istry.PackageManifest{ + &manifests.PackageManifest{ Channels: nil, DefaultChannelName: "baz", PackageName: "test-package", @@ -91,8 +91,8 @@ func TestValidatePackageManifest(t *testing.T) { errors.ErrInvalidPackageManifest(`channel "foo" currentCSV is empty`, pkgName), }, }, - ®istry.PackageManifest{ - Channels: []registry.PackageChannel{{Name: "foo"}}, + &manifests.PackageManifest{ + Channels: []manifests.PackageChannel{{Name: "foo"}}, DefaultChannelName: "foo", PackageName: "test-package", }, @@ -105,8 +105,8 @@ func TestValidatePackageManifest(t *testing.T) { errors.ErrInvalidPackageManifest(`duplicate package manifest channel name "foo"`, pkgName), }, }, - ®istry.PackageManifest{ - Channels: []registry.PackageChannel{ + &manifests.PackageManifest{ + Channels: []manifests.PackageChannel{ {Name: "foo", CurrentCSVName: "bar"}, {Name: "foo", CurrentCSVName: "baz"}, }, diff --git a/pkg/validation/internal/testdata/noInstallMode.csv.yaml b/pkg/validation/internal/testdata/noInstallMode.csv.yaml new file mode 100644 index 000000000..f6d3e9297 --- /dev/null +++ b/pkg/validation/internal/testdata/noInstallMode.csv.yaml @@ -0,0 +1,283 @@ +#! validate-crd: deploy/chart/templates/0000_30_02-clusterserviceversion.crd.yaml +#! parse-kind: ClusterServiceVersion +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + name: etcdoperator.v0.9.0 + namespace: placeholder + annotations: + capabilities: Full Lifecycle + tectonic-visibility: ocs + alm-examples: '[{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"","awsSecret":""}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":[""],"storageType":"S3","s3":{"path":"","awsSecret":""}}}]' + description: etcd is a distributed key value store providing a reliable way to store data across a cluster of machines. +spec: + displayName: etcd + description: | + etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd. + A simple use-case is to store database connection details or feature flags within etcd as key value pairs. These values can be watched, allowing your app to reconfigure itself when they change. Advanced uses take advantage of the consistency guarantees to implement database leader elections or do distributed locking across a cluster of workers. + + _The etcd Open Cloud Service is Public Alpha. The goal before Beta is to fully implement backup features._ + + ### Reading and writing to etcd + + Communicate with etcd though its command line utility `etcdctl` or with the API using the automatically generated Kubernetes Service. + + [Read the complete guide to using the etcd Open Cloud Service](https://coreos.com/tectonic/docs/latest/alm/etcd-ocs.html) + + ### Supported Features + + + **High availability** + + + Multiple instances of etcd are networked together and secured. Individual failures or networking issues are transparently handled to keep your cluster up and running. + + + **Automated updates** + + + Rolling out a new etcd version works like all Kubernetes rolling updates. Simply declare the desired version, and the etcd service starts a safe rolling update to the new version automatically. + + + **Backups included** + + + Coming soon, the ability to schedule backups to happen on or off cluster. + keywords: ['etcd', 'key value', 'database', 'coreos', 'open source'] + version: 0.9.0 + maturity: alpha + maintainers: + - name: CoreOS, Inc + email: support@coreos.com + + provider: + name: CoreOS, Inc + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + + icon: + - base64data: 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 + mediatype: image/png + install: + strategy: deployment + spec: + permissions: + - serviceAccountName: etcd-operator + rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - "*" + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - "*" + - apiGroups: + - apps + resources: + - deployments + verbs: + - "*" + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + name: etcd-operator-alm-owned + labels: + name: etcd-operator-alm-owned + spec: + serviceAccountName: etcd-operator + containers: + - name: etcd-operator + command: + - etcd-operator + - --create-crd=false + image: quay.io/coreos/etcd-operator@sha256:db563baa8194fcfe39d1df744ed70024b0f1f9e9b55b5923c2f3a413c44dc6b8 + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: etcd-backup-operator + image: quay.io/coreos/etcd-operator@sha256:db563baa8194fcfe39d1df744ed70024b0f1f9e9b55b5923c2f3a413c44dc6b8 + command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: etcd-restore-operator + image: quay.io/coreos/etcd-operator@sha256:db563baa8194fcfe39d1df744ed70024b0f1f9e9b55b5923c2f3a413c44dc6b8 + command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + customresourcedefinitions: + owned: + - name: etcdclusters.etcd.database.coreos.com + version: v1beta2 + kind: EtcdCluster + displayName: etcd Cluster + description: Represents a cluster of etcd nodes. + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:podCount' + - description: Limits describes the minimum/maximum amount of compute resources required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:resourceRequirements' + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:podStatuses' + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes:Service' + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: 'The target version of the etcd cluster, after upgrading.' + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes.phase' + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes.phase:reason' + - name: etcdbackups.etcd.database.coreos.com + version: v1beta2 + kind: EtcdBackup + displayName: etcd Backup + description: Represents the intent to backup an etcd cluster. + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - 'urn:alm:descriptor:etcd:endpoint' + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - 'urn:alm:descriptor:aws:s3:path' + - description: The name of the secret object that stores the AWS credential and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes:Secret' + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - 'urn:alm:descriptor:text' + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes.phase:reason' + - name: etcdrestores.etcd.database.coreos.com + version: v1beta2 + kind: EtcdRestore + displayName: etcd Restore + description: Represents the intent to restore an etcd cluster from a backup. + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes:EtcdCluster' + - 'urn:alm:descriptor:text' + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - 'urn:alm:descriptor:aws:s3:path' + - description: The name of the secret object that stores the AWS credential and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes:Secret' + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - 'urn:alm:descriptor:text' + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes.phase:reason' \ No newline at end of file diff --git a/pkg/validation/testdata/invalid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/invalid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5afc088b9 --- /dev/null +++ b/pkg/validation/testdata/invalid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdbackups.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdBackup + listKind: EtcdBackupList + plural: etcdbackups + singular: etcdbackup + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/invalid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml b/pkg/validation/testdata/invalid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml new file mode 100644 index 000000000..56f414d66 --- /dev/null +++ b/pkg/validation/testdata/invalid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml @@ -0,0 +1,309 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdCluster\",\n \"metadata\": {\n \"name\": \"example\"\ + \n },\n \"spec\": {\n \"size\": 3,\n \"version\": \"3.2.13\"\ + \n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdRestore\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-restore\"\ + \n },\n \"spec\": {\n \"etcdCluster\": {\n \"name\": \"example-etcd-cluster\"\ + \n },\n \"backupStorageType\": \"S3\",\n \"s3\": {\n \"\ + path\": \"\",\n \"awsSecret\": \"\"\n \ + \ }\n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdBackup\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-backup\"\ + \n },\n \"spec\": {\n \"etcdEndpoints\": [\"\"\ + ],\n \"storageType\":\"S3\",\n \"s3\": {\n \"path\": \"\"\ + ,\n \"awsSecret\": \"\"\n }\n }\n }\n]\n" + capabilities: Full Lifecycle + categories: Database + containerImage: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + createdAt: 2019-02-28 01:03:00 + description: Create and maintain highly-available etcd clusters on Kubernetes + repository: https://github.com/coreos/etcd-operator + tectonic-visibility: ocs + name: etcdoperator.v0.9.4 + namespace: placeholder +spec: + customresourcedefinitions: + owned: + - description: Represents a cluster of etcd nodes. + displayName: etcd Cluster + kind: EtcdCluster + name: etcdclusters.etcd.database.coreos.com + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: Limits describes the minimum/maximum amount of compute resources + required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podStatuses + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Service + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: The target version of the etcd cluster, after upgrading. + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to backup an etcd cluster. + displayName: etcd Backup + kind: EtcdBackup + name: etcdbackups.etcd.database.coreos.com + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - urn:alm:descriptor:etcd:endpoint + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to restore an etcd cluster from a backup. + displayName: etcd Restore + kind: EtcdRestore + name: etcdrestores.etcd.database.coreos.com + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - urn:alm:descriptor:io.kubernetes:EtcdCluster + - urn:alm:descriptor:text + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + description: "The etcd Operater creates and maintains highly-available etcd clusters\ + \ on Kubernetes, allowing engineers to easily deploy and manage etcd clusters\ + \ for their applications.\n\netcd is a distributed key value store that provides\ + \ a reliable way to store data across a cluster of machines. It\xE2\u20AC\u2122\ + s open-source and available on GitHub. etcd gracefully handles leader elections\ + \ during network partitions and will tolerate machine failure, including the leader.\n\ + \n\n### Reading and writing to etcd\n\nCommunicate with etcd though its command\ + \ line utility `etcdctl` via port forwarding:\n\n $ kubectl --namespace default\ + \ port-forward service/example-client 2379:2379\n $ etcdctl --endpoints http://127.0.0.1:2379\ + \ get /\n\nOr directly to the API using the automatically generated Kubernetes\ + \ Service:\n\n $ etcdctl --endpoints http://example-client.default.svc:2379\ + \ get /\n\nBe sure to secure your etcd cluster (see Common Configurations) before\ + \ exposing it outside of the namespace or cluster.\n\n\n### Supported Features\n\ + \n* **High availability** - Multiple instances of etcd are networked together\ + \ and secured. Individual failures or networking issues are transparently handled\ + \ to keep your cluster up and running.\n\n* **Automated updates** - Rolling out\ + \ a new etcd version works like all Kubernetes rolling updates. Simply declare\ + \ the desired version, and the etcd service starts a safe rolling update to the\ + \ new version automatically.\n\n* **Backups included** - Create etcd backups and\ + \ restore them through the etcd Operator.\n\n### Common Configurations\n\n* **Configure\ + \ TLS** - Specify [static TLS certs](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md)\ + \ as Kubernetes secrets.\n\n* **Set Node Selector and Affinity** - [Spread your\ + \ etcd Pods](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-node-selector-and-anti-affinity-across-nodes)\ + \ across Nodes and availability zones.\n\n* **Set Resource Limits** - [Set the\ + \ Kubernetes limit and request](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-resource-requirement)\ + \ values for your etcd Pods.\n\n* **Customize Storage** - [Set a custom StorageClass](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#custom-persistentvolumeclaim-definition)\ + \ that you would like to use.\n" + displayName: etcd + icon: + - base64data: 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 + mediatype: image/png + install: + spec: + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + labels: + name: etcd-operator-alm-owned + name: etcd-operator-alm-owned + spec: + containers: + - command: + - etcd-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-operator + - command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-backup-operator + - command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-restore-operator + serviceAccountName: etcd-operator + permissions: + - rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + verbs: + - '*' + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + serviceAccountName: etcd-operator + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: false + type: AllNamespaces + keywords: + - etcd + - key value + - database + - coreos + - open source + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + maintainers: + - email: etcd-dev@googlegroups.com + name: etcd Community + maturity: alpha + provider: + name: CNCF + replaces: etcdoperator.v0.9.2 + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + version: 0.9.4 diff --git a/pkg/validation/testdata/invalid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/invalid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5b851cd12 --- /dev/null +++ b/pkg/validation/testdata/invalid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdrestores.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdRestore + listKind: EtcdRestoreList + plural: etcdrestores + singular: etcdrestore + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/invalid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/invalid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5afc088b9 --- /dev/null +++ b/pkg/validation/testdata/invalid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdbackups.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdBackup + listKind: EtcdBackupList + plural: etcdbackups + singular: etcdbackup + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/invalid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/invalid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..01111e5c5 --- /dev/null +++ b/pkg/validation/testdata/invalid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,16 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdclusters.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdCluster + listKind: EtcdClusterList + plural: etcdclusters + shortNames: + - etcdclus + - etcd + singular: etcdcluster + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/invalid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml b/pkg/validation/testdata/invalid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml new file mode 100644 index 000000000..efc209da6 --- /dev/null +++ b/pkg/validation/testdata/invalid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml @@ -0,0 +1,305 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdCluster\",\n \"metadata\": {\n \"name\": \"example\"\ + \n },\n \"spec\": {\n \"size\": 3,\n \"version\": \"3.2.13\"\ + \n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdRestore\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-restore\"\ + \n },\n \"spec\": {\n \"etcdCluster\": {\n \"name\": \"example-etcd-cluster\"\ + \n },\n \"backupStorageType\": \"S3\",\n \"s3\": {\n \"\ + path\": \"\",\n \"awsSecret\": \"\"\n \ + \ }\n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdBackup\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-backup\"\ + \n },\n \"spec\": {\n \"etcdEndpoints\": [\"\"\ + ],\n \"storageType\":\"S3\",\n \"s3\": {\n \"path\": \"\"\ + ,\n \"awsSecret\": \"\"\n }\n }\n }\n]\n" + capabilities: Full Lifecycle + categories: Database + description: Creates and maintain highly-available etcd clusters on Kubernetes + tectonic-visibility: ocs + name: etcdoperator.v0.9.2 + namespace: placeholder +spec: + customresourcedefinitions: + owned: + - description: Represents a cluster of etcd nodes. + displayName: etcd Cluster + kind: EtcdCluster + name: etcdclusters.etcd.database.coreos.com + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: Limits describes the minimum/maximum amount of compute resources + required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podStatuses + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Service + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: The target version of the etcd cluster, after upgrading. + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to backup an etcd cluster. + displayName: etcd Backup + kind: EtcdBackup + name: etcdbackups.etcd.database.coreos.com + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - urn:alm:descriptor:etcd:endpoint + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to restore an etcd cluster from a backup. + displayName: etcd Restore + kind: EtcdRestore + name: etcdrestores.etcd.database.coreos.com + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - urn:alm:descriptor:io.kubernetes:EtcdCluster + - urn:alm:descriptor:text + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + description: "The etcd Operater creates and maintains highly-available etcd clusters\ + \ on Kubernetes, allowing engineers to easily deploy and manage etcd clusters\ + \ for their applications.\n\netcd is a distributed key value store that provides\ + \ a reliable way to store data across a cluster of machines. It\xE2\u20AC\u2122\ + s open-source and available on GitHub. etcd gracefully handles leader elections\ + \ during network partitions and will tolerate machine failure, including the leader.\n\ + \n\n### Reading and writing to etcd\n\nCommunicate with etcd though its command\ + \ line utility `etcdctl` via port forwarding:\n\n $ kubectl --namespace default\ + \ port-forward service/example-client 2379:2379\n $ etcdctl --endpoints http://127.0.0.1:2379\ + \ get /\n\nOr directly to the API using the automatically generated Kubernetes\ + \ Service:\n\n $ etcdctl --endpoints http://example-client.default.svc:2379\ + \ get /\n\nBe sure to secure your etcd cluster (see Common Configurations) before\ + \ exposing it outside of the namespace or cluster.\n\n\n### Supported Features\n\ + \n* **High availability** - Multiple instances of etcd are networked together\ + \ and secured. Individual failures or networking issues are transparently handled\ + \ to keep your cluster up and running.\n\n* **Automated updates** - Rolling out\ + \ a new etcd version works like all Kubernetes rolling updates. Simply declare\ + \ the desired version, and the etcd service starts a safe rolling update to the\ + \ new version automatically.\n\n* **Backups included** - Create etcd backups and\ + \ restore them through the etcd Operator.\n\n### Common Configurations\n\n* **Configure\ + \ TLS** - Specify [static TLS certs](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md)\ + \ as Kubernetes secrets.\n\n* **Set Node Selector and Affinity** - [Spread your\ + \ etcd Pods](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-node-selector-and-anti-affinity-across-nodes)\ + \ across Nodes and availability zones.\n\n* **Set Resource Limits** - [Set the\ + \ Kubernetes limit and request](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-resource-requirement)\ + \ values for your etcd Pods.\n\n* **Customize Storage** - [Set a custom StorageClass](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#custom-persistentvolumeclaim-definition)\ + \ that you would like to use.\n" + displayName: etcd + icon: + - base64data: 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 + mediatype: image/png + install: + spec: + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + labels: + name: etcd-operator-alm-owned + name: etcd-operator-alm-owned + spec: + containers: + - command: + - etcd-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2 + name: etcd-operator + - command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2 + name: etcd-backup-operator + - command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2 + name: etcd-restore-operator + serviceAccountName: etcd-operator + permissions: + - rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + verbs: + - '*' + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + serviceAccountName: etcd-operator + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: false + type: AllNamespaces + keywords: + - etcd + - key value + - database + - coreos + - open source + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + maintainers: + - email: etcd-dev@googlegroups.com + name: etcd Community + maturity: alpha + provider: + name: CNCF + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + version: 0.9.2 diff --git a/pkg/validation/testdata/invalid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/invalid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5b851cd12 --- /dev/null +++ b/pkg/validation/testdata/invalid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdrestores.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdRestore + listKind: EtcdRestoreList + plural: etcdrestores + singular: etcdrestore + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/invalid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/invalid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5afc088b9 --- /dev/null +++ b/pkg/validation/testdata/invalid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdbackups.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdBackup + listKind: EtcdBackupList + plural: etcdbackups + singular: etcdbackup + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/invalid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/invalid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..01111e5c5 --- /dev/null +++ b/pkg/validation/testdata/invalid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,16 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdclusters.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdCluster + listKind: EtcdClusterList + plural: etcdclusters + shortNames: + - etcdclus + - etcd + singular: etcdcluster + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/invalid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml b/pkg/validation/testdata/invalid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml new file mode 100644 index 000000000..56f414d66 --- /dev/null +++ b/pkg/validation/testdata/invalid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml @@ -0,0 +1,309 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdCluster\",\n \"metadata\": {\n \"name\": \"example\"\ + \n },\n \"spec\": {\n \"size\": 3,\n \"version\": \"3.2.13\"\ + \n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdRestore\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-restore\"\ + \n },\n \"spec\": {\n \"etcdCluster\": {\n \"name\": \"example-etcd-cluster\"\ + \n },\n \"backupStorageType\": \"S3\",\n \"s3\": {\n \"\ + path\": \"\",\n \"awsSecret\": \"\"\n \ + \ }\n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdBackup\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-backup\"\ + \n },\n \"spec\": {\n \"etcdEndpoints\": [\"\"\ + ],\n \"storageType\":\"S3\",\n \"s3\": {\n \"path\": \"\"\ + ,\n \"awsSecret\": \"\"\n }\n }\n }\n]\n" + capabilities: Full Lifecycle + categories: Database + containerImage: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + createdAt: 2019-02-28 01:03:00 + description: Create and maintain highly-available etcd clusters on Kubernetes + repository: https://github.com/coreos/etcd-operator + tectonic-visibility: ocs + name: etcdoperator.v0.9.4 + namespace: placeholder +spec: + customresourcedefinitions: + owned: + - description: Represents a cluster of etcd nodes. + displayName: etcd Cluster + kind: EtcdCluster + name: etcdclusters.etcd.database.coreos.com + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: Limits describes the minimum/maximum amount of compute resources + required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podStatuses + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Service + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: The target version of the etcd cluster, after upgrading. + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to backup an etcd cluster. + displayName: etcd Backup + kind: EtcdBackup + name: etcdbackups.etcd.database.coreos.com + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - urn:alm:descriptor:etcd:endpoint + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to restore an etcd cluster from a backup. + displayName: etcd Restore + kind: EtcdRestore + name: etcdrestores.etcd.database.coreos.com + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - urn:alm:descriptor:io.kubernetes:EtcdCluster + - urn:alm:descriptor:text + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + description: "The etcd Operater creates and maintains highly-available etcd clusters\ + \ on Kubernetes, allowing engineers to easily deploy and manage etcd clusters\ + \ for their applications.\n\netcd is a distributed key value store that provides\ + \ a reliable way to store data across a cluster of machines. It\xE2\u20AC\u2122\ + s open-source and available on GitHub. etcd gracefully handles leader elections\ + \ during network partitions and will tolerate machine failure, including the leader.\n\ + \n\n### Reading and writing to etcd\n\nCommunicate with etcd though its command\ + \ line utility `etcdctl` via port forwarding:\n\n $ kubectl --namespace default\ + \ port-forward service/example-client 2379:2379\n $ etcdctl --endpoints http://127.0.0.1:2379\ + \ get /\n\nOr directly to the API using the automatically generated Kubernetes\ + \ Service:\n\n $ etcdctl --endpoints http://example-client.default.svc:2379\ + \ get /\n\nBe sure to secure your etcd cluster (see Common Configurations) before\ + \ exposing it outside of the namespace or cluster.\n\n\n### Supported Features\n\ + \n* **High availability** - Multiple instances of etcd are networked together\ + \ and secured. Individual failures or networking issues are transparently handled\ + \ to keep your cluster up and running.\n\n* **Automated updates** - Rolling out\ + \ a new etcd version works like all Kubernetes rolling updates. Simply declare\ + \ the desired version, and the etcd service starts a safe rolling update to the\ + \ new version automatically.\n\n* **Backups included** - Create etcd backups and\ + \ restore them through the etcd Operator.\n\n### Common Configurations\n\n* **Configure\ + \ TLS** - Specify [static TLS certs](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md)\ + \ as Kubernetes secrets.\n\n* **Set Node Selector and Affinity** - [Spread your\ + \ etcd Pods](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-node-selector-and-anti-affinity-across-nodes)\ + \ across Nodes and availability zones.\n\n* **Set Resource Limits** - [Set the\ + \ Kubernetes limit and request](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-resource-requirement)\ + \ values for your etcd Pods.\n\n* **Customize Storage** - [Set a custom StorageClass](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#custom-persistentvolumeclaim-definition)\ + \ that you would like to use.\n" + displayName: etcd + icon: + - base64data: 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 + mediatype: image/png + install: + spec: + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + labels: + name: etcd-operator-alm-owned + name: etcd-operator-alm-owned + spec: + containers: + - command: + - etcd-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-operator + - command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-backup-operator + - command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-restore-operator + serviceAccountName: etcd-operator + permissions: + - rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + verbs: + - '*' + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + serviceAccountName: etcd-operator + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: false + type: AllNamespaces + keywords: + - etcd + - key value + - database + - coreos + - open source + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + maintainers: + - email: etcd-dev@googlegroups.com + name: etcd Community + maturity: alpha + provider: + name: CNCF + replaces: etcdoperator.v0.9.2 + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + version: 0.9.4 diff --git a/pkg/validation/testdata/invalid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/invalid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5b851cd12 --- /dev/null +++ b/pkg/validation/testdata/invalid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdrestores.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdRestore + listKind: EtcdRestoreList + plural: etcdrestores + singular: etcdrestore + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/invalid_package/package.yaml b/pkg/validation/testdata/invalid_package/package.yaml new file mode 100644 index 000000000..c7314e87d --- /dev/null +++ b/pkg/validation/testdata/invalid_package/package.yaml @@ -0,0 +1,4 @@ +channels: +- currentCSV: etcdoperator.v0.9.4 + name: singlenamespace-alpha +defaultChannel: singlenamespace-alpha diff --git a/pkg/validation/testdata/valid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/valid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5afc088b9 --- /dev/null +++ b/pkg/validation/testdata/valid_bundle/etcdbackups.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdbackups.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdBackup + listKind: EtcdBackupList + plural: etcdbackups + singular: etcdbackup + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/valid_bundle/etcdclusters.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/valid_bundle/etcdclusters.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..01111e5c5 --- /dev/null +++ b/pkg/validation/testdata/valid_bundle/etcdclusters.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,16 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdclusters.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdCluster + listKind: EtcdClusterList + plural: etcdclusters + shortNames: + - etcdclus + - etcd + singular: etcdcluster + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml b/pkg/validation/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml new file mode 100644 index 000000000..56f414d66 --- /dev/null +++ b/pkg/validation/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml @@ -0,0 +1,309 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdCluster\",\n \"metadata\": {\n \"name\": \"example\"\ + \n },\n \"spec\": {\n \"size\": 3,\n \"version\": \"3.2.13\"\ + \n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdRestore\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-restore\"\ + \n },\n \"spec\": {\n \"etcdCluster\": {\n \"name\": \"example-etcd-cluster\"\ + \n },\n \"backupStorageType\": \"S3\",\n \"s3\": {\n \"\ + path\": \"\",\n \"awsSecret\": \"\"\n \ + \ }\n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdBackup\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-backup\"\ + \n },\n \"spec\": {\n \"etcdEndpoints\": [\"\"\ + ],\n \"storageType\":\"S3\",\n \"s3\": {\n \"path\": \"\"\ + ,\n \"awsSecret\": \"\"\n }\n }\n }\n]\n" + capabilities: Full Lifecycle + categories: Database + containerImage: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + createdAt: 2019-02-28 01:03:00 + description: Create and maintain highly-available etcd clusters on Kubernetes + repository: https://github.com/coreos/etcd-operator + tectonic-visibility: ocs + name: etcdoperator.v0.9.4 + namespace: placeholder +spec: + customresourcedefinitions: + owned: + - description: Represents a cluster of etcd nodes. + displayName: etcd Cluster + kind: EtcdCluster + name: etcdclusters.etcd.database.coreos.com + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: Limits describes the minimum/maximum amount of compute resources + required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podStatuses + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Service + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: The target version of the etcd cluster, after upgrading. + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to backup an etcd cluster. + displayName: etcd Backup + kind: EtcdBackup + name: etcdbackups.etcd.database.coreos.com + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - urn:alm:descriptor:etcd:endpoint + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to restore an etcd cluster from a backup. + displayName: etcd Restore + kind: EtcdRestore + name: etcdrestores.etcd.database.coreos.com + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - urn:alm:descriptor:io.kubernetes:EtcdCluster + - urn:alm:descriptor:text + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + description: "The etcd Operater creates and maintains highly-available etcd clusters\ + \ on Kubernetes, allowing engineers to easily deploy and manage etcd clusters\ + \ for their applications.\n\netcd is a distributed key value store that provides\ + \ a reliable way to store data across a cluster of machines. It\xE2\u20AC\u2122\ + s open-source and available on GitHub. etcd gracefully handles leader elections\ + \ during network partitions and will tolerate machine failure, including the leader.\n\ + \n\n### Reading and writing to etcd\n\nCommunicate with etcd though its command\ + \ line utility `etcdctl` via port forwarding:\n\n $ kubectl --namespace default\ + \ port-forward service/example-client 2379:2379\n $ etcdctl --endpoints http://127.0.0.1:2379\ + \ get /\n\nOr directly to the API using the automatically generated Kubernetes\ + \ Service:\n\n $ etcdctl --endpoints http://example-client.default.svc:2379\ + \ get /\n\nBe sure to secure your etcd cluster (see Common Configurations) before\ + \ exposing it outside of the namespace or cluster.\n\n\n### Supported Features\n\ + \n* **High availability** - Multiple instances of etcd are networked together\ + \ and secured. Individual failures or networking issues are transparently handled\ + \ to keep your cluster up and running.\n\n* **Automated updates** - Rolling out\ + \ a new etcd version works like all Kubernetes rolling updates. Simply declare\ + \ the desired version, and the etcd service starts a safe rolling update to the\ + \ new version automatically.\n\n* **Backups included** - Create etcd backups and\ + \ restore them through the etcd Operator.\n\n### Common Configurations\n\n* **Configure\ + \ TLS** - Specify [static TLS certs](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md)\ + \ as Kubernetes secrets.\n\n* **Set Node Selector and Affinity** - [Spread your\ + \ etcd Pods](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-node-selector-and-anti-affinity-across-nodes)\ + \ across Nodes and availability zones.\n\n* **Set Resource Limits** - [Set the\ + \ Kubernetes limit and request](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-resource-requirement)\ + \ values for your etcd Pods.\n\n* **Customize Storage** - [Set a custom StorageClass](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#custom-persistentvolumeclaim-definition)\ + \ that you would like to use.\n" + displayName: etcd + icon: + - base64data: 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 + mediatype: image/png + install: + spec: + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + labels: + name: etcd-operator-alm-owned + name: etcd-operator-alm-owned + spec: + containers: + - command: + - etcd-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-operator + - command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-backup-operator + - command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-restore-operator + serviceAccountName: etcd-operator + permissions: + - rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + verbs: + - '*' + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + serviceAccountName: etcd-operator + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: false + type: AllNamespaces + keywords: + - etcd + - key value + - database + - coreos + - open source + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + maintainers: + - email: etcd-dev@googlegroups.com + name: etcd Community + maturity: alpha + provider: + name: CNCF + replaces: etcdoperator.v0.9.2 + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + version: 0.9.4 diff --git a/pkg/validation/testdata/valid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/valid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5b851cd12 --- /dev/null +++ b/pkg/validation/testdata/valid_bundle/etcdrestores.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdrestores.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdRestore + listKind: EtcdRestoreList + plural: etcdrestores + singular: etcdrestore + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/valid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/valid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5afc088b9 --- /dev/null +++ b/pkg/validation/testdata/valid_package/0.9.2/etcdbackups.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdbackups.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdBackup + listKind: EtcdBackupList + plural: etcdbackups + singular: etcdbackup + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/valid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/valid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..01111e5c5 --- /dev/null +++ b/pkg/validation/testdata/valid_package/0.9.2/etcdclusters.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,16 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdclusters.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdCluster + listKind: EtcdClusterList + plural: etcdclusters + shortNames: + - etcdclus + - etcd + singular: etcdcluster + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/valid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml b/pkg/validation/testdata/valid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml new file mode 100644 index 000000000..efc209da6 --- /dev/null +++ b/pkg/validation/testdata/valid_package/0.9.2/etcdoperator.v0.9.2.clusterserviceversion.yaml @@ -0,0 +1,305 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdCluster\",\n \"metadata\": {\n \"name\": \"example\"\ + \n },\n \"spec\": {\n \"size\": 3,\n \"version\": \"3.2.13\"\ + \n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdRestore\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-restore\"\ + \n },\n \"spec\": {\n \"etcdCluster\": {\n \"name\": \"example-etcd-cluster\"\ + \n },\n \"backupStorageType\": \"S3\",\n \"s3\": {\n \"\ + path\": \"\",\n \"awsSecret\": \"\"\n \ + \ }\n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdBackup\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-backup\"\ + \n },\n \"spec\": {\n \"etcdEndpoints\": [\"\"\ + ],\n \"storageType\":\"S3\",\n \"s3\": {\n \"path\": \"\"\ + ,\n \"awsSecret\": \"\"\n }\n }\n }\n]\n" + capabilities: Full Lifecycle + categories: Database + description: Creates and maintain highly-available etcd clusters on Kubernetes + tectonic-visibility: ocs + name: etcdoperator.v0.9.2 + namespace: placeholder +spec: + customresourcedefinitions: + owned: + - description: Represents a cluster of etcd nodes. + displayName: etcd Cluster + kind: EtcdCluster + name: etcdclusters.etcd.database.coreos.com + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: Limits describes the minimum/maximum amount of compute resources + required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podStatuses + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Service + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: The target version of the etcd cluster, after upgrading. + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to backup an etcd cluster. + displayName: etcd Backup + kind: EtcdBackup + name: etcdbackups.etcd.database.coreos.com + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - urn:alm:descriptor:etcd:endpoint + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to restore an etcd cluster from a backup. + displayName: etcd Restore + kind: EtcdRestore + name: etcdrestores.etcd.database.coreos.com + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - urn:alm:descriptor:io.kubernetes:EtcdCluster + - urn:alm:descriptor:text + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + description: "The etcd Operater creates and maintains highly-available etcd clusters\ + \ on Kubernetes, allowing engineers to easily deploy and manage etcd clusters\ + \ for their applications.\n\netcd is a distributed key value store that provides\ + \ a reliable way to store data across a cluster of machines. It\xE2\u20AC\u2122\ + s open-source and available on GitHub. etcd gracefully handles leader elections\ + \ during network partitions and will tolerate machine failure, including the leader.\n\ + \n\n### Reading and writing to etcd\n\nCommunicate with etcd though its command\ + \ line utility `etcdctl` via port forwarding:\n\n $ kubectl --namespace default\ + \ port-forward service/example-client 2379:2379\n $ etcdctl --endpoints http://127.0.0.1:2379\ + \ get /\n\nOr directly to the API using the automatically generated Kubernetes\ + \ Service:\n\n $ etcdctl --endpoints http://example-client.default.svc:2379\ + \ get /\n\nBe sure to secure your etcd cluster (see Common Configurations) before\ + \ exposing it outside of the namespace or cluster.\n\n\n### Supported Features\n\ + \n* **High availability** - Multiple instances of etcd are networked together\ + \ and secured. Individual failures or networking issues are transparently handled\ + \ to keep your cluster up and running.\n\n* **Automated updates** - Rolling out\ + \ a new etcd version works like all Kubernetes rolling updates. Simply declare\ + \ the desired version, and the etcd service starts a safe rolling update to the\ + \ new version automatically.\n\n* **Backups included** - Create etcd backups and\ + \ restore them through the etcd Operator.\n\n### Common Configurations\n\n* **Configure\ + \ TLS** - Specify [static TLS certs](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md)\ + \ as Kubernetes secrets.\n\n* **Set Node Selector and Affinity** - [Spread your\ + \ etcd Pods](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-node-selector-and-anti-affinity-across-nodes)\ + \ across Nodes and availability zones.\n\n* **Set Resource Limits** - [Set the\ + \ Kubernetes limit and request](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-resource-requirement)\ + \ values for your etcd Pods.\n\n* **Customize Storage** - [Set a custom StorageClass](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#custom-persistentvolumeclaim-definition)\ + \ that you would like to use.\n" + displayName: etcd + icon: + - base64data: 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 + mediatype: image/png + install: + spec: + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + labels: + name: etcd-operator-alm-owned + name: etcd-operator-alm-owned + spec: + containers: + - command: + - etcd-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2 + name: etcd-operator + - command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2 + name: etcd-backup-operator + - command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2 + name: etcd-restore-operator + serviceAccountName: etcd-operator + permissions: + - rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + verbs: + - '*' + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + serviceAccountName: etcd-operator + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: false + type: AllNamespaces + keywords: + - etcd + - key value + - database + - coreos + - open source + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + maintainers: + - email: etcd-dev@googlegroups.com + name: etcd Community + maturity: alpha + provider: + name: CNCF + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + version: 0.9.2 diff --git a/pkg/validation/testdata/valid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/valid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5b851cd12 --- /dev/null +++ b/pkg/validation/testdata/valid_package/0.9.2/etcdrestores.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdrestores.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdRestore + listKind: EtcdRestoreList + plural: etcdrestores + singular: etcdrestore + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/valid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/valid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5afc088b9 --- /dev/null +++ b/pkg/validation/testdata/valid_package/0.9.4/etcdbackups.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdbackups.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdBackup + listKind: EtcdBackupList + plural: etcdbackups + singular: etcdbackup + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/valid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/valid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..01111e5c5 --- /dev/null +++ b/pkg/validation/testdata/valid_package/0.9.4/etcdclusters.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,16 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdclusters.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdCluster + listKind: EtcdClusterList + plural: etcdclusters + shortNames: + - etcdclus + - etcd + singular: etcdcluster + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/valid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml b/pkg/validation/testdata/valid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml new file mode 100644 index 000000000..56f414d66 --- /dev/null +++ b/pkg/validation/testdata/valid_package/0.9.4/etcdoperator.v0.9.4.clusterserviceversion.yaml @@ -0,0 +1,309 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdCluster\",\n \"metadata\": {\n \"name\": \"example\"\ + \n },\n \"spec\": {\n \"size\": 3,\n \"version\": \"3.2.13\"\ + \n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdRestore\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-restore\"\ + \n },\n \"spec\": {\n \"etcdCluster\": {\n \"name\": \"example-etcd-cluster\"\ + \n },\n \"backupStorageType\": \"S3\",\n \"s3\": {\n \"\ + path\": \"\",\n \"awsSecret\": \"\"\n \ + \ }\n }\n },\n {\n \"apiVersion\": \"etcd.database.coreos.com/v1beta2\"\ + ,\n \"kind\": \"EtcdBackup\",\n \"metadata\": {\n \"name\": \"example-etcd-cluster-backup\"\ + \n },\n \"spec\": {\n \"etcdEndpoints\": [\"\"\ + ],\n \"storageType\":\"S3\",\n \"s3\": {\n \"path\": \"\"\ + ,\n \"awsSecret\": \"\"\n }\n }\n }\n]\n" + capabilities: Full Lifecycle + categories: Database + containerImage: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + createdAt: 2019-02-28 01:03:00 + description: Create and maintain highly-available etcd clusters on Kubernetes + repository: https://github.com/coreos/etcd-operator + tectonic-visibility: ocs + name: etcdoperator.v0.9.4 + namespace: placeholder +spec: + customresourcedefinitions: + owned: + - description: Represents a cluster of etcd nodes. + displayName: etcd Cluster + kind: EtcdCluster + name: etcdclusters.etcd.database.coreos.com + resources: + - kind: Service + version: v1 + - kind: Pod + version: v1 + specDescriptors: + - description: The desired number of member Pods for the etcd cluster. + displayName: Size + path: size + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: Limits describes the minimum/maximum amount of compute resources + required/allowed + displayName: Resource Requirements + path: pod.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + statusDescriptors: + - description: The status of each of the member Pods for the etcd cluster. + displayName: Member Status + path: members + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podStatuses + - description: The service at which the running etcd cluster can be accessed. + displayName: Service + path: serviceName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Service + - description: The current size of the etcd cluster. + displayName: Cluster Size + path: size + - description: The current version of the etcd cluster. + displayName: Current Version + path: currentVersion + - description: The target version of the etcd cluster, after upgrading. + displayName: Target Version + path: targetVersion + - description: The current status of the etcd cluster. + displayName: Status + path: phase + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase + - description: Explanation for the current status of the cluster. + displayName: Status Details + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to backup an etcd cluster. + displayName: etcd Backup + kind: EtcdBackup + name: etcdbackups.etcd.database.coreos.com + specDescriptors: + - description: Specifies the endpoints of an etcd cluster. + displayName: etcd Endpoint(s) + path: etcdEndpoints + x-descriptors: + - urn:alm:descriptor:etcd:endpoint + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the backup was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any backup related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + - description: Represents the intent to restore an etcd cluster from a backup. + displayName: etcd Restore + kind: EtcdRestore + name: etcdrestores.etcd.database.coreos.com + specDescriptors: + - description: References the EtcdCluster which should be restored, + displayName: etcd Cluster + path: etcdCluster.name + x-descriptors: + - urn:alm:descriptor:io.kubernetes:EtcdCluster + - urn:alm:descriptor:text + - description: The full AWS S3 path where the backup is saved. + displayName: S3 Path + path: s3.path + x-descriptors: + - urn:alm:descriptor:aws:s3:path + - description: The name of the secret object that stores the AWS credential + and config files. + displayName: AWS Secret + path: s3.awsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Indicates if the restore was successful. + displayName: Succeeded + path: succeeded + x-descriptors: + - urn:alm:descriptor:text + - description: Indicates the reason for any restore related failures. + displayName: Reason + path: reason + x-descriptors: + - urn:alm:descriptor:io.kubernetes.phase:reason + version: v1beta2 + description: "The etcd Operater creates and maintains highly-available etcd clusters\ + \ on Kubernetes, allowing engineers to easily deploy and manage etcd clusters\ + \ for their applications.\n\netcd is a distributed key value store that provides\ + \ a reliable way to store data across a cluster of machines. It\xE2\u20AC\u2122\ + s open-source and available on GitHub. etcd gracefully handles leader elections\ + \ during network partitions and will tolerate machine failure, including the leader.\n\ + \n\n### Reading and writing to etcd\n\nCommunicate with etcd though its command\ + \ line utility `etcdctl` via port forwarding:\n\n $ kubectl --namespace default\ + \ port-forward service/example-client 2379:2379\n $ etcdctl --endpoints http://127.0.0.1:2379\ + \ get /\n\nOr directly to the API using the automatically generated Kubernetes\ + \ Service:\n\n $ etcdctl --endpoints http://example-client.default.svc:2379\ + \ get /\n\nBe sure to secure your etcd cluster (see Common Configurations) before\ + \ exposing it outside of the namespace or cluster.\n\n\n### Supported Features\n\ + \n* **High availability** - Multiple instances of etcd are networked together\ + \ and secured. Individual failures or networking issues are transparently handled\ + \ to keep your cluster up and running.\n\n* **Automated updates** - Rolling out\ + \ a new etcd version works like all Kubernetes rolling updates. Simply declare\ + \ the desired version, and the etcd service starts a safe rolling update to the\ + \ new version automatically.\n\n* **Backups included** - Create etcd backups and\ + \ restore them through the etcd Operator.\n\n### Common Configurations\n\n* **Configure\ + \ TLS** - Specify [static TLS certs](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md)\ + \ as Kubernetes secrets.\n\n* **Set Node Selector and Affinity** - [Spread your\ + \ etcd Pods](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-node-selector-and-anti-affinity-across-nodes)\ + \ across Nodes and availability zones.\n\n* **Set Resource Limits** - [Set the\ + \ Kubernetes limit and request](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-member-cluster-with-resource-requirement)\ + \ values for your etcd Pods.\n\n* **Customize Storage** - [Set a custom StorageClass](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#custom-persistentvolumeclaim-definition)\ + \ that you would like to use.\n" + displayName: etcd + icon: + - base64data: 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 + mediatype: image/png + install: + spec: + deployments: + - name: etcd-operator + spec: + replicas: 1 + selector: + matchLabels: + name: etcd-operator-alm-owned + template: + metadata: + labels: + name: etcd-operator-alm-owned + name: etcd-operator-alm-owned + spec: + containers: + - command: + - etcd-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-operator + - command: + - etcd-backup-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-backup-operator + - command: + - etcd-restore-operator + - --create-crd=false + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: etcd-restore-operator + serviceAccountName: etcd-operator + permissions: + - rules: + - apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + verbs: + - '*' + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + serviceAccountName: etcd-operator + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: false + type: AllNamespaces + keywords: + - etcd + - key value + - database + - coreos + - open source + labels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + links: + - name: Blog + url: https://coreos.com/etcd + - name: Documentation + url: https://coreos.com/operators/etcd/docs/latest/ + - name: etcd Operator Source Code + url: https://github.com/coreos/etcd-operator + maintainers: + - email: etcd-dev@googlegroups.com + name: etcd Community + maturity: alpha + provider: + name: CNCF + replaces: etcdoperator.v0.9.2 + selector: + matchLabels: + alm-owner-etcd: etcdoperator + operated-by: etcdoperator + version: 0.9.4 diff --git a/pkg/validation/testdata/valid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml b/pkg/validation/testdata/valid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml new file mode 100644 index 000000000..5b851cd12 --- /dev/null +++ b/pkg/validation/testdata/valid_package/0.9.4/etcdrestores.etcd.database.coreos.com.crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: etcdrestores.etcd.database.coreos.com +spec: + group: etcd.database.coreos.com + names: + kind: EtcdRestore + listKind: EtcdRestoreList + plural: etcdrestores + singular: etcdrestore + scope: Namespaced + version: v1beta2 diff --git a/pkg/validation/testdata/valid_package/package.yaml b/pkg/validation/testdata/valid_package/package.yaml new file mode 100644 index 000000000..cec7bc072 --- /dev/null +++ b/pkg/validation/testdata/valid_package/package.yaml @@ -0,0 +1,5 @@ +channels: +- currentCSV: etcdoperator.v0.9.4 + name: singlenamespace-alpha +defaultChannel: singlenamespace-alpha +packageName: etcd diff --git a/pkg/validation/validation.go b/pkg/validation/validation.go index 796c6e5e7..ac7adbddd 100644 --- a/pkg/validation/validation.go +++ b/pkg/validation/validation.go @@ -24,14 +24,13 @@ var ClusterServiceVersionValidator = internal.CSVValidator // CustomResourceDefinitions. var CustomResourceDefinitionValidator = internal.CRDValidator -// PackageUpdateGraphValidator implements Validator to validate the -// package update graph between a package manifest and Bundles. -var PackageUpdateGraphValidator = internal.PackageUpdateGraphValidator +// BundleValidator implements Validator to validate Bundles. +var BundleValidator = internal.BundleValidator // AllValidators implements Validator to validate all Operator manifest types. var AllValidators = interfaces.Validators{ PackageManifestValidator, ClusterServiceVersionValidator, CustomResourceDefinitionValidator, - PackageUpdateGraphValidator, + BundleValidator, } diff --git a/pkg/validation/validation_test.go b/pkg/validation/validation_test.go new file mode 100644 index 000000000..b6cc7af12 --- /dev/null +++ b/pkg/validation/validation_test.go @@ -0,0 +1,61 @@ +package validation + +import ( + "testing" + + "github.com/operator-framework/api/pkg/manifests" + "github.com/operator-framework/api/pkg/validation/errors" + + "github.com/stretchr/testify/require" +) + +func TestValidateSuccess(t *testing.T) { + bundle, err := manifests.GetBundleFromDir("./testdata/valid_bundle") + require.NoError(t, err) + + results := AllValidators.Validate(bundle) + for _, result := range results { + require.Equal(t, false, result.HasError()) + } +} + +func TestValidate_WithErrors(t *testing.T) { + bundle, err := manifests.GetBundleFromDir("./testdata/invalid_bundle") + require.NoError(t, err) + + results := AllValidators.Validate(bundle) + for _, result := range results { + require.Equal(t, true, result.HasError()) + } + require.Equal(t, 1, len(results)) +} + +func TestValidatePackageSuccess(t *testing.T) { + pkg, bundles, err := manifests.GetManifestsDir("./testdata/valid_package") + require.NoError(t, err) + + objs := []interface{}{} + for _, obj := range bundles { + objs = append(objs, obj) + } + objs = append(objs, pkg) + + results := AllValidators.Validate(objs...) + for _, result := range results { + require.Equal(t, false, result.HasError()) + } +} + +func TestValidatePackageError(t *testing.T) { + pkg, _, err := manifests.GetManifestsDir("./testdata/invalid_package") + require.NoError(t, err) + + objs := []interface{}{pkg} + + results := AllValidators.Validate(objs...) + require.Equal(t, 1, len(results)) + require.True(t, results[0].HasError()) + pkgErrs := results[0].Errors + require.Equal(t, 1, len(pkgErrs)) + require.Equal(t, errors.ErrInvalidPackageManifest("packageName empty", pkg.PackageName), pkgErrs[0]) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 07a3540ce..fc49a6cdd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -100,12 +100,6 @@ github.com/modern-go/reflect2 # github.com/onsi/gomega v1.9.0 github.com/onsi/gomega/gstruct/errors github.com/onsi/gomega/types -# github.com/operator-framework/operator-registry v1.12.1 -github.com/operator-framework/operator-registry/pkg/api -github.com/operator-framework/operator-registry/pkg/image -github.com/operator-framework/operator-registry/pkg/registry -github.com/operator-framework/operator-registry/pkg/sqlite -github.com/operator-framework/operator-registry/pkg/sqlite/migrations # github.com/pkg/errors v0.9.1 github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 From eb083ab8be110823de591cb7b18de3aa125f804f Mon Sep 17 00:00:00 2001 From: kevinrizza Date: Thu, 21 May 2020 12:16:09 -0400 Subject: [PATCH 2/2] Remove operator-registry from vendor folder --- .../operator-registry/LICENSE | 201 --- .../operator-registry/pkg/api/registry.pb.go | 1558 ----------------- .../operator-registry/pkg/api/registry.proto | 115 -- .../operator-registry/pkg/image/reference.go | 16 - .../operator-registry/pkg/image/registry.go | 32 - .../operator-registry/pkg/registry/bundle.go | 287 --- .../pkg/registry/bundlegraphloader.go | 147 -- .../pkg/registry/channelupdateoptions.go | 27 - .../pkg/registry/conversion.go | 83 - .../operator-registry/pkg/registry/csv.go | 334 ---- .../operator-registry/pkg/registry/decode.go | 43 - .../pkg/registry/directoryGraphLoader.go | 226 --- .../operator-registry/pkg/registry/empty.go | 111 -- .../operator-registry/pkg/registry/graph.go | 51 - .../pkg/registry/imageinput.go | 125 -- .../pkg/registry/interface.go | 70 - .../pkg/registry/populator.go | 405 ----- .../pkg/registry/replacesgraphloader.go | 40 - .../operator-registry/pkg/registry/types.go | 270 --- .../operator-registry/pkg/sqlite/configmap.go | 187 -- .../pkg/sqlite/db_options.go | 24 - .../operator-registry/pkg/sqlite/directory.go | 229 --- .../pkg/sqlite/graphloader.go | 138 -- .../operator-registry/pkg/sqlite/load.go | 719 -------- .../operator-registry/pkg/sqlite/loadprocs.go | 146 -- .../pkg/sqlite/migrations/000_init.go | 78 - .../sqlite/migrations/001_related_images.go | 123 -- .../pkg/sqlite/migrations/002_bundle_path.go | 55 - .../sqlite/migrations/003_required_apis.go | 147 -- .../sqlite/migrations/004_cascade_delete.go | 453 ----- .../migrations/005_version_skiprange.go | 94 - .../006_associate_apis_with_bundle.go | 335 ---- .../sqlite/migrations/007_replaces_skips.go | 142 -- .../pkg/sqlite/migrations/008_dependencies.go | 119 -- .../pkg/sqlite/migrations/migrations.go | 93 - .../operator-registry/pkg/sqlite/migrator.go | 209 --- .../operator-registry/pkg/sqlite/query.go | 924 ---------- .../operator-registry/pkg/sqlite/remove.go | 67 - .../operator-registry/pkg/sqlite/test.txt | 1 - 39 files changed, 8424 deletions(-) delete mode 100644 vendor/github.com/operator-framework/operator-registry/LICENSE delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/api/registry.pb.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/api/registry.proto delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/image/reference.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/image/registry.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/bundle.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/bundlegraphloader.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/channelupdateoptions.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/conversion.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/csv.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/decode.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/directoryGraphLoader.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/empty.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/graph.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/imageinput.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/interface.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/populator.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/replacesgraphloader.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/registry/types.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/configmap.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/db_options.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/directory.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/graphloader.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/load.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/loadprocs.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/000_init.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/001_related_images.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/002_bundle_path.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/003_required_apis.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/004_cascade_delete.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/005_version_skiprange.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/006_associate_apis_with_bundle.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/007_replaces_skips.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/008_dependencies.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/migrations.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrator.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/query.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/remove.go delete mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/sqlite/test.txt diff --git a/vendor/github.com/operator-framework/operator-registry/LICENSE b/vendor/github.com/operator-framework/operator-registry/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/vendor/github.com/operator-framework/operator-registry/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.pb.go b/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.pb.go deleted file mode 100644 index 1d0769876..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.pb.go +++ /dev/null @@ -1,1558 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: registry.proto - -package api - -import ( - context "context" - fmt "fmt" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - math "math" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -type Channel struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - CsvName string `protobuf:"bytes,2,opt,name=csvName,proto3" json:"csvName,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Channel) Reset() { *m = Channel{} } -func (m *Channel) String() string { return proto.CompactTextString(m) } -func (*Channel) ProtoMessage() {} -func (*Channel) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{0} -} - -func (m *Channel) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Channel.Unmarshal(m, b) -} -func (m *Channel) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Channel.Marshal(b, m, deterministic) -} -func (m *Channel) XXX_Merge(src proto.Message) { - xxx_messageInfo_Channel.Merge(m, src) -} -func (m *Channel) XXX_Size() int { - return xxx_messageInfo_Channel.Size(m) -} -func (m *Channel) XXX_DiscardUnknown() { - xxx_messageInfo_Channel.DiscardUnknown(m) -} - -var xxx_messageInfo_Channel proto.InternalMessageInfo - -func (m *Channel) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func (m *Channel) GetCsvName() string { - if m != nil { - return m.CsvName - } - return "" -} - -type PackageName struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PackageName) Reset() { *m = PackageName{} } -func (m *PackageName) String() string { return proto.CompactTextString(m) } -func (*PackageName) ProtoMessage() {} -func (*PackageName) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{1} -} - -func (m *PackageName) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PackageName.Unmarshal(m, b) -} -func (m *PackageName) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PackageName.Marshal(b, m, deterministic) -} -func (m *PackageName) XXX_Merge(src proto.Message) { - xxx_messageInfo_PackageName.Merge(m, src) -} -func (m *PackageName) XXX_Size() int { - return xxx_messageInfo_PackageName.Size(m) -} -func (m *PackageName) XXX_DiscardUnknown() { - xxx_messageInfo_PackageName.DiscardUnknown(m) -} - -var xxx_messageInfo_PackageName proto.InternalMessageInfo - -func (m *PackageName) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -type Package struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Channels []*Channel `protobuf:"bytes,2,rep,name=channels,proto3" json:"channels,omitempty"` - DefaultChannelName string `protobuf:"bytes,3,opt,name=defaultChannelName,proto3" json:"defaultChannelName,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Package) Reset() { *m = Package{} } -func (m *Package) String() string { return proto.CompactTextString(m) } -func (*Package) ProtoMessage() {} -func (*Package) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{2} -} - -func (m *Package) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Package.Unmarshal(m, b) -} -func (m *Package) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Package.Marshal(b, m, deterministic) -} -func (m *Package) XXX_Merge(src proto.Message) { - xxx_messageInfo_Package.Merge(m, src) -} -func (m *Package) XXX_Size() int { - return xxx_messageInfo_Package.Size(m) -} -func (m *Package) XXX_DiscardUnknown() { - xxx_messageInfo_Package.DiscardUnknown(m) -} - -var xxx_messageInfo_Package proto.InternalMessageInfo - -func (m *Package) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func (m *Package) GetChannels() []*Channel { - if m != nil { - return m.Channels - } - return nil -} - -func (m *Package) GetDefaultChannelName() string { - if m != nil { - return m.DefaultChannelName - } - return "" -} - -type GroupVersionKind struct { - Group string `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - Kind string `protobuf:"bytes,3,opt,name=kind,proto3" json:"kind,omitempty"` - Plural string `protobuf:"bytes,4,opt,name=plural,proto3" json:"plural,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GroupVersionKind) Reset() { *m = GroupVersionKind{} } -func (m *GroupVersionKind) String() string { return proto.CompactTextString(m) } -func (*GroupVersionKind) ProtoMessage() {} -func (*GroupVersionKind) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{3} -} - -func (m *GroupVersionKind) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GroupVersionKind.Unmarshal(m, b) -} -func (m *GroupVersionKind) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GroupVersionKind.Marshal(b, m, deterministic) -} -func (m *GroupVersionKind) XXX_Merge(src proto.Message) { - xxx_messageInfo_GroupVersionKind.Merge(m, src) -} -func (m *GroupVersionKind) XXX_Size() int { - return xxx_messageInfo_GroupVersionKind.Size(m) -} -func (m *GroupVersionKind) XXX_DiscardUnknown() { - xxx_messageInfo_GroupVersionKind.DiscardUnknown(m) -} - -var xxx_messageInfo_GroupVersionKind proto.InternalMessageInfo - -func (m *GroupVersionKind) GetGroup() string { - if m != nil { - return m.Group - } - return "" -} - -func (m *GroupVersionKind) GetVersion() string { - if m != nil { - return m.Version - } - return "" -} - -func (m *GroupVersionKind) GetKind() string { - if m != nil { - return m.Kind - } - return "" -} - -func (m *GroupVersionKind) GetPlural() string { - if m != nil { - return m.Plural - } - return "" -} - -type Dependency struct { - Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Dependency) Reset() { *m = Dependency{} } -func (m *Dependency) String() string { return proto.CompactTextString(m) } -func (*Dependency) ProtoMessage() {} -func (*Dependency) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{4} -} - -func (m *Dependency) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Dependency.Unmarshal(m, b) -} -func (m *Dependency) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Dependency.Marshal(b, m, deterministic) -} -func (m *Dependency) XXX_Merge(src proto.Message) { - xxx_messageInfo_Dependency.Merge(m, src) -} -func (m *Dependency) XXX_Size() int { - return xxx_messageInfo_Dependency.Size(m) -} -func (m *Dependency) XXX_DiscardUnknown() { - xxx_messageInfo_Dependency.DiscardUnknown(m) -} - -var xxx_messageInfo_Dependency proto.InternalMessageInfo - -func (m *Dependency) GetType() string { - if m != nil { - return m.Type - } - return "" -} - -func (m *Dependency) GetValue() string { - if m != nil { - return m.Value - } - return "" -} - -type Bundle struct { - CsvName string `protobuf:"bytes,1,opt,name=csvName,proto3" json:"csvName,omitempty"` - PackageName string `protobuf:"bytes,2,opt,name=packageName,proto3" json:"packageName,omitempty"` - ChannelName string `protobuf:"bytes,3,opt,name=channelName,proto3" json:"channelName,omitempty"` - CsvJson string `protobuf:"bytes,4,opt,name=csvJson,proto3" json:"csvJson,omitempty"` - Object []string `protobuf:"bytes,5,rep,name=object,proto3" json:"object,omitempty"` - BundlePath string `protobuf:"bytes,6,opt,name=bundlePath,proto3" json:"bundlePath,omitempty"` - ProvidedApis []*GroupVersionKind `protobuf:"bytes,7,rep,name=providedApis,proto3" json:"providedApis,omitempty"` - RequiredApis []*GroupVersionKind `protobuf:"bytes,8,rep,name=requiredApis,proto3" json:"requiredApis,omitempty"` - Version string `protobuf:"bytes,9,opt,name=version,proto3" json:"version,omitempty"` - SkipRange string `protobuf:"bytes,10,opt,name=skipRange,proto3" json:"skipRange,omitempty"` - Dependencies []*Dependency `protobuf:"bytes,11,rep,name=dependencies,proto3" json:"dependencies,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Bundle) Reset() { *m = Bundle{} } -func (m *Bundle) String() string { return proto.CompactTextString(m) } -func (*Bundle) ProtoMessage() {} -func (*Bundle) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{5} -} - -func (m *Bundle) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Bundle.Unmarshal(m, b) -} -func (m *Bundle) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Bundle.Marshal(b, m, deterministic) -} -func (m *Bundle) XXX_Merge(src proto.Message) { - xxx_messageInfo_Bundle.Merge(m, src) -} -func (m *Bundle) XXX_Size() int { - return xxx_messageInfo_Bundle.Size(m) -} -func (m *Bundle) XXX_DiscardUnknown() { - xxx_messageInfo_Bundle.DiscardUnknown(m) -} - -var xxx_messageInfo_Bundle proto.InternalMessageInfo - -func (m *Bundle) GetCsvName() string { - if m != nil { - return m.CsvName - } - return "" -} - -func (m *Bundle) GetPackageName() string { - if m != nil { - return m.PackageName - } - return "" -} - -func (m *Bundle) GetChannelName() string { - if m != nil { - return m.ChannelName - } - return "" -} - -func (m *Bundle) GetCsvJson() string { - if m != nil { - return m.CsvJson - } - return "" -} - -func (m *Bundle) GetObject() []string { - if m != nil { - return m.Object - } - return nil -} - -func (m *Bundle) GetBundlePath() string { - if m != nil { - return m.BundlePath - } - return "" -} - -func (m *Bundle) GetProvidedApis() []*GroupVersionKind { - if m != nil { - return m.ProvidedApis - } - return nil -} - -func (m *Bundle) GetRequiredApis() []*GroupVersionKind { - if m != nil { - return m.RequiredApis - } - return nil -} - -func (m *Bundle) GetVersion() string { - if m != nil { - return m.Version - } - return "" -} - -func (m *Bundle) GetSkipRange() string { - if m != nil { - return m.SkipRange - } - return "" -} - -func (m *Bundle) GetDependencies() []*Dependency { - if m != nil { - return m.Dependencies - } - return nil -} - -type ChannelEntry struct { - PackageName string `protobuf:"bytes,1,opt,name=packageName,proto3" json:"packageName,omitempty"` - ChannelName string `protobuf:"bytes,2,opt,name=channelName,proto3" json:"channelName,omitempty"` - BundleName string `protobuf:"bytes,3,opt,name=bundleName,proto3" json:"bundleName,omitempty"` - Replaces string `protobuf:"bytes,4,opt,name=replaces,proto3" json:"replaces,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ChannelEntry) Reset() { *m = ChannelEntry{} } -func (m *ChannelEntry) String() string { return proto.CompactTextString(m) } -func (*ChannelEntry) ProtoMessage() {} -func (*ChannelEntry) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{6} -} - -func (m *ChannelEntry) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ChannelEntry.Unmarshal(m, b) -} -func (m *ChannelEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ChannelEntry.Marshal(b, m, deterministic) -} -func (m *ChannelEntry) XXX_Merge(src proto.Message) { - xxx_messageInfo_ChannelEntry.Merge(m, src) -} -func (m *ChannelEntry) XXX_Size() int { - return xxx_messageInfo_ChannelEntry.Size(m) -} -func (m *ChannelEntry) XXX_DiscardUnknown() { - xxx_messageInfo_ChannelEntry.DiscardUnknown(m) -} - -var xxx_messageInfo_ChannelEntry proto.InternalMessageInfo - -func (m *ChannelEntry) GetPackageName() string { - if m != nil { - return m.PackageName - } - return "" -} - -func (m *ChannelEntry) GetChannelName() string { - if m != nil { - return m.ChannelName - } - return "" -} - -func (m *ChannelEntry) GetBundleName() string { - if m != nil { - return m.BundleName - } - return "" -} - -func (m *ChannelEntry) GetReplaces() string { - if m != nil { - return m.Replaces - } - return "" -} - -type ListPackageRequest struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ListPackageRequest) Reset() { *m = ListPackageRequest{} } -func (m *ListPackageRequest) String() string { return proto.CompactTextString(m) } -func (*ListPackageRequest) ProtoMessage() {} -func (*ListPackageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{7} -} - -func (m *ListPackageRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ListPackageRequest.Unmarshal(m, b) -} -func (m *ListPackageRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ListPackageRequest.Marshal(b, m, deterministic) -} -func (m *ListPackageRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_ListPackageRequest.Merge(m, src) -} -func (m *ListPackageRequest) XXX_Size() int { - return xxx_messageInfo_ListPackageRequest.Size(m) -} -func (m *ListPackageRequest) XXX_DiscardUnknown() { - xxx_messageInfo_ListPackageRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_ListPackageRequest proto.InternalMessageInfo - -type ListBundlesRequest struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ListBundlesRequest) Reset() { *m = ListBundlesRequest{} } -func (m *ListBundlesRequest) String() string { return proto.CompactTextString(m) } -func (*ListBundlesRequest) ProtoMessage() {} -func (*ListBundlesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{8} -} - -func (m *ListBundlesRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ListBundlesRequest.Unmarshal(m, b) -} -func (m *ListBundlesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ListBundlesRequest.Marshal(b, m, deterministic) -} -func (m *ListBundlesRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_ListBundlesRequest.Merge(m, src) -} -func (m *ListBundlesRequest) XXX_Size() int { - return xxx_messageInfo_ListBundlesRequest.Size(m) -} -func (m *ListBundlesRequest) XXX_DiscardUnknown() { - xxx_messageInfo_ListBundlesRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_ListBundlesRequest proto.InternalMessageInfo - -type GetPackageRequest struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetPackageRequest) Reset() { *m = GetPackageRequest{} } -func (m *GetPackageRequest) String() string { return proto.CompactTextString(m) } -func (*GetPackageRequest) ProtoMessage() {} -func (*GetPackageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{9} -} - -func (m *GetPackageRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetPackageRequest.Unmarshal(m, b) -} -func (m *GetPackageRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetPackageRequest.Marshal(b, m, deterministic) -} -func (m *GetPackageRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetPackageRequest.Merge(m, src) -} -func (m *GetPackageRequest) XXX_Size() int { - return xxx_messageInfo_GetPackageRequest.Size(m) -} -func (m *GetPackageRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetPackageRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_GetPackageRequest proto.InternalMessageInfo - -func (m *GetPackageRequest) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -type GetBundleRequest struct { - PkgName string `protobuf:"bytes,1,opt,name=pkgName,proto3" json:"pkgName,omitempty"` - ChannelName string `protobuf:"bytes,2,opt,name=channelName,proto3" json:"channelName,omitempty"` - CsvName string `protobuf:"bytes,3,opt,name=csvName,proto3" json:"csvName,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetBundleRequest) Reset() { *m = GetBundleRequest{} } -func (m *GetBundleRequest) String() string { return proto.CompactTextString(m) } -func (*GetBundleRequest) ProtoMessage() {} -func (*GetBundleRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{10} -} - -func (m *GetBundleRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetBundleRequest.Unmarshal(m, b) -} -func (m *GetBundleRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetBundleRequest.Marshal(b, m, deterministic) -} -func (m *GetBundleRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetBundleRequest.Merge(m, src) -} -func (m *GetBundleRequest) XXX_Size() int { - return xxx_messageInfo_GetBundleRequest.Size(m) -} -func (m *GetBundleRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetBundleRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_GetBundleRequest proto.InternalMessageInfo - -func (m *GetBundleRequest) GetPkgName() string { - if m != nil { - return m.PkgName - } - return "" -} - -func (m *GetBundleRequest) GetChannelName() string { - if m != nil { - return m.ChannelName - } - return "" -} - -func (m *GetBundleRequest) GetCsvName() string { - if m != nil { - return m.CsvName - } - return "" -} - -type GetBundleInChannelRequest struct { - PkgName string `protobuf:"bytes,1,opt,name=pkgName,proto3" json:"pkgName,omitempty"` - ChannelName string `protobuf:"bytes,2,opt,name=channelName,proto3" json:"channelName,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetBundleInChannelRequest) Reset() { *m = GetBundleInChannelRequest{} } -func (m *GetBundleInChannelRequest) String() string { return proto.CompactTextString(m) } -func (*GetBundleInChannelRequest) ProtoMessage() {} -func (*GetBundleInChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{11} -} - -func (m *GetBundleInChannelRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetBundleInChannelRequest.Unmarshal(m, b) -} -func (m *GetBundleInChannelRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetBundleInChannelRequest.Marshal(b, m, deterministic) -} -func (m *GetBundleInChannelRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetBundleInChannelRequest.Merge(m, src) -} -func (m *GetBundleInChannelRequest) XXX_Size() int { - return xxx_messageInfo_GetBundleInChannelRequest.Size(m) -} -func (m *GetBundleInChannelRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetBundleInChannelRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_GetBundleInChannelRequest proto.InternalMessageInfo - -func (m *GetBundleInChannelRequest) GetPkgName() string { - if m != nil { - return m.PkgName - } - return "" -} - -func (m *GetBundleInChannelRequest) GetChannelName() string { - if m != nil { - return m.ChannelName - } - return "" -} - -type GetAllReplacementsRequest struct { - CsvName string `protobuf:"bytes,1,opt,name=csvName,proto3" json:"csvName,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetAllReplacementsRequest) Reset() { *m = GetAllReplacementsRequest{} } -func (m *GetAllReplacementsRequest) String() string { return proto.CompactTextString(m) } -func (*GetAllReplacementsRequest) ProtoMessage() {} -func (*GetAllReplacementsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{12} -} - -func (m *GetAllReplacementsRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetAllReplacementsRequest.Unmarshal(m, b) -} -func (m *GetAllReplacementsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetAllReplacementsRequest.Marshal(b, m, deterministic) -} -func (m *GetAllReplacementsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetAllReplacementsRequest.Merge(m, src) -} -func (m *GetAllReplacementsRequest) XXX_Size() int { - return xxx_messageInfo_GetAllReplacementsRequest.Size(m) -} -func (m *GetAllReplacementsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetAllReplacementsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_GetAllReplacementsRequest proto.InternalMessageInfo - -func (m *GetAllReplacementsRequest) GetCsvName() string { - if m != nil { - return m.CsvName - } - return "" -} - -type GetReplacementRequest struct { - CsvName string `protobuf:"bytes,1,opt,name=csvName,proto3" json:"csvName,omitempty"` - PkgName string `protobuf:"bytes,2,opt,name=pkgName,proto3" json:"pkgName,omitempty"` - ChannelName string `protobuf:"bytes,3,opt,name=channelName,proto3" json:"channelName,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetReplacementRequest) Reset() { *m = GetReplacementRequest{} } -func (m *GetReplacementRequest) String() string { return proto.CompactTextString(m) } -func (*GetReplacementRequest) ProtoMessage() {} -func (*GetReplacementRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{13} -} - -func (m *GetReplacementRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetReplacementRequest.Unmarshal(m, b) -} -func (m *GetReplacementRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetReplacementRequest.Marshal(b, m, deterministic) -} -func (m *GetReplacementRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetReplacementRequest.Merge(m, src) -} -func (m *GetReplacementRequest) XXX_Size() int { - return xxx_messageInfo_GetReplacementRequest.Size(m) -} -func (m *GetReplacementRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetReplacementRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_GetReplacementRequest proto.InternalMessageInfo - -func (m *GetReplacementRequest) GetCsvName() string { - if m != nil { - return m.CsvName - } - return "" -} - -func (m *GetReplacementRequest) GetPkgName() string { - if m != nil { - return m.PkgName - } - return "" -} - -func (m *GetReplacementRequest) GetChannelName() string { - if m != nil { - return m.ChannelName - } - return "" -} - -type GetAllProvidersRequest struct { - Group string `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - Kind string `protobuf:"bytes,3,opt,name=kind,proto3" json:"kind,omitempty"` - Plural string `protobuf:"bytes,4,opt,name=plural,proto3" json:"plural,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetAllProvidersRequest) Reset() { *m = GetAllProvidersRequest{} } -func (m *GetAllProvidersRequest) String() string { return proto.CompactTextString(m) } -func (*GetAllProvidersRequest) ProtoMessage() {} -func (*GetAllProvidersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{14} -} - -func (m *GetAllProvidersRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetAllProvidersRequest.Unmarshal(m, b) -} -func (m *GetAllProvidersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetAllProvidersRequest.Marshal(b, m, deterministic) -} -func (m *GetAllProvidersRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetAllProvidersRequest.Merge(m, src) -} -func (m *GetAllProvidersRequest) XXX_Size() int { - return xxx_messageInfo_GetAllProvidersRequest.Size(m) -} -func (m *GetAllProvidersRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetAllProvidersRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_GetAllProvidersRequest proto.InternalMessageInfo - -func (m *GetAllProvidersRequest) GetGroup() string { - if m != nil { - return m.Group - } - return "" -} - -func (m *GetAllProvidersRequest) GetVersion() string { - if m != nil { - return m.Version - } - return "" -} - -func (m *GetAllProvidersRequest) GetKind() string { - if m != nil { - return m.Kind - } - return "" -} - -func (m *GetAllProvidersRequest) GetPlural() string { - if m != nil { - return m.Plural - } - return "" -} - -type GetLatestProvidersRequest struct { - Group string `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - Kind string `protobuf:"bytes,3,opt,name=kind,proto3" json:"kind,omitempty"` - Plural string `protobuf:"bytes,4,opt,name=plural,proto3" json:"plural,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetLatestProvidersRequest) Reset() { *m = GetLatestProvidersRequest{} } -func (m *GetLatestProvidersRequest) String() string { return proto.CompactTextString(m) } -func (*GetLatestProvidersRequest) ProtoMessage() {} -func (*GetLatestProvidersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{15} -} - -func (m *GetLatestProvidersRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetLatestProvidersRequest.Unmarshal(m, b) -} -func (m *GetLatestProvidersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetLatestProvidersRequest.Marshal(b, m, deterministic) -} -func (m *GetLatestProvidersRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetLatestProvidersRequest.Merge(m, src) -} -func (m *GetLatestProvidersRequest) XXX_Size() int { - return xxx_messageInfo_GetLatestProvidersRequest.Size(m) -} -func (m *GetLatestProvidersRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetLatestProvidersRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_GetLatestProvidersRequest proto.InternalMessageInfo - -func (m *GetLatestProvidersRequest) GetGroup() string { - if m != nil { - return m.Group - } - return "" -} - -func (m *GetLatestProvidersRequest) GetVersion() string { - if m != nil { - return m.Version - } - return "" -} - -func (m *GetLatestProvidersRequest) GetKind() string { - if m != nil { - return m.Kind - } - return "" -} - -func (m *GetLatestProvidersRequest) GetPlural() string { - if m != nil { - return m.Plural - } - return "" -} - -type GetDefaultProviderRequest struct { - Group string `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - Kind string `protobuf:"bytes,3,opt,name=kind,proto3" json:"kind,omitempty"` - Plural string `protobuf:"bytes,4,opt,name=plural,proto3" json:"plural,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetDefaultProviderRequest) Reset() { *m = GetDefaultProviderRequest{} } -func (m *GetDefaultProviderRequest) String() string { return proto.CompactTextString(m) } -func (*GetDefaultProviderRequest) ProtoMessage() {} -func (*GetDefaultProviderRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{16} -} - -func (m *GetDefaultProviderRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetDefaultProviderRequest.Unmarshal(m, b) -} -func (m *GetDefaultProviderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetDefaultProviderRequest.Marshal(b, m, deterministic) -} -func (m *GetDefaultProviderRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetDefaultProviderRequest.Merge(m, src) -} -func (m *GetDefaultProviderRequest) XXX_Size() int { - return xxx_messageInfo_GetDefaultProviderRequest.Size(m) -} -func (m *GetDefaultProviderRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetDefaultProviderRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_GetDefaultProviderRequest proto.InternalMessageInfo - -func (m *GetDefaultProviderRequest) GetGroup() string { - if m != nil { - return m.Group - } - return "" -} - -func (m *GetDefaultProviderRequest) GetVersion() string { - if m != nil { - return m.Version - } - return "" -} - -func (m *GetDefaultProviderRequest) GetKind() string { - if m != nil { - return m.Kind - } - return "" -} - -func (m *GetDefaultProviderRequest) GetPlural() string { - if m != nil { - return m.Plural - } - return "" -} - -func init() { - proto.RegisterType((*Channel)(nil), "api.Channel") - proto.RegisterType((*PackageName)(nil), "api.PackageName") - proto.RegisterType((*Package)(nil), "api.Package") - proto.RegisterType((*GroupVersionKind)(nil), "api.GroupVersionKind") - proto.RegisterType((*Dependency)(nil), "api.Dependency") - proto.RegisterType((*Bundle)(nil), "api.Bundle") - proto.RegisterType((*ChannelEntry)(nil), "api.ChannelEntry") - proto.RegisterType((*ListPackageRequest)(nil), "api.ListPackageRequest") - proto.RegisterType((*ListBundlesRequest)(nil), "api.ListBundlesRequest") - proto.RegisterType((*GetPackageRequest)(nil), "api.GetPackageRequest") - proto.RegisterType((*GetBundleRequest)(nil), "api.GetBundleRequest") - proto.RegisterType((*GetBundleInChannelRequest)(nil), "api.GetBundleInChannelRequest") - proto.RegisterType((*GetAllReplacementsRequest)(nil), "api.GetAllReplacementsRequest") - proto.RegisterType((*GetReplacementRequest)(nil), "api.GetReplacementRequest") - proto.RegisterType((*GetAllProvidersRequest)(nil), "api.GetAllProvidersRequest") - proto.RegisterType((*GetLatestProvidersRequest)(nil), "api.GetLatestProvidersRequest") - proto.RegisterType((*GetDefaultProviderRequest)(nil), "api.GetDefaultProviderRequest") -} - -func init() { proto.RegisterFile("registry.proto", fileDescriptor_41af05d40a615591) } - -var fileDescriptor_41af05d40a615591 = []byte{ - // 766 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x56, 0xcb, 0x6e, 0xd3, 0x4c, - 0x14, 0x6e, 0x92, 0x36, 0x97, 0x93, 0xe8, 0xff, 0xdb, 0xf9, 0xdb, 0xfe, 0x26, 0x54, 0x55, 0x98, - 0x0d, 0x5d, 0x45, 0xa5, 0x05, 0x2a, 0x16, 0x2c, 0x5a, 0x0a, 0x11, 0x50, 0x50, 0x65, 0x71, 0x59, - 0xb0, 0x9a, 0xda, 0x43, 0x62, 0xe2, 0x8e, 0x5d, 0xcf, 0x38, 0x55, 0x5e, 0x82, 0x17, 0xe0, 0x95, - 0x78, 0x28, 0xe4, 0xf1, 0x8c, 0x3d, 0x76, 0x9c, 0x16, 0x09, 0x01, 0xbb, 0x9c, 0x33, 0xe7, 0xf2, - 0x9d, 0xcb, 0x77, 0x1c, 0xf8, 0x27, 0xa2, 0x63, 0x8f, 0x8b, 0x68, 0x3e, 0x0c, 0xa3, 0x40, 0x04, - 0xa8, 0x41, 0x42, 0x0f, 0x1f, 0x41, 0xeb, 0xd9, 0x84, 0x30, 0x46, 0x7d, 0x84, 0x60, 0x95, 0x91, - 0x4b, 0x6a, 0xd5, 0x06, 0xb5, 0xbd, 0x8e, 0x2d, 0x7f, 0x23, 0x0b, 0x5a, 0x0e, 0x9f, 0xbd, 0x4d, - 0xd4, 0x75, 0xa9, 0xd6, 0x22, 0xbe, 0x07, 0xdd, 0x73, 0xe2, 0x4c, 0xc9, 0x98, 0x26, 0x62, 0x95, - 0x33, 0xbe, 0x86, 0x96, 0x32, 0xa9, 0x8c, 0xbd, 0x07, 0x6d, 0x27, 0x4d, 0xcd, 0xad, 0xfa, 0xa0, - 0xb1, 0xd7, 0x3d, 0xe8, 0x0d, 0x49, 0xe8, 0x0d, 0x15, 0x1e, 0x3b, 0x7b, 0x45, 0x43, 0x40, 0x2e, - 0xfd, 0x4c, 0x62, 0x5f, 0xa8, 0x37, 0x09, 0xa8, 0x21, 0x63, 0x55, 0xbc, 0x60, 0x06, 0xeb, 0xa3, - 0x28, 0x88, 0xc3, 0x0f, 0x34, 0xe2, 0x5e, 0xc0, 0x5e, 0x7b, 0xcc, 0x45, 0x9b, 0xb0, 0x36, 0x4e, - 0x74, 0x0a, 0x42, 0x2a, 0x24, 0xf5, 0xcd, 0x52, 0x23, 0x5d, 0x9f, 0x12, 0x13, 0xc4, 0x53, 0x8f, - 0xb9, 0x2a, 0x8b, 0xfc, 0x8d, 0xb6, 0xa1, 0x19, 0xfa, 0x71, 0x44, 0x7c, 0x6b, 0x55, 0x6a, 0x95, - 0x84, 0x1f, 0x03, 0x9c, 0xd2, 0x90, 0x32, 0x97, 0x32, 0x67, 0x9e, 0x78, 0x8a, 0x79, 0x98, 0xd5, - 0x9a, 0xfc, 0x4e, 0xb2, 0xcf, 0x88, 0x1f, 0xeb, 0x2e, 0xa6, 0x02, 0xfe, 0xd6, 0x80, 0xe6, 0x49, - 0xcc, 0x5c, 0xbf, 0xd0, 0xe8, 0x5a, 0xa1, 0xd1, 0x68, 0x00, 0xdd, 0x30, 0x6f, 0xb4, 0x0a, 0x60, - 0xaa, 0x12, 0x0b, 0x67, 0xa1, 0x2f, 0xa6, 0x4a, 0x45, 0x7f, 0xc5, 0x03, 0xa6, 0x90, 0x6b, 0x31, - 0x29, 0x29, 0xb8, 0xf8, 0x42, 0x1d, 0x61, 0xad, 0x0d, 0x1a, 0x49, 0x49, 0xa9, 0x84, 0x76, 0x01, - 0x2e, 0x24, 0xb2, 0x73, 0x22, 0x26, 0x56, 0x53, 0x3a, 0x19, 0x1a, 0xf4, 0x04, 0x7a, 0x61, 0x14, - 0xcc, 0x3c, 0x97, 0xba, 0xc7, 0xa1, 0xc7, 0xad, 0x96, 0x1c, 0xe0, 0x96, 0x1c, 0x60, 0xb9, 0xf7, - 0x76, 0xc1, 0x34, 0x71, 0x8d, 0xe8, 0x55, 0xec, 0x45, 0xca, 0xb5, 0x7d, 0xa3, 0xab, 0x69, 0x6a, - 0x8e, 0xab, 0x53, 0x1c, 0xd7, 0x0e, 0x74, 0xf8, 0xd4, 0x0b, 0x6d, 0xc2, 0xc6, 0xd4, 0x02, 0xf9, - 0x96, 0x2b, 0xd0, 0x21, 0xf4, 0x5c, 0x3d, 0x20, 0x8f, 0x72, 0xab, 0x2b, 0x53, 0xfe, 0x2b, 0x53, - 0xe6, 0x93, 0xb3, 0x0b, 0x46, 0xf8, 0x6b, 0x0d, 0x7a, 0x6a, 0xab, 0x9e, 0x33, 0x11, 0xcd, 0xcb, - 0x93, 0xa8, 0xdd, 0x3a, 0x89, 0xfa, 0xe2, 0x24, 0xb2, 0xbe, 0x1a, 0xa3, 0x32, 0x34, 0xa8, 0x0f, - 0xed, 0x88, 0x86, 0x3e, 0x71, 0x28, 0x57, 0xa3, 0xca, 0x64, 0xbc, 0x09, 0xe8, 0xcc, 0xe3, 0x42, - 0x71, 0xca, 0xa6, 0x57, 0x31, 0xe5, 0x42, 0x6b, 0xd3, 0x3d, 0xe2, 0x5a, 0x7b, 0x1f, 0x36, 0x46, - 0xb4, 0x64, 0x5a, 0x49, 0xd2, 0x09, 0xac, 0x8f, 0xa8, 0xf2, 0xd6, 0x76, 0x16, 0xb4, 0xc2, 0xe9, - 0xd8, 0x5c, 0x46, 0x25, 0xfe, 0x44, 0x81, 0xc6, 0x22, 0x37, 0x8a, 0x17, 0xe3, 0x23, 0xdc, 0xc9, - 0x32, 0xbd, 0x64, 0x9a, 0xe5, 0xbf, 0x9e, 0x12, 0x3f, 0x92, 0x81, 0x8f, 0x7d, 0xdf, 0x4e, 0x3b, - 0x75, 0x49, 0x99, 0xe0, 0x46, 0xe0, 0x6a, 0x62, 0xe1, 0x4b, 0xd8, 0x1a, 0x51, 0x61, 0xf8, 0xdc, - 0xea, 0x62, 0xa2, 0xac, 0xdf, 0x88, 0x72, 0x91, 0x83, 0x58, 0xc0, 0x76, 0x8a, 0xf2, 0x3c, 0x25, - 0x43, 0x94, 0x41, 0xfc, 0x9d, 0xa7, 0xe9, 0x5a, 0xf6, 0xe6, 0x8c, 0x08, 0xca, 0xc5, 0x5f, 0x48, - 0x7c, 0x9a, 0x1e, 0x67, 0x9d, 0xf9, 0x0f, 0x24, 0x3e, 0xf8, 0xbe, 0x06, 0x6d, 0x5b, 0x7d, 0xe9, - 0xd0, 0x53, 0xe8, 0x19, 0x94, 0xe1, 0xe8, 0x7f, 0x49, 0xf9, 0x45, 0x16, 0xf5, 0xd7, 0xe5, 0x83, - 0xf1, 0x45, 0xc3, 0x2b, 0xfb, 0x35, 0xf4, 0x10, 0x20, 0x67, 0x11, 0xda, 0x4e, 0x4f, 0x54, 0x99, - 0x56, 0xfd, 0x9e, 0xe9, 0x8b, 0x57, 0xd0, 0x03, 0xe8, 0x64, 0x8b, 0x8e, 0xb6, 0xb4, 0x53, 0x81, - 0x62, 0xfd, 0xae, 0x54, 0xa7, 0x3a, 0xbc, 0x82, 0x4e, 0xe1, 0xbf, 0xcc, 0xe4, 0x45, 0x10, 0xe9, - 0x4f, 0xf2, 0x6e, 0xd1, 0xb9, 0xcc, 0x9a, 0x72, 0x94, 0xf7, 0xb0, 0x33, 0xa2, 0xc2, 0xb8, 0x59, - 0x1e, 0xe5, 0xef, 0x26, 0x44, 0xef, 0x78, 0x1e, 0xae, 0x9a, 0x2b, 0xfd, 0x0d, 0xf3, 0xfb, 0x2b, - 0x6f, 0x9e, 0xec, 0xc2, 0x89, 0x24, 0x4a, 0x9a, 0xc5, 0x08, 0xc7, 0x51, 0x5f, 0xc7, 0x5b, 0x24, - 0x51, 0x19, 0x9a, 0xbd, 0x04, 0x9a, 0xda, 0x0c, 0x74, 0xd7, 0x80, 0x56, 0xde, 0xd3, 0x65, 0xb8, - 0x3e, 0x01, 0xce, 0x76, 0x7b, 0x79, 0xe4, 0xac, 0xe8, 0x6a, 0x12, 0x2c, 0x0b, 0xfe, 0x46, 0x02, - 0x56, 0xfb, 0x9b, 0xd7, 0xae, 0xdc, 0x79, 0x1e, 0xb6, 0x7a, 0xc5, 0xcb, 0xf5, 0x1f, 0x41, 0xd7, - 0xb8, 0xd2, 0xc6, 0x1e, 0x16, 0xef, 0x76, 0xc9, 0x6d, 0xbf, 0x76, 0xd1, 0x94, 0x7f, 0xd6, 0x0e, - 0x7f, 0x04, 0x00, 0x00, 0xff, 0xff, 0x92, 0x79, 0x1b, 0xe1, 0xbe, 0x09, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// RegistryClient is the client API for Registry service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type RegistryClient interface { - ListPackages(ctx context.Context, in *ListPackageRequest, opts ...grpc.CallOption) (Registry_ListPackagesClient, error) - GetPackage(ctx context.Context, in *GetPackageRequest, opts ...grpc.CallOption) (*Package, error) - GetBundle(ctx context.Context, in *GetBundleRequest, opts ...grpc.CallOption) (*Bundle, error) - GetBundleForChannel(ctx context.Context, in *GetBundleInChannelRequest, opts ...grpc.CallOption) (*Bundle, error) - GetChannelEntriesThatReplace(ctx context.Context, in *GetAllReplacementsRequest, opts ...grpc.CallOption) (Registry_GetChannelEntriesThatReplaceClient, error) - GetBundleThatReplaces(ctx context.Context, in *GetReplacementRequest, opts ...grpc.CallOption) (*Bundle, error) - GetChannelEntriesThatProvide(ctx context.Context, in *GetAllProvidersRequest, opts ...grpc.CallOption) (Registry_GetChannelEntriesThatProvideClient, error) - GetLatestChannelEntriesThatProvide(ctx context.Context, in *GetLatestProvidersRequest, opts ...grpc.CallOption) (Registry_GetLatestChannelEntriesThatProvideClient, error) - GetDefaultBundleThatProvides(ctx context.Context, in *GetDefaultProviderRequest, opts ...grpc.CallOption) (*Bundle, error) - ListBundles(ctx context.Context, in *ListBundlesRequest, opts ...grpc.CallOption) (Registry_ListBundlesClient, error) -} - -type registryClient struct { - cc *grpc.ClientConn -} - -func NewRegistryClient(cc *grpc.ClientConn) RegistryClient { - return ®istryClient{cc} -} - -func (c *registryClient) ListPackages(ctx context.Context, in *ListPackageRequest, opts ...grpc.CallOption) (Registry_ListPackagesClient, error) { - stream, err := c.cc.NewStream(ctx, &_Registry_serviceDesc.Streams[0], "/api.Registry/ListPackages", opts...) - if err != nil { - return nil, err - } - x := ®istryListPackagesClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Registry_ListPackagesClient interface { - Recv() (*PackageName, error) - grpc.ClientStream -} - -type registryListPackagesClient struct { - grpc.ClientStream -} - -func (x *registryListPackagesClient) Recv() (*PackageName, error) { - m := new(PackageName) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *registryClient) GetPackage(ctx context.Context, in *GetPackageRequest, opts ...grpc.CallOption) (*Package, error) { - out := new(Package) - err := c.cc.Invoke(ctx, "/api.Registry/GetPackage", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *registryClient) GetBundle(ctx context.Context, in *GetBundleRequest, opts ...grpc.CallOption) (*Bundle, error) { - out := new(Bundle) - err := c.cc.Invoke(ctx, "/api.Registry/GetBundle", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *registryClient) GetBundleForChannel(ctx context.Context, in *GetBundleInChannelRequest, opts ...grpc.CallOption) (*Bundle, error) { - out := new(Bundle) - err := c.cc.Invoke(ctx, "/api.Registry/GetBundleForChannel", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *registryClient) GetChannelEntriesThatReplace(ctx context.Context, in *GetAllReplacementsRequest, opts ...grpc.CallOption) (Registry_GetChannelEntriesThatReplaceClient, error) { - stream, err := c.cc.NewStream(ctx, &_Registry_serviceDesc.Streams[1], "/api.Registry/GetChannelEntriesThatReplace", opts...) - if err != nil { - return nil, err - } - x := ®istryGetChannelEntriesThatReplaceClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Registry_GetChannelEntriesThatReplaceClient interface { - Recv() (*ChannelEntry, error) - grpc.ClientStream -} - -type registryGetChannelEntriesThatReplaceClient struct { - grpc.ClientStream -} - -func (x *registryGetChannelEntriesThatReplaceClient) Recv() (*ChannelEntry, error) { - m := new(ChannelEntry) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *registryClient) GetBundleThatReplaces(ctx context.Context, in *GetReplacementRequest, opts ...grpc.CallOption) (*Bundle, error) { - out := new(Bundle) - err := c.cc.Invoke(ctx, "/api.Registry/GetBundleThatReplaces", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *registryClient) GetChannelEntriesThatProvide(ctx context.Context, in *GetAllProvidersRequest, opts ...grpc.CallOption) (Registry_GetChannelEntriesThatProvideClient, error) { - stream, err := c.cc.NewStream(ctx, &_Registry_serviceDesc.Streams[2], "/api.Registry/GetChannelEntriesThatProvide", opts...) - if err != nil { - return nil, err - } - x := ®istryGetChannelEntriesThatProvideClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Registry_GetChannelEntriesThatProvideClient interface { - Recv() (*ChannelEntry, error) - grpc.ClientStream -} - -type registryGetChannelEntriesThatProvideClient struct { - grpc.ClientStream -} - -func (x *registryGetChannelEntriesThatProvideClient) Recv() (*ChannelEntry, error) { - m := new(ChannelEntry) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *registryClient) GetLatestChannelEntriesThatProvide(ctx context.Context, in *GetLatestProvidersRequest, opts ...grpc.CallOption) (Registry_GetLatestChannelEntriesThatProvideClient, error) { - stream, err := c.cc.NewStream(ctx, &_Registry_serviceDesc.Streams[3], "/api.Registry/GetLatestChannelEntriesThatProvide", opts...) - if err != nil { - return nil, err - } - x := ®istryGetLatestChannelEntriesThatProvideClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Registry_GetLatestChannelEntriesThatProvideClient interface { - Recv() (*ChannelEntry, error) - grpc.ClientStream -} - -type registryGetLatestChannelEntriesThatProvideClient struct { - grpc.ClientStream -} - -func (x *registryGetLatestChannelEntriesThatProvideClient) Recv() (*ChannelEntry, error) { - m := new(ChannelEntry) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *registryClient) GetDefaultBundleThatProvides(ctx context.Context, in *GetDefaultProviderRequest, opts ...grpc.CallOption) (*Bundle, error) { - out := new(Bundle) - err := c.cc.Invoke(ctx, "/api.Registry/GetDefaultBundleThatProvides", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *registryClient) ListBundles(ctx context.Context, in *ListBundlesRequest, opts ...grpc.CallOption) (Registry_ListBundlesClient, error) { - stream, err := c.cc.NewStream(ctx, &_Registry_serviceDesc.Streams[4], "/api.Registry/ListBundles", opts...) - if err != nil { - return nil, err - } - x := ®istryListBundlesClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Registry_ListBundlesClient interface { - Recv() (*Bundle, error) - grpc.ClientStream -} - -type registryListBundlesClient struct { - grpc.ClientStream -} - -func (x *registryListBundlesClient) Recv() (*Bundle, error) { - m := new(Bundle) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// RegistryServer is the server API for Registry service. -type RegistryServer interface { - ListPackages(*ListPackageRequest, Registry_ListPackagesServer) error - GetPackage(context.Context, *GetPackageRequest) (*Package, error) - GetBundle(context.Context, *GetBundleRequest) (*Bundle, error) - GetBundleForChannel(context.Context, *GetBundleInChannelRequest) (*Bundle, error) - GetChannelEntriesThatReplace(*GetAllReplacementsRequest, Registry_GetChannelEntriesThatReplaceServer) error - GetBundleThatReplaces(context.Context, *GetReplacementRequest) (*Bundle, error) - GetChannelEntriesThatProvide(*GetAllProvidersRequest, Registry_GetChannelEntriesThatProvideServer) error - GetLatestChannelEntriesThatProvide(*GetLatestProvidersRequest, Registry_GetLatestChannelEntriesThatProvideServer) error - GetDefaultBundleThatProvides(context.Context, *GetDefaultProviderRequest) (*Bundle, error) - ListBundles(*ListBundlesRequest, Registry_ListBundlesServer) error -} - -// UnimplementedRegistryServer can be embedded to have forward compatible implementations. -type UnimplementedRegistryServer struct { -} - -func (*UnimplementedRegistryServer) ListPackages(req *ListPackageRequest, srv Registry_ListPackagesServer) error { - return status.Errorf(codes.Unimplemented, "method ListPackages not implemented") -} -func (*UnimplementedRegistryServer) GetPackage(ctx context.Context, req *GetPackageRequest) (*Package, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetPackage not implemented") -} -func (*UnimplementedRegistryServer) GetBundle(ctx context.Context, req *GetBundleRequest) (*Bundle, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetBundle not implemented") -} -func (*UnimplementedRegistryServer) GetBundleForChannel(ctx context.Context, req *GetBundleInChannelRequest) (*Bundle, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetBundleForChannel not implemented") -} -func (*UnimplementedRegistryServer) GetChannelEntriesThatReplace(req *GetAllReplacementsRequest, srv Registry_GetChannelEntriesThatReplaceServer) error { - return status.Errorf(codes.Unimplemented, "method GetChannelEntriesThatReplace not implemented") -} -func (*UnimplementedRegistryServer) GetBundleThatReplaces(ctx context.Context, req *GetReplacementRequest) (*Bundle, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetBundleThatReplaces not implemented") -} -func (*UnimplementedRegistryServer) GetChannelEntriesThatProvide(req *GetAllProvidersRequest, srv Registry_GetChannelEntriesThatProvideServer) error { - return status.Errorf(codes.Unimplemented, "method GetChannelEntriesThatProvide not implemented") -} -func (*UnimplementedRegistryServer) GetLatestChannelEntriesThatProvide(req *GetLatestProvidersRequest, srv Registry_GetLatestChannelEntriesThatProvideServer) error { - return status.Errorf(codes.Unimplemented, "method GetLatestChannelEntriesThatProvide not implemented") -} -func (*UnimplementedRegistryServer) GetDefaultBundleThatProvides(ctx context.Context, req *GetDefaultProviderRequest) (*Bundle, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetDefaultBundleThatProvides not implemented") -} -func (*UnimplementedRegistryServer) ListBundles(req *ListBundlesRequest, srv Registry_ListBundlesServer) error { - return status.Errorf(codes.Unimplemented, "method ListBundles not implemented") -} - -func RegisterRegistryServer(s *grpc.Server, srv RegistryServer) { - s.RegisterService(&_Registry_serviceDesc, srv) -} - -func _Registry_ListPackages_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(ListPackageRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(RegistryServer).ListPackages(m, ®istryListPackagesServer{stream}) -} - -type Registry_ListPackagesServer interface { - Send(*PackageName) error - grpc.ServerStream -} - -type registryListPackagesServer struct { - grpc.ServerStream -} - -func (x *registryListPackagesServer) Send(m *PackageName) error { - return x.ServerStream.SendMsg(m) -} - -func _Registry_GetPackage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetPackageRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RegistryServer).GetPackage(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Registry/GetPackage", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RegistryServer).GetPackage(ctx, req.(*GetPackageRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Registry_GetBundle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetBundleRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RegistryServer).GetBundle(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Registry/GetBundle", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RegistryServer).GetBundle(ctx, req.(*GetBundleRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Registry_GetBundleForChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetBundleInChannelRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RegistryServer).GetBundleForChannel(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Registry/GetBundleForChannel", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RegistryServer).GetBundleForChannel(ctx, req.(*GetBundleInChannelRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Registry_GetChannelEntriesThatReplace_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetAllReplacementsRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(RegistryServer).GetChannelEntriesThatReplace(m, ®istryGetChannelEntriesThatReplaceServer{stream}) -} - -type Registry_GetChannelEntriesThatReplaceServer interface { - Send(*ChannelEntry) error - grpc.ServerStream -} - -type registryGetChannelEntriesThatReplaceServer struct { - grpc.ServerStream -} - -func (x *registryGetChannelEntriesThatReplaceServer) Send(m *ChannelEntry) error { - return x.ServerStream.SendMsg(m) -} - -func _Registry_GetBundleThatReplaces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetReplacementRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RegistryServer).GetBundleThatReplaces(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Registry/GetBundleThatReplaces", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RegistryServer).GetBundleThatReplaces(ctx, req.(*GetReplacementRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Registry_GetChannelEntriesThatProvide_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetAllProvidersRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(RegistryServer).GetChannelEntriesThatProvide(m, ®istryGetChannelEntriesThatProvideServer{stream}) -} - -type Registry_GetChannelEntriesThatProvideServer interface { - Send(*ChannelEntry) error - grpc.ServerStream -} - -type registryGetChannelEntriesThatProvideServer struct { - grpc.ServerStream -} - -func (x *registryGetChannelEntriesThatProvideServer) Send(m *ChannelEntry) error { - return x.ServerStream.SendMsg(m) -} - -func _Registry_GetLatestChannelEntriesThatProvide_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetLatestProvidersRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(RegistryServer).GetLatestChannelEntriesThatProvide(m, ®istryGetLatestChannelEntriesThatProvideServer{stream}) -} - -type Registry_GetLatestChannelEntriesThatProvideServer interface { - Send(*ChannelEntry) error - grpc.ServerStream -} - -type registryGetLatestChannelEntriesThatProvideServer struct { - grpc.ServerStream -} - -func (x *registryGetLatestChannelEntriesThatProvideServer) Send(m *ChannelEntry) error { - return x.ServerStream.SendMsg(m) -} - -func _Registry_GetDefaultBundleThatProvides_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetDefaultProviderRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RegistryServer).GetDefaultBundleThatProvides(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Registry/GetDefaultBundleThatProvides", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RegistryServer).GetDefaultBundleThatProvides(ctx, req.(*GetDefaultProviderRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Registry_ListBundles_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(ListBundlesRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(RegistryServer).ListBundles(m, ®istryListBundlesServer{stream}) -} - -type Registry_ListBundlesServer interface { - Send(*Bundle) error - grpc.ServerStream -} - -type registryListBundlesServer struct { - grpc.ServerStream -} - -func (x *registryListBundlesServer) Send(m *Bundle) error { - return x.ServerStream.SendMsg(m) -} - -var _Registry_serviceDesc = grpc.ServiceDesc{ - ServiceName: "api.Registry", - HandlerType: (*RegistryServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetPackage", - Handler: _Registry_GetPackage_Handler, - }, - { - MethodName: "GetBundle", - Handler: _Registry_GetBundle_Handler, - }, - { - MethodName: "GetBundleForChannel", - Handler: _Registry_GetBundleForChannel_Handler, - }, - { - MethodName: "GetBundleThatReplaces", - Handler: _Registry_GetBundleThatReplaces_Handler, - }, - { - MethodName: "GetDefaultBundleThatProvides", - Handler: _Registry_GetDefaultBundleThatProvides_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "ListPackages", - Handler: _Registry_ListPackages_Handler, - ServerStreams: true, - }, - { - StreamName: "GetChannelEntriesThatReplace", - Handler: _Registry_GetChannelEntriesThatReplace_Handler, - ServerStreams: true, - }, - { - StreamName: "GetChannelEntriesThatProvide", - Handler: _Registry_GetChannelEntriesThatProvide_Handler, - ServerStreams: true, - }, - { - StreamName: "GetLatestChannelEntriesThatProvide", - Handler: _Registry_GetLatestChannelEntriesThatProvide_Handler, - ServerStreams: true, - }, - { - StreamName: "ListBundles", - Handler: _Registry_ListBundles_Handler, - ServerStreams: true, - }, - }, - Metadata: "registry.proto", -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.proto b/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.proto deleted file mode 100644 index bb32bee60..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.proto +++ /dev/null @@ -1,115 +0,0 @@ -syntax = "proto3"; - -package api; - -service Registry { - rpc ListPackages(ListPackageRequest) returns (stream PackageName) {} - rpc GetPackage(GetPackageRequest) returns (Package) {} - rpc GetBundle(GetBundleRequest) returns (Bundle) {} - rpc GetBundleForChannel(GetBundleInChannelRequest) returns (Bundle) {} - rpc GetChannelEntriesThatReplace(GetAllReplacementsRequest) returns (stream ChannelEntry) {} - rpc GetBundleThatReplaces(GetReplacementRequest) returns (Bundle) {} - rpc GetChannelEntriesThatProvide(GetAllProvidersRequest) returns (stream ChannelEntry) {} - rpc GetLatestChannelEntriesThatProvide(GetLatestProvidersRequest) returns (stream ChannelEntry) {} - rpc GetDefaultBundleThatProvides(GetDefaultProviderRequest) returns (Bundle) {} - rpc ListBundles(ListBundlesRequest) returns (stream Bundle) {} -} - - -message Channel{ - string name = 1; - string csvName = 2; -} - -message PackageName{ - string name = 1; -} - -message Package{ - string name = 1; - repeated Channel channels = 2; - string defaultChannelName = 3; -} - -message GroupVersionKind{ - string group = 1; - string version = 2; - string kind = 3; - string plural = 4; -} - -message Dependency{ - string type = 1; - string value = 2; -} - -message Bundle{ - string csvName = 1; - string packageName = 2; - string channelName = 3; - string csvJson = 4; - repeated string object = 5; - string bundlePath = 6; - repeated GroupVersionKind providedApis = 7; - repeated GroupVersionKind requiredApis = 8; - string version = 9; - string skipRange = 10; - repeated Dependency dependencies = 11; -} - -message ChannelEntry{ - string packageName = 1; - string channelName = 2; - string bundleName = 3; - string replaces = 4; -} - -message ListPackageRequest{} - -message ListBundlesRequest{} - -message GetPackageRequest{ - string name = 1; -} - -message GetBundleRequest{ - string pkgName = 1; - string channelName = 2; - string csvName = 3; -} - -message GetBundleInChannelRequest{ - string pkgName = 1; - string channelName = 2; -} - -message GetAllReplacementsRequest{ - string csvName = 1; -} - -message GetReplacementRequest{ - string csvName = 1; - string pkgName = 2; - string channelName = 3; -} - -message GetAllProvidersRequest{ - string group = 1; - string version = 2; - string kind = 3; - string plural = 4; -} - -message GetLatestProvidersRequest{ - string group = 1; - string version = 2; - string kind = 3; - string plural = 4; -} - -message GetDefaultProviderRequest{ - string group = 1; - string version = 2; - string kind = 3; - string plural = 4; -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/image/reference.go b/vendor/github.com/operator-framework/operator-registry/pkg/image/reference.go deleted file mode 100644 index 660df5089..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/image/reference.go +++ /dev/null @@ -1,16 +0,0 @@ -package image - -import "fmt" - -// Reference describes a reference to a container image. -type Reference interface { - fmt.Stringer -} - -// SimpleReference is a reference backed by a string with no additional validation. -type SimpleReference string - -func (s SimpleReference) String() string { - ref := string(s) - return ref -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/image/registry.go b/vendor/github.com/operator-framework/operator-registry/pkg/image/registry.go deleted file mode 100644 index d47507ab2..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/image/registry.go +++ /dev/null @@ -1,32 +0,0 @@ -package image - -import ( - "context" -) - -// Registry knows how to Pull and Unpack Operator Bundle images to the filesystem. -// Note: In the future, Registry will know how to Build and Push Operator Bundle images as well. -type Registry interface { - // Pull fetches and stores an image by reference. - Pull(ctx context.Context, ref Reference) error - - // Push uploads an image to the remote registry of its reference. - // If the referenced image does not exist in the registry, an error is returned. - // Push(ctx context.Context, ref string) error - - // Unpack writes the unpackaged content of an image to a directory. - // If the referenced image does not exist in the registry, an error is returned. - Unpack(ctx context.Context, ref Reference, dir string) error - - // Labels gets the labels for an image that is already stored. - Labels(ctx context.Context, ref Reference) (map[string]string, error) - - // Destroy cleans up any on-disk resources used to track images - Destroy() error - - // Pack creates and stores an image based on the given reference and returns a reference to the new image. - // If the referenced image does not exist in the registry, a new image is created from scratch. - // If it exists, it's used as the base image. - // Pack(ctx context.Context, ref Reference, from io.Reader) (next string, err error) -} - diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/bundle.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/bundle.go deleted file mode 100644 index 92600e83a..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/bundle.go +++ /dev/null @@ -1,287 +0,0 @@ -package registry - -import ( - "fmt" - "strings" - - "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/apimachinery/pkg/util/yaml" -) - -// Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. -var Scheme = runtime.NewScheme() - -// Codecs provides access to encoding and decoding for the scheme -var Codecs = serializer.NewCodecFactory(Scheme) - -func DefaultYAMLDecoder() runtime.Decoder { - return Codecs.UniversalDeserializer() -} - -func init() { - if err := v1beta1.AddToScheme(Scheme); err != nil { - panic(err) - } -} - -type Bundle struct { - Name string - Objects []*unstructured.Unstructured - Package string - Channels []string - BundleImage string - csv *ClusterServiceVersion - crds []*v1beta1.CustomResourceDefinition - Dependencies []*Dependency - cacheStale bool -} - -func NewBundle(name, pkgName string, channels []string, objs ...*unstructured.Unstructured) *Bundle { - bundle := &Bundle{Name: name, Package: pkgName, Channels: channels, cacheStale: false} - for _, o := range objs { - bundle.Add(o) - } - return bundle -} - -func NewBundleFromStrings(name, pkgName string, channels []string, objs []string) (*Bundle, error) { - unstObjs := []*unstructured.Unstructured{} - for _, o := range objs { - dec := yaml.NewYAMLOrJSONDecoder(strings.NewReader(o), 10) - unst := &unstructured.Unstructured{} - if err := dec.Decode(unst); err != nil { - return nil, err - } - unstObjs = append(unstObjs, unst) - } - return NewBundle(name, pkgName, channels, unstObjs...), nil -} - -func (b *Bundle) Size() int { - return len(b.Objects) -} - -func (b *Bundle) Add(obj *unstructured.Unstructured) { - b.Objects = append(b.Objects, obj) - b.cacheStale = true -} - -func (b *Bundle) ClusterServiceVersion() (*ClusterServiceVersion, error) { - if err := b.cache(); err != nil { - return nil, err - } - return b.csv, nil -} - -func (b *Bundle) Version() (string, error) { - if err := b.cache(); err != nil { - return "", err - } - return b.csv.GetVersion() -} - -func (b *Bundle) SkipRange() (string, error) { - if err := b.cache(); err != nil { - return "", err - } - return b.csv.GetSkipRange(), nil -} - -func (b *Bundle) Replaces() (string, error) { - if err := b.cache(); err != nil { - return "", err - } - return b.csv.GetReplaces() -} - -func (b *Bundle) Skips() ([]string, error) { - if err := b.cache(); err != nil { - return nil, err - } - return b.csv.GetSkips() -} - -func (b *Bundle) CustomResourceDefinitions() ([]*v1beta1.CustomResourceDefinition, error) { - if err := b.cache(); err != nil { - return nil, err - } - return b.crds, nil -} - -func (b *Bundle) ProvidedAPIs() (map[APIKey]struct{}, error) { - provided := map[APIKey]struct{}{} - crds, err := b.CustomResourceDefinitions() - if err != nil { - return nil, err - } - for _, crd := range crds { - for _, v := range crd.Spec.Versions { - provided[APIKey{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Spec.Names.Kind, Plural: crd.Spec.Names.Plural}] = struct{}{} - } - if crd.Spec.Version != "" { - provided[APIKey{Group: crd.Spec.Group, Version: crd.Spec.Version, Kind: crd.Spec.Names.Kind, Plural: crd.Spec.Names.Plural}] = struct{}{} - } - } - - csv, err := b.ClusterServiceVersion() - if err != nil { - return nil, err - } - - ownedAPIs, _, err := csv.GetApiServiceDefinitions() - if err != nil { - return nil, err - } - for _, api := range ownedAPIs { - provided[APIKey{Group: api.Group, Version: api.Version, Kind: api.Kind, Plural: api.Name}] = struct{}{} - } - return provided, nil -} - -func (b *Bundle) RequiredAPIs() (map[APIKey]struct{}, error) { - required := map[APIKey]struct{}{} - csv, err := b.ClusterServiceVersion() - if err != nil { - return nil, err - } - - _, requiredCRDs, err := csv.GetCustomResourceDefintions() - if err != nil { - return nil, err - } - for _, api := range requiredCRDs { - parts := strings.SplitN(api.Name, ".", 2) - if len(parts) < 2 { - return nil, fmt.Errorf("couldn't parse plural.group from crd name: %s", api.Name) - } - required[APIKey{parts[1], api.Version, api.Kind, parts[0]}] = struct{}{} - - } - _, requiredAPIs, err := csv.GetApiServiceDefinitions() - if err != nil { - return nil, err - } - for _, api := range requiredAPIs { - required[APIKey{Group: api.Group, Version: api.Version, Kind: api.Kind, Plural: api.Name}] = struct{}{} - } - return required, nil -} - -func (b *Bundle) AllProvidedAPIsInBundle() error { - csv, err := b.ClusterServiceVersion() - if err != nil { - return err - } - bundleAPIs, err := b.ProvidedAPIs() - if err != nil { - return err - } - ownedCRDs, _, err := csv.GetCustomResourceDefintions() - if err != nil { - return err - } - shouldExist := make(map[APIKey]struct{}, len(ownedCRDs)) - for _, crdDef := range ownedCRDs { - parts := strings.SplitN(crdDef.Name, ".", 2) - if len(parts) < 2 { - return fmt.Errorf("couldn't parse plural.group from crd name: %s", crdDef.Name) - } - shouldExist[APIKey{parts[1], crdDef.Version, crdDef.Kind, parts[0]}] = struct{}{} - } - for key := range shouldExist { - if _, ok := bundleAPIs[key]; !ok { - return fmt.Errorf("couldn't find %v in bundle. found: %v", key, bundleAPIs) - } - } - // note: don't need to check bundle for extension apiserver types, which don't require extra bundle entries - return nil -} - -func (b *Bundle) Serialize() (csvName, bundleImage string, csvBytes []byte, bundleBytes []byte, err error) { - csvCount := 0 - for _, obj := range b.Objects { - objBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) - if err != nil { - return "", "", nil, nil, err - } - bundleBytes = append(bundleBytes, objBytes...) - - if obj.GetObjectKind().GroupVersionKind().Kind == "ClusterServiceVersion" { - csvName = obj.GetName() - csvBytes, err = runtime.Encode(unstructured.UnstructuredJSONScheme, obj) - if err != nil { - return "", "", nil, nil, err - } - csvCount += 1 - if csvCount > 1 { - return "", "", nil, nil, fmt.Errorf("two csvs found in one bundle") - } - } - } - - return csvName, b.BundleImage, csvBytes, bundleBytes, nil -} - -func (b *Bundle) Images() (map[string]struct{}, error) { - csv, err := b.ClusterServiceVersion() - if err != nil { - return nil, err - } - - images, err := csv.GetOperatorImages() - if err != nil { - return nil, err - } - - relatedImages, err := csv.GetRelatedImages() - if err != nil { - return nil, err - } - for img := range relatedImages { - images[img] = struct{}{} - } - - return images, nil -} - -func (b *Bundle) cache() error { - if !b.cacheStale { - return nil - } - for _, o := range b.Objects { - if o.GetObjectKind().GroupVersionKind().Kind == "ClusterServiceVersion" { - csv := &ClusterServiceVersion{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(o.UnstructuredContent(), csv); err != nil { - return err - } - b.csv = csv - break - } - } - - if b.crds == nil { - b.crds = []*v1beta1.CustomResourceDefinition{} - } - for _, o := range b.Objects { - if o.GetObjectKind().GroupVersionKind().Kind == "CustomResourceDefinition" { - crd := &v1beta1.CustomResourceDefinition{} - // Marshal Unstructured and Decode as CustomResourceDefinition. FromUnstructured has issues - // converting JSON numbers to float64 for CRD minimum/maximum validation. - cb, err := o.MarshalJSON() - if err != nil { - return err - } - dec := serializer.NewCodecFactory(Scheme).UniversalDeserializer() - if _, _, err = dec.Decode(cb, nil, crd); err != nil { - return fmt.Errorf("error decoding CRD: %v", err) - } - b.crds = append(b.crds, crd) - } - } - - b.cacheStale = false - return nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/bundlegraphloader.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/bundlegraphloader.go deleted file mode 100644 index f03c128a3..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/bundlegraphloader.go +++ /dev/null @@ -1,147 +0,0 @@ -package registry - -import ( - "fmt" - - "github.com/blang/semver" -) - -// BundleGraphLoader generates updated graphs by adding bundles to them, updating -// the graph implicitly via semantic version of each bundle -type BundleGraphLoader struct { -} - -// AddBundleToGraph takes a bundle and an existing graph and updates the graph to insert the new bundle -// into each channel it is included in -func (g *BundleGraphLoader) AddBundleToGraph(bundle *Bundle, graph *Package, newDefaultChannel string, skippatch bool) (*Package, error) { - bundleVersion, err := bundle.Version() - if err != nil { - return nil, fmt.Errorf("Unable to extract bundle version from bundle %s, can't insert in semver mode", bundle.BundleImage) - } - - versionToAdd, err := semver.Make(bundleVersion) - if err != nil { - return nil, fmt.Errorf("Bundle version %s is not valid", bundleVersion) - } - - newBundleKey := BundleKey{ - CsvName: bundle.Name, - Version: versionToAdd.String(), - BundlePath: bundle.BundleImage, - } - - // initialize the graph if it started empty - if graph.Name == "" { - graph.Name = bundle.Package - } - if newDefaultChannel != "" { - graph.DefaultChannel = newDefaultChannel - } - - // generate the DAG for each channel the new bundle is being insert into - for _, channel := range bundle.Channels { - replaces := make(map[BundleKey]struct{}, 0) - - // If the channel doesn't exist yet, initialize it - if !graph.HasChannel(channel) { - // create the channel and add a single node - newChannelGraph := Channel{ - Head: newBundleKey, - Nodes: map[BundleKey]map[BundleKey]struct{}{ - newBundleKey: nil, - }, - } - if graph.Channels == nil { - graph.Channels = make(map[string]Channel, 1) - } - graph.Channels[channel] = newChannelGraph - continue - } - - // find the version(s) it should sit between - channelGraph := graph.Channels[channel] - if channelGraph.Nodes == nil { - channelGraph.Nodes = make(map[BundleKey]map[BundleKey]struct{}, 1) - } - - lowestAhead := BundleKey{} - greatestBehind := BundleKey{} - skipPatchCandidates := []BundleKey{} - - // Iterate over existing nodes and compare the new node's version to find the - // lowest version above it and highest version below it (to insert between these nodes) - for node := range channelGraph.Nodes { - nodeVersion, err := semver.Make(node.Version) - if err != nil { - return nil, fmt.Errorf("Unable to parse existing bundle version stored in index %s %s %s", - node.CsvName, node.Version, node.BundlePath) - } - - switch comparison := nodeVersion.Compare(versionToAdd); comparison { - case 0: - return nil, fmt.Errorf("Bundle version %s already added to index", bundleVersion) - case 1: - if lowestAhead.IsEmpty() { - lowestAhead = node - } else { - lowestAheadSemver, _ := semver.Make(lowestAhead.Version) - if nodeVersion.LT(lowestAheadSemver) { - lowestAhead = node - } - } - case -1: - if greatestBehind.IsEmpty() { - greatestBehind = node - } else { - greatestBehindSemver, _ := semver.Make(greatestBehind.Version) - if nodeVersion.GT(greatestBehindSemver) { - greatestBehind = node - } - } - } - - // if skippatch mode is enabled, check each node to determine if z-updates should - // be replaced as well. Keep track of them to delete those nodes from the graph itself, - // just be aware of them for replacements - if skippatch { - if isSkipPatchCandidate(versionToAdd, nodeVersion) { - skipPatchCandidates = append(skipPatchCandidates, node) - replaces[node] = struct{}{} - } - } - } - - // If we found a node behind the one we're adding, make the new node replace it - if !greatestBehind.IsEmpty() { - replaces[greatestBehind] = struct{}{} - } - - // If we found a node ahead of the one we're adding, make the lowest to replace - // the new node. If we didn't find a node semantically ahead, the new node is - // the new channel head - if !lowestAhead.IsEmpty() { - channelGraph.Nodes[lowestAhead] = map[BundleKey]struct{}{ - newBundleKey: struct{}{}, - } - } else { - channelGraph.Head = newBundleKey - } - - if skippatch { - // Remove the nodes that are now being skipped by a new patch version update - for _, candidate := range skipPatchCandidates { - delete(channelGraph.Nodes, candidate) - } - } - - // add the node and update the graph - channelGraph.Nodes[newBundleKey] = replaces - graph.Channels[channel] = channelGraph - } - - return graph, nil -} - -func isSkipPatchCandidate(version, toCompare semver.Version) bool { - return (version.Major == toCompare.Major) && (version.Minor == toCompare.Minor) && (version.Patch > toCompare.Patch) -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/channelupdateoptions.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/channelupdateoptions.go deleted file mode 100644 index 85f5acb40..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/channelupdateoptions.go +++ /dev/null @@ -1,27 +0,0 @@ -package registry - -import ( - "fmt" - "strings" -) - -type Mode int - -const ( - ReplacesMode = iota - SemVerMode - SkipPatchMode -) - -func GetModeFromString(mode string) (Mode, error) { - switch strings.ToLower(mode) { - case "replaces": - return ReplacesMode, nil - case "semver": - return SemVerMode, nil - case "semver-skippatch": - return SkipPatchMode, nil - default: - return -1, fmt.Errorf("Invalid channel update mode %s specified", mode) - } -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/conversion.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/conversion.go deleted file mode 100644 index fd79b31c2..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/conversion.go +++ /dev/null @@ -1,83 +0,0 @@ -package registry - -import ( - "encoding/json" - "fmt" - "strings" - - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/util/yaml" - - "github.com/operator-framework/operator-registry/pkg/api" -) - -func PackageManifestToAPIPackage(manifest *PackageManifest) *api.Package { - channels := []*api.Channel{} - for _, c := range manifest.Channels { - channels = append(channels, PackageChannelToAPIChannel(&c)) - } - return &api.Package{ - Name: manifest.PackageName, - DefaultChannelName: manifest.DefaultChannelName, - Channels: channels, - } -} - -func PackageChannelToAPIChannel(channel *PackageChannel) *api.Channel { - return &api.Channel{ - Name: channel.Name, - CsvName: channel.CurrentCSVName, - } -} - -func ChannelEntryToAPIChannelEntry(entry *ChannelEntry) *api.ChannelEntry { - return &api.ChannelEntry{ - PackageName: entry.PackageName, - ChannelName: entry.ChannelName, - BundleName: entry.BundleName, - Replaces: entry.Replaces, - } -} - -// Bundle strings are appended json objects, we need to split them apart -// e.g. {"my":"obj"}{"csv":"data"}{"crd":"too"} -func BundleStringToObjectStrings(bundleString string) ([]string, error) { - objs := []string{} - dec := json.NewDecoder(strings.NewReader(bundleString)) - - for dec.More() { - var m json.RawMessage - err := dec.Decode(&m) - if err != nil { - return nil, err - } - objs = append(objs, string(m)) - } - return objs, nil -} - -func BundleStringToAPIBundle(bundleString string) (*api.Bundle, error) { - objs, err := BundleStringToObjectStrings(bundleString) - if err != nil { - return nil, err - } - out := &api.Bundle{ - Object: objs, - } - for _, o := range objs { - dec := yaml.NewYAMLOrJSONDecoder(strings.NewReader(o), 10) - unst := &unstructured.Unstructured{} - if err := dec.Decode(unst); err != nil { - return nil, err - } - if unst.GetKind() == "ClusterServiceVersion" { - out.CsvName = unst.GetName() - out.CsvJson = o - break - } - } - if out.CsvName == "" { - return nil, fmt.Errorf("no csv in bundle") - } - return out, nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/csv.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/csv.go deleted file mode 100644 index 3600204f5..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/csv.go +++ /dev/null @@ -1,334 +0,0 @@ -package registry - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path" - - v1 "k8s.io/api/apps/v1" - 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/util/yaml" - - "github.com/operator-framework/api/pkg/operators" -) - -const ( - // Name of the CSV's kind - clusterServiceVersionKind = "ClusterServiceVersion" - - // Name of the section under which the list of owned and required list of - // CRD(s) is specified inside an operator manifest. - customResourceDefinitions = "customresourcedefinitions" - - // Name of the section under which the list of owned and required list of - // apiservices is specified inside an operator manifest. - apiServiceDefinitions = "apiservicedefinitions" - - // The yaml attribute that points to the name of an older - // ClusterServiceVersion object that the current ClusterServiceVersion - // replaces. - replaces = "replaces" - - // The yaml attribute that points to the names of older - // ClusterServiceVersion objects that the current ClusterServiceVersion - // skips - skips = "skips" - - // The yaml attribute that specifies the version of the ClusterServiceVersion - // expected to be semver and parseable by blang/semver - version = "version" - - // The yaml attribute that specifies the related images of the ClusterServiceVersion - relatedImages = "relatedImages" - - // The yaml attribute that specifies the skipRange of the ClusterServiceVersion - skipRangeAnnotationKey = "olm.skipRange" -) - -// ClusterServiceVersion is a structured representation of cluster service -// version object(s) specified inside the 'clusterServiceVersions' section of -// an operator manifest. -type ClusterServiceVersion struct { - // Type metadata. - metav1.TypeMeta `json:",inline"` - - // Object metadata. - metav1.ObjectMeta `json:"metadata"` - - // Spec is the raw representation of the 'spec' element of - // ClusterServiceVersion object. Since we are - // not interested in the content of spec we are not parsing it. - Spec json.RawMessage `json:"spec"` -} - -// ReadCSVFromBundleDirectory tries to parse every YAML file in the directory and see if they are CSV. -// According to the strict one CSV rule for every bundle, we return the first file that is considered a CSV type. -func ReadCSVFromBundleDirectory(bundleDir string) (*ClusterServiceVersion, error) { - dirContent, err := ioutil.ReadDir(bundleDir) - if err != nil { - return nil, fmt.Errorf("error reading bundle directory %s, %v", bundleDir, err) - } - - files := []string{} - for _, f := range dirContent { - if !f.IsDir() { - files = append(files, f.Name()) - } - } - - for _, file := range files { - yamlReader, err := os.Open(path.Join(bundleDir, file)) - if err != nil { - continue - } - - unstructuredCSV := unstructured.Unstructured{} - csv := ClusterServiceVersion{} - - decoder := yaml.NewYAMLOrJSONDecoder(yamlReader, 30) - if err = decoder.Decode(&unstructuredCSV); err != nil { - continue - } - - if unstructuredCSV.GetKind() != operators.ClusterServiceVersionKind { - continue - } - - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredCSV.UnstructuredContent(), - &csv); err != nil { - return nil, err - } - - return &csv, nil - } - return nil, fmt.Errorf("no ClusterServiceVersion object found in %s", bundleDir) - -} - -// GetReplaces returns the name of the older ClusterServiceVersion object that -// is replaced by this ClusterServiceVersion object. -// -// If not defined, the function returns an empty string. -func (csv *ClusterServiceVersion) GetReplaces() (string, error) { - var objmap map[string]*json.RawMessage - if err := json.Unmarshal(csv.Spec, &objmap); err != nil { - return "", err - } - - rawValue, ok := objmap[replaces] - if !ok || rawValue == nil { - return "", nil - } - - var replaces string - if err := json.Unmarshal(*rawValue, &replaces); err != nil { - return "", err - } - - return replaces, nil -} - -// GetVersion returns the version of the CSV -// -// If not defined, the function returns an empty string. -func (csv *ClusterServiceVersion) GetVersion() (string, error) { - var objmap map[string]*json.RawMessage - if err := json.Unmarshal(csv.Spec, &objmap); err != nil { - return "", err - } - - rawValue, ok := objmap[version] - if !ok || rawValue == nil { - return "", nil - } - - var v string - if err := json.Unmarshal(*rawValue, &v); err != nil { - return "", err - } - - return v, nil -} - -// GetSkipRange returns the skiprange of the CSV -// -// If not defined, the function returns an empty string. -func (csv *ClusterServiceVersion) GetSkipRange() string { - skipRange, ok := csv.Annotations[skipRangeAnnotationKey] - if !ok { - return "" - } - return skipRange -} - -// GetSkips returns the name of the older ClusterServiceVersion objects that -// are skipped by this ClusterServiceVersion object. -// -// If not defined, the function returns an empty string. -func (csv *ClusterServiceVersion) GetSkips() ([]string, error) { - var objmap map[string]*json.RawMessage - if err := json.Unmarshal(csv.Spec, &objmap); err != nil { - return nil, err - } - - rawValue, ok := objmap[skips] - if !ok || rawValue == nil { - return nil, nil - } - - var skips []string - if err := json.Unmarshal(*rawValue, &skips); err != nil { - return nil, err - } - - return skips, nil -} - -// GetCustomResourceDefintions returns a list of owned and required -// CustomResourceDefinition object(s) specified inside the -// 'customresourcedefinitions' section of a ClusterServiceVersion 'spec'. -// -// owned represents the list of CRD(s) managed by this ClusterServiceVersion -// object. -// required represents the list of CRD(s) that this ClusterServiceVersion -// object depends on. -// -// If owned or required is not defined in the spec then an empty list is -// returned respectively. -func (csv *ClusterServiceVersion) GetCustomResourceDefintions() (owned []*DefinitionKey, required []*DefinitionKey, err error) { - var objmap map[string]*json.RawMessage - - if err = json.Unmarshal(csv.Spec, &objmap); err != nil { - return - } - - rawValue, ok := objmap[customResourceDefinitions] - if !ok || rawValue == nil { - return - } - - var definitions struct { - Owned []*DefinitionKey `json:"owned"` - Required []*DefinitionKey `json:"required"` - } - - if err = json.Unmarshal(*rawValue, &definitions); err != nil { - return - } - - owned = definitions.Owned - required = definitions.Required - return -} - -// GetApiServiceDefinitions returns a list of owned and required -// APISerivces specified inside the -// 'apiservicedefinitions' section of a ClusterServiceVersion 'spec'. -// -// owned represents the list of apiservices managed by this ClusterServiceVersion -// object. -// required represents the list of apiservices that this ClusterServiceVersion -// object depends on. -// -// If owned or required is not defined in the spec then an empty list is -// returned respectively. -func (csv *ClusterServiceVersion) GetApiServiceDefinitions() (owned []*DefinitionKey, required []*DefinitionKey, err error) { - var objmap map[string]*json.RawMessage - - if err = json.Unmarshal(csv.Spec, &objmap); err != nil { - return - } - - rawValue, ok := objmap[apiServiceDefinitions] - if !ok || rawValue == nil { - return - } - - var definitions struct { - Owned []*DefinitionKey `json:"owned"` - Required []*DefinitionKey `json:"required"` - } - - if err = json.Unmarshal(*rawValue, &definitions); err != nil { - return - } - - owned = definitions.Owned - required = definitions.Required - return -} - -// GetRelatedImage returns the list of associated images for the operator -func (csv *ClusterServiceVersion) GetRelatedImages() (imageSet map[string]struct{}, err error) { - var objmap map[string]*json.RawMessage - imageSet = make(map[string]struct{}) - - if err = json.Unmarshal(csv.Spec, &objmap); err != nil { - return - } - - rawValue, ok := objmap[relatedImages] - if !ok || rawValue == nil { - return - } - - type relatedImage struct { - Name string `json:"name"` - Ref string `json:"image"` - } - var relatedImages []relatedImage - if err = json.Unmarshal(*rawValue, &relatedImages); err != nil { - return - } - - for _, img := range relatedImages { - imageSet[img.Ref] = struct{}{} - } - - return -} - -// GetOperatorImages returns a list of any images used to run the operator. -// Currently this pulls any images in the pod specs of operator deployments. -func (csv *ClusterServiceVersion) GetOperatorImages() (map[string]struct{}, error) { - type dep struct { - Name string - Spec v1.DeploymentSpec - } - type strategySpec struct { - Deployments []dep - } - type strategy struct { - Name string `json:"strategy"` - Spec strategySpec `json:"spec"` - } - type csvSpec struct { - Install strategy - } - - var spec csvSpec - if err := json.Unmarshal(csv.Spec, &spec); err != nil { - return nil, err - } - - // this is the only install strategy we know about - if spec.Install.Name != "deployment" { - return nil, nil - } - - images := map[string]struct{}{} - for _, d := range spec.Install.Spec.Deployments { - for _, c := range d.Spec.Template.Spec.Containers { - images[c.Image] = struct{}{} - } - for _, c := range d.Spec.Template.Spec.InitContainers { - images[c.Image] = struct{}{} - } - } - - return images, nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/decode.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/decode.go deleted file mode 100644 index 4d418df76..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/decode.go +++ /dev/null @@ -1,43 +0,0 @@ -package registry - -import ( - "errors" - "fmt" - "io" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/util/yaml" -) - -// DecodeUnstructured decodes a raw stream into a an -// unstructured.Unstructured instance. -func DecodeUnstructured(reader io.Reader) (obj *unstructured.Unstructured, err error) { - decoder := yaml.NewYAMLOrJSONDecoder(reader, 30) - - t := &unstructured.Unstructured{} - if err = decoder.Decode(t); err != nil { - return - } - - obj = t - return -} - -// DecodePackageManifest decodes a raw stream into a a PackageManifest instance. -// If a package name is empty we consider the object invalid! -func DecodePackageManifest(reader io.Reader) (manifest *PackageManifest, err error) { - decoder := yaml.NewYAMLOrJSONDecoder(reader, 30) - - obj := &PackageManifest{} - if decodeErr := decoder.Decode(obj); decodeErr != nil { - err = fmt.Errorf("could not decode contents into package manifest - %v", decodeErr) - return - } - - if obj.PackageName == "" { - err = errors.New("name of package (packageName) is missing") - return - } - - manifest = obj - return -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/directoryGraphLoader.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/directoryGraphLoader.go deleted file mode 100644 index bd336f9f8..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/directoryGraphLoader.go +++ /dev/null @@ -1,226 +0,0 @@ -package registry - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" - "sort" - - "github.com/blang/semver" - "github.com/onsi/gomega/gstruct/errors" -) - -type DirGraphLoader struct { - PackageDir string - CsvNameAndReplaceMap map[string]csvReplaces - SortedCSVs csvs // only contains bundles with version field which will be considered for skip range. -} - -type csvReplaces struct { - replaces []string - skipRange semver.Range -} - -type csv struct { - name string - version semver.Version -} - -type csvs []csv - -func (c csvs) Len() int { return len(c) } -func (c csvs) Less(i, j int) bool { return c[i].version.LT(c[j].version) } -func (c csvs) Swap(i, j int) { c[i], c[j] = c[j], c[i] } - -// NewPackageGraphLoaderFromDir takes the root directory of the package in the file system. -func NewPackageGraphLoaderFromDir(packageDir string) (*DirGraphLoader, error) { - _, err := ioutil.ReadDir(packageDir) - if err != nil { - return nil, fmt.Errorf("error reading from %s directory, %v", packageDir, err) - } - - loader := DirGraphLoader{ - PackageDir: packageDir, - } - - return &loader, nil -} - -// Generate returns Package graph by parsing through package directory assuming all bundles in the package exist. -func (g *DirGraphLoader) Generate() (*Package, error) { - err := g.loadBundleCsvPathMap() - if err != nil { - return nil, fmt.Errorf("error geting CSVs from bundles in the package directory, %v", err) - } - - g.loadReplaces() - - pkg, err := g.parsePackageYAMLFile() - if err != nil { - return nil, fmt.Errorf("error parsing package.yaml file in the package root directory, %v", err) - } - - for chName, ch := range pkg.Channels { - pkg.Channels[chName] = Channel{ - Head: ch.Head, - Nodes: *g.getChannelNodes(ch.Head.CsvName), - } - } - return pkg, nil -} - -// loadBundleCsvPathMap loads the CsvNameAndReplaceMap and SortedCSVs in the Package Struct. -func (g *DirGraphLoader) loadBundleCsvPathMap() error { - bundleDirs, err := ioutil.ReadDir(g.PackageDir) - if err != nil { - return fmt.Errorf("error reading from %s directory, %v", g.PackageDir, err) - } - CsvNameAndReplaceMap := make(map[string]csvReplaces) - for _, bundlePath := range bundleDirs { - if bundlePath.IsDir() { - csvStruct, err := ReadCSVFromBundleDirectory(filepath.Join(g.PackageDir, bundlePath.Name())) - if err != nil { - return err - } - - // Best effort to get Skips, Replace, and SkipRange - srString := csvStruct.GetSkipRange() - sr, _ := semver.ParseRange(srString) - - var replaceStrings []string - rs, err := csvStruct.GetSkips() - if err == nil && rs != nil { - replaceStrings = rs - } - - r, err := csvStruct.GetReplaces() - if err == nil && r != "" { - replaceStrings = append(replaceStrings, r) - } - - CsvNameAndReplaceMap[csvStruct.GetName()] = csvReplaces{ - replaces: replaceStrings, - skipRange: sr, - } - - version, err := csvStruct.GetVersion() - if err == nil && version != "" { - v, err := semver.Parse(version) - if err == nil { - g.SortedCSVs = append(g.SortedCSVs, csv{name: csvStruct.GetName(), version: v}) - } - } - } - } - - g.CsvNameAndReplaceMap = CsvNameAndReplaceMap - sort.Sort(g.SortedCSVs) - return nil -} - -// loadReplaces converts skipRange to explicit csv name and write to replaces in CsvNameAndReplaceMap. -func (g *DirGraphLoader) loadReplaces() { - for csvName, replace := range g.CsvNameAndReplaceMap { - if replace.skipRange != nil { - for _, v := range g.SortedCSVs { - if replace.skipRange(v.version) { - g.CsvNameAndReplaceMap[csvName] = csvReplaces{ - replaces: append(g.CsvNameAndReplaceMap[csvName].replaces, v.name), - skipRange: g.CsvNameAndReplaceMap[csvName].skipRange, - } - } - } - } - } -} - -// getChannelNodes follows the head of the channel csv through all replaces to fill the nodes until the tail of the -// channel which will not replace anything. -func (g *DirGraphLoader) getChannelNodes(channelHeadCsv string) *map[BundleKey]map[BundleKey]struct{} { - nodes := make(map[BundleKey]map[BundleKey]struct{}) - remainingCSVsInChannel := make(map[BundleKey]struct{}) - - remainingCSVsInChannel[BundleKey{CsvName: channelHeadCsv}] = struct{}{} - for _, csv := range g.CsvNameAndReplaceMap[channelHeadCsv].replaces { - remainingCSVsInChannel[BundleKey{CsvName: csv}] = struct{}{} - } - - // Iterate through remainingCSVsInChannel and add replaces of each encountered CSVs if not already in nodes. - // Loop only exit after all remaining csvs are visited/deleted. - for len(remainingCSVsInChannel) > 0 { - for bk, _ := range remainingCSVsInChannel { - if _, ok := nodes[BundleKey{CsvName: bk.CsvName}]; !ok { - nodes[BundleKey{CsvName: bk.CsvName}] = func() map[BundleKey]struct{} { - subNode := make(map[BundleKey]struct{}) - for _, csv := range g.CsvNameAndReplaceMap[bk.CsvName].replaces { - subNode[BundleKey{CsvName: csv}] = struct{}{} - } - return subNode - }() - for _, csv := range g.CsvNameAndReplaceMap[bk.CsvName].replaces { - if _, ok := nodes[BundleKey{CsvName: csv}]; !ok { - remainingCSVsInChannel[BundleKey{CsvName: csv}] = struct{}{} - } - } - } - delete(remainingCSVsInChannel, bk) - } - } - return &nodes -} - -// parsePackageYAMLFile parses the *.package.yaml file and fills the information in Package including name, -// defaultchannel, and head of all Channels. It returns parsing error if any. -func (g *DirGraphLoader) parsePackageYAMLFile() (*Package, error) { - files, err := ioutil.ReadDir(g.PackageDir) - if err != nil { - return nil, fmt.Errorf("error reading bundle parent directory, %v", err) - } - - var ymlFiles []string - for _, f := range files { - if !f.IsDir() { - ymlFiles = append(ymlFiles, f.Name()) - } - } - - errs := errors.AggregateError{} - - for _, ymlFile := range ymlFiles { - ymlFile = path.Join(g.PackageDir, ymlFile) - ymlReader, err := os.Open(ymlFile) - if err != nil { - errs = append(errs, fmt.Errorf("error opening %s file, %v", ymlFile, err)) - continue - } - - pkgManifest, err := DecodePackageManifest(ymlReader) - if err != nil { - errs = append(errs, fmt.Errorf("error parsing %s as package.yaml file, %v", ymlFile, err)) - continue - } - return convertFromPackageManifest(*pkgManifest), nil - } - - return nil, fmt.Errorf("valid PackageManifest YAML file not found in %s, %s", g.PackageDir, errs.Error()) -} - -func convertFromPackageManifest(pkgManifest PackageManifest) *Package { - pkgChannels := make(map[string]Channel) - for _, channel := range pkgManifest.Channels { - pkgChannels[channel.Name] = Channel{ - Head: BundleKey{ - CsvName: channel.CurrentCSVName, - }, - } - } - - return &Package{ - Name: pkgManifest.PackageName, - DefaultChannel: pkgManifest.GetDefaultChannel(), - Channels: pkgChannels, - } - -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/empty.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/empty.go deleted file mode 100644 index a35bf3eb8..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/empty.go +++ /dev/null @@ -1,111 +0,0 @@ -package registry - -import ( - "context" - "errors" - - "github.com/operator-framework/operator-registry/pkg/api" -) - -// EmptyQuery acts as a "zero value" implementation of the Query interface. -// -// EmptyQuery can be used as a substitute for any operation dependent on Query. -type EmptyQuery struct{} - -func (EmptyQuery) ListTables(ctx context.Context) ([]string, error) { - return nil, errors.New("empty querier: cannot list tables") -} - -func (EmptyQuery) ListPackages(ctx context.Context) ([]string, error) { - return nil, errors.New("empty querier: cannot list packages") -} - -func (EmptyQuery) GetPackage(ctx context.Context, name string) (*PackageManifest, error) { - return nil, errors.New("empty querier: cannot get package") -} - -func (EmptyQuery) GetDefaultPackage(ctx context.Context, name string) (string, error) { - return "", errors.New("empty querier: cannot get default package") -} - -func (EmptyQuery) GetChannelEntriesFromPackage(ctx context.Context, packageName string) ([]ChannelEntryAnnotated, error) { - return nil, errors.New("empty querier: cannot get all channel entries for package") -} - -func (EmptyQuery) GetBundle(ctx context.Context, pkgName, channelName, csvName string) (*api.Bundle, error) { - return nil, errors.New("empty querier: cannot get bundle") -} - -func (EmptyQuery) GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (*api.Bundle, error) { - return nil, errors.New("empty querier: cannot get bundle for channel") -} - -func (EmptyQuery) GetChannelEntriesThatReplace(ctx context.Context, name string) (entries []*ChannelEntry, err error) { - return nil, errors.New("empty querier: cannot get channel entries that replace") -} - -func (EmptyQuery) GetBundleThatReplaces(ctx context.Context, name, pkgName, channelName string) (*api.Bundle, error) { - return nil, errors.New("empty querier: cannot get bundle that replaces") -} - -func (EmptyQuery) GetChannelEntriesThatProvide(ctx context.Context, group, version, kind string) (entries []*ChannelEntry, err error) { - return nil, errors.New("empty querier: cannot get channel entries that provide") -} - -func (EmptyQuery) GetLatestChannelEntriesThatProvide(ctx context.Context, group, version, kind string) (entries []*ChannelEntry, err error) { - return nil, errors.New("empty querier: cannot get latest channel entries that provide") -} - -func (EmptyQuery) GetBundleThatProvides(ctx context.Context, group, version, kind string) (*api.Bundle, error) { - return nil, errors.New("empty querier: cannot get bundle that provides") -} - -func (EmptyQuery) ListImages(ctx context.Context) ([]string, error) { - return nil, errors.New("empty querier: cannot get image list") -} - -func (EmptyQuery) GetImagesForBundle(ctx context.Context, bundleName string) ([]string, error) { - return nil, errors.New("empty querier: cannot get image list") -} - -func (EmptyQuery) GetApisForEntry(ctx context.Context, entryId int64) (provided []*api.GroupVersionKind, required []*api.GroupVersionKind, err error) { - return nil, nil, errors.New("empty querier: cannot apis") -} - -func (EmptyQuery) GetBundleVersion(ctx context.Context, image string) (string, error) { - return "", errors.New("empty querier: cannot get version") -} - -func (EmptyQuery) GetBundlePathsForPackage(ctx context.Context, pkgName string) ([]string, error) { - return nil, errors.New("empty querier: cannot get images") -} - -func (EmptyQuery) GetBundlesForPackage(ctx context.Context, pkgName string) (map[BundleKey]struct{}, error) { - return nil, errors.New("empty querier: cannot get bundles") -} - -func (EmptyQuery) GetDefaultChannelForPackage(ctx context.Context, pkgName string) (string, error) { - return "", errors.New("empty querier: cannot get default channel") -} - -func (EmptyQuery) ListChannels(ctx context.Context, pkgName string) ([]string, error) { - return nil, errors.New("empty querier: cannot list channels") -} - -func (EmptyQuery) GetCurrentCSVNameForChannel(ctx context.Context, pkgName, channel string) (string, error) { - return "", errors.New("empty querier: cannot get csv name for package and channel") -} - -func (EmptyQuery) ListBundles(ctx context.Context) ([]*api.Bundle, error) { - return nil, errors.New("empty querier: cannot list bundles") -} - -func (EmptyQuery) GetDependenciesForBundle(ctx context.Context, name, version, path string) (dependencies []*api.Dependency, err error) { - return nil, errors.New("empty querier: cannot get dependencies for bundle") -} - -var _ Query = &EmptyQuery{} - -func NewEmptyQuerier() *EmptyQuery { - return &EmptyQuery{} -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/graph.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/graph.go deleted file mode 100644 index f62a30ab4..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/graph.go +++ /dev/null @@ -1,51 +0,0 @@ -package registry - -import ( - "fmt" -) - -type Package struct { - Name string - DefaultChannel string - Channels map[string]Channel -} - -type Channel struct { - Head BundleKey - Nodes map[BundleKey]map[BundleKey]struct{} -} - -type BundleKey struct { - BundlePath string - Version string //semver string - CsvName string -} - -func (b *BundleKey) IsEmpty() bool { - return b.BundlePath == "" && b.Version == "" && b.CsvName == "" -} - -func (b *BundleKey) String() string { - return fmt.Sprintf("%s %s %s", b.CsvName, b.Version, b.BundlePath) -} - -func (p *Package) HasChannel(channel string) bool { - if p.Channels == nil { - return false - } - - _, found := p.Channels[channel] - return found -} - -func (p *Package) HasCsv(csv string) bool { - for _, channelGraph := range p.Channels { - for node := range channelGraph.Nodes { - if node.CsvName == csv { - return true - } - } - } - - return false -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/imageinput.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/imageinput.go deleted file mode 100644 index 49f231ca0..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/imageinput.go +++ /dev/null @@ -1,125 +0,0 @@ -package registry - -import ( - "fmt" - "io/ioutil" - "path/filepath" - "strings" - - "github.com/sirupsen/logrus" - - "github.com/operator-framework/operator-registry/pkg/image" -) - -type ImageInput struct { - manifestsDir string - metadataDir string - to image.Reference - from string - annotationsFile *AnnotationsFile - dependenciesFile *DependenciesFile - bundle *Bundle -} - -func NewImageInput(to image.Reference, from string) (*ImageInput, error) { - var annotationsFound, dependenciesFound bool - path := from - manifests := filepath.Join(path, "manifests") - metadata := filepath.Join(path, "metadata") - // Get annotations file - log := logrus.WithFields(logrus.Fields{"dir": from, "file": metadata, "load": "annotations"}) - files, err := ioutil.ReadDir(metadata) - if err != nil { - return nil, fmt.Errorf("unable to read directory %s: %s", metadata, err) - } - - // Look for the metadata and manifests sub-directories to find the annotations.yaml - // file that will inform how the manifests of the bundle should be loaded into the database. - // If dependencies.yaml which contains operator dependencies in metadata directory - // exists, parse and load it into the DB - annotationsFile := &AnnotationsFile{} - dependenciesFile := &DependenciesFile{} - for _, f := range files { - if !annotationsFound { - err = DecodeFile(filepath.Join(metadata, f.Name()), annotationsFile) - if err == nil && *annotationsFile != (AnnotationsFile{}) { - annotationsFound = true - continue - } - } - - if !dependenciesFound { - err = parseDependenciesFile(filepath.Join(metadata, f.Name()), dependenciesFile) - if err == nil && len(dependenciesFile.Dependencies) > 0 { - dependenciesFound = true - } - } - } - - if !annotationsFound { - return nil, fmt.Errorf("Could not find annotations file") - } - - if !dependenciesFound { - log.Info("Could not find dependencies file") - } - - imageInput := &ImageInput{ - manifestsDir: manifests, - metadataDir: metadata, - to: to, - from: from, - annotationsFile: annotationsFile, - dependenciesFile: dependenciesFile, - } - - err = imageInput.getBundleFromManifests() - if err != nil { - return nil, err - } - - return imageInput, nil -} - -func (i *ImageInput) getBundleFromManifests() error { - log := logrus.WithFields(logrus.Fields{"dir": i.from, "file": i.manifestsDir, "load": "bundle"}) - - csv, err := i.findCSV(i.manifestsDir) - if err != nil { - return err - } - - if csv.Object == nil { - return fmt.Errorf("csv is empty: %s", err) - } - - log.Info("found csv, loading bundle") - - csvName := csv.GetName() - - bundle, err := loadBundle(csvName, i.manifestsDir) - if err != nil { - return fmt.Errorf("error loading objs in directory: %s", err) - } - - if bundle == nil || bundle.Size() == 0 { - return fmt.Errorf("no bundle objects found") - } - - // set the bundleimage on the bundle - bundle.BundleImage = i.to.String() - // set the dependencies on the bundle - bundle.Dependencies = i.dependenciesFile.GetDependencies() - - bundle.Name = csvName - bundle.Package = i.annotationsFile.Annotations.PackageName - bundle.Channels = strings.Split(i.annotationsFile.Annotations.Channels, ",") - - if err := bundle.AllProvidedAPIsInBundle(); err != nil { - return fmt.Errorf("error checking provided apis in bundle %s: %s", bundle.Name, err) - } - - i.bundle = bundle - - return nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/interface.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/interface.go deleted file mode 100644 index 3df0713cd..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/interface.go +++ /dev/null @@ -1,70 +0,0 @@ -package registry - -import ( - "context" - - "github.com/operator-framework/operator-registry/pkg/api" -) - -type Load interface { - AddOperatorBundle(bundle *Bundle) error - AddBundleSemver(graph *Package, bundle *Bundle) error - AddPackageChannels(manifest PackageManifest) error - AddBundlePackageChannels(manifest PackageManifest, bundle *Bundle) error - RemovePackage(packageName string) error - ClearNonHeadBundles() error -} - -type Query interface { - ListTables(ctx context.Context) ([]string, error) - ListPackages(ctx context.Context) ([]string, error) - GetPackage(ctx context.Context, name string) (*PackageManifest, error) - GetDefaultPackage(ctx context.Context, name string) (string, error) - GetChannelEntriesFromPackage(ctx context.Context, packageName string) ([]ChannelEntryAnnotated, error) - GetBundle(ctx context.Context, pkgName, channelName, csvName string) (*api.Bundle, error) - GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (*api.Bundle, error) - // Get all channel entries that say they replace this one - GetChannelEntriesThatReplace(ctx context.Context, name string) (entries []*ChannelEntry, err error) - // Get the bundle in a package/channel that replace this one - GetBundleThatReplaces(ctx context.Context, name, pkgName, channelName string) (*api.Bundle, error) - // Get all channel entries that provide an api - GetChannelEntriesThatProvide(ctx context.Context, group, version, kind string) (entries []*ChannelEntry, err error) - // Get latest channel entries that provide an api - GetLatestChannelEntriesThatProvide(ctx context.Context, group, version, kind string) (entries []*ChannelEntry, err error) - // Get the the latest bundle that provides the API in a default channel - GetBundleThatProvides(ctx context.Context, group, version, kind string) (*api.Bundle, error) - // List all images in the database - ListImages(ctx context.Context) ([]string, error) - // List all images for a particular bundle - GetImagesForBundle(ctx context.Context, bundleName string) ([]string, error) - // Get Provided and Required APIs for a particular bundle - GetApisForEntry(ctx context.Context, entryID int64) (provided []*api.GroupVersionKind, required []*api.GroupVersionKind, err error) - // Get Version of a Bundle Image - GetBundleVersion(ctx context.Context, image string) (string, error) - // List Images for Package - GetBundlePathsForPackage(ctx context.Context, pkgName string) ([]string, error) - // List Bundles for Package - GetBundlesForPackage(ctx context.Context, pkgName string) (map[BundleKey]struct{}, error) - // Get DefaultChannel for Package - GetDefaultChannelForPackage(ctx context.Context, pkgName string) (string, error) - // List channels for package - ListChannels(ctx context.Context, pkgName string) ([]string, error) - // Get CurrentCSV name for channel and package - GetCurrentCSVNameForChannel(ctx context.Context, pkgName, channel string) (string, error) - // List all available bundles in the database - ListBundles(ctx context.Context) (bundles []*api.Bundle, err error) - // Get the list of dependencies for a bundle - GetDependenciesForBundle(ctx context.Context, name, version, path string) (dependencies []*api.Dependency, err error) -} - -// GraphLoader generates a graph -// GraphLoader supports multiple different loading schemes -// GraphLoader from SQL, GraphLoader from old format (filesystem), GraphLoader from SQL + input bundles -type GraphLoader interface { - Generate(packageName string) (*Package, error) -} - -// RegistryPopulator populates a registry. -type RegistryPopulator interface { - Populate() error -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/populator.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/populator.go deleted file mode 100644 index b9b2655e9..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/populator.go +++ /dev/null @@ -1,405 +0,0 @@ -package registry - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/sirupsen/logrus" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/yaml" - - "github.com/operator-framework/operator-registry/pkg/image" -) - -type Dependencies struct { - RawMessage []map[string]string `json:"dependencies" yaml:"dependencies"` -} - -// DirectoryPopulator loads an unpacked operator bundle from a directory into the database. -type DirectoryPopulator struct { - loader Load - graphLoader GraphLoader - querier Query - imageDirMap map[image.Reference]string -} - -func NewDirectoryPopulator(loader Load, graphLoader GraphLoader, querier Query, imageDirMap map[image.Reference]string) *DirectoryPopulator { - return &DirectoryPopulator{ - loader: loader, - graphLoader: graphLoader, - querier: querier, - imageDirMap: imageDirMap, - } -} - -func (i *DirectoryPopulator) Populate(mode Mode) error { - var errs []error - imagesToAdd := make([]*ImageInput, 0) - for to, from := range i.imageDirMap { - imageInput, err := NewImageInput(to, from) - if err != nil { - errs = append(errs, err) - continue - } - - imagesToAdd = append(imagesToAdd, imageInput) - } - - if len(errs) > 0 { - return utilerrors.NewAggregate(errs) - } - - err := i.loadManifests(imagesToAdd, mode) - if err != nil { - return err - } - - return nil -} - -func (i *DirectoryPopulator) loadManifests(imagesToAdd []*ImageInput, mode Mode) error { - switch mode { - case ReplacesMode: - // TODO: This is relatively inefficient. Ideally, we should be able to use a replaces - // graph loader to construct what the graph would look like with a set of new bundles - // and use that to return an error if it's not valid, rather than insert one at a time - // and reinspect the database. - // - // Additionally, it would be preferrable if there was a single database transaction - // that took the updated graph as a whole as input, rather than inserting bundles of the - // same package linearly. - var err error - var validImagesToAdd []*ImageInput - for len(imagesToAdd) > 0 { - validImagesToAdd, imagesToAdd, err = i.getNextReplacesImagesToAdd(imagesToAdd) - if err != nil { - return err - } - for _, image := range validImagesToAdd { - err := i.loadManifestsReplaces(image.bundle, image.annotationsFile) - if err != nil { - return err - } - } - } - case SemVerMode: - for _, image := range imagesToAdd { - err := i.loadManifestsSemver(image.bundle, image.annotationsFile, false) - if err != nil { - return err - } - } - case SkipPatchMode: - for _, image := range imagesToAdd { - err := i.loadManifestsSemver(image.bundle, image.annotationsFile, true) - if err != nil { - return err - } - } - default: - err := fmt.Errorf("Unsupported update mode") - if err != nil { - return err - } - } - - // Finally let's delete all the old bundles - if err := i.loader.ClearNonHeadBundles(); err != nil { - return fmt.Errorf("Error deleting previous bundles: %s", err) - } - - return nil -} - -func (i *DirectoryPopulator) loadManifestsReplaces(bundle *Bundle, annotationsFile *AnnotationsFile) error { - channels, err := i.querier.ListChannels(context.TODO(), annotationsFile.GetName()) - existingPackageChannels := map[string]string{} - for _, c := range channels { - current, err := i.querier.GetCurrentCSVNameForChannel(context.TODO(), annotationsFile.GetName(), c) - if err != nil { - return err - } - existingPackageChannels[c] = current - } - - bcsv, err := bundle.ClusterServiceVersion() - if err != nil { - return fmt.Errorf("error getting csv from bundle %s: %s", bundle.Name, err) - } - - packageManifest, err := translateAnnotationsIntoPackage(annotationsFile, bcsv, existingPackageChannels) - if err != nil { - return fmt.Errorf("Could not translate annotations file into packageManifest %s", err) - } - - if err := i.loadOperatorBundle(packageManifest, bundle); err != nil { - return fmt.Errorf("Error adding package %s", err) - } - - return nil -} - -func (i *DirectoryPopulator) getNextReplacesImagesToAdd(imagesToAdd []*ImageInput) ([]*ImageInput, []*ImageInput, error) { - remainingImages := make([]*ImageInput, 0) - foundImages := make([]*ImageInput, 0) - - var errs []error - - // Separate these image sets per package, since multiple different packages have - // separate graph - imagesPerPackage := make(map[string][]*ImageInput, 0) - for _, image := range imagesToAdd { - pkg := image.bundle.Package - if _, ok := imagesPerPackage[pkg]; !ok { - newPkgImages := make([]*ImageInput, 0) - newPkgImages = append(newPkgImages, image) - imagesPerPackage[pkg] = newPkgImages - } else { - imagesPerPackage[pkg] = append(imagesPerPackage[pkg], image) - } - } - - for pkg, pkgImages := range imagesPerPackage { - // keep a tally of valid and invalid images to ensure at least one - // image per package is valid. If not, throw an error - pkgRemainingImages := 0 - pkgFoundImages := 0 - - // first, try to pull the existing package graph from the database if it exists - graph, err := i.graphLoader.Generate(pkg) - if err != nil && !errors.Is(err, ErrPackageNotInDatabase) { - return nil, nil, err - } - - var pkgErrs []error - // then check each image to see if it can be a replacement - replacesLoader := ReplacesGraphLoader{} - for _, pkgImage := range pkgImages { - canAdd, err := replacesLoader.CanAdd(pkgImage.bundle, graph) - if err != nil { - pkgErrs = append(pkgErrs, err) - } - if canAdd { - pkgFoundImages++ - foundImages = append(foundImages, pkgImage) - } else { - pkgRemainingImages++ - remainingImages = append(remainingImages, pkgImage) - } - } - - // no new images can be added, the current iteration aggregates all the - // errors that describe invalid bundles - if pkgFoundImages == 0 && pkgRemainingImages > 0 { - errs = append(errs, utilerrors.NewAggregate(pkgErrs)) - } - } - - if len(errs) > 0 { - return nil, nil, utilerrors.NewAggregate(errs) - } - - return foundImages, remainingImages, nil -} - -func (i *DirectoryPopulator) loadManifestsSemver(bundle *Bundle, annotations *AnnotationsFile, skippatch bool) error { - graph, err := i.graphLoader.Generate(bundle.Package) - if err != nil && !errors.Is(err, ErrPackageNotInDatabase) { - return err - } - - // add to the graph - bundleLoader := BundleGraphLoader{} - updatedGraph, err := bundleLoader.AddBundleToGraph(bundle, graph, annotations.Annotations.DefaultChannelName, skippatch) - if err != nil { - return err - } - - if err := i.loader.AddBundleSemver(updatedGraph, bundle); err != nil { - return fmt.Errorf("error loading bundle into db: %s", err) - } - - return nil -} - -// loadBundle takes the directory that a CSV is in and assumes the rest of the objects in that directory -// are part of the bundle. -func loadBundle(csvName string, dir string) (*Bundle, error) { - log := logrus.WithFields(logrus.Fields{"dir": dir, "load": "bundle"}) - files, err := ioutil.ReadDir(dir) - if err != nil { - return nil, err - } - - bundle := &Bundle{ - Name: csvName, - } - for _, f := range files { - log = log.WithField("file", f.Name()) - if f.IsDir() { - log.Info("skipping directory") - continue - } - - if strings.HasPrefix(f.Name(), ".") { - log.Info("skipping hidden file") - continue - } - - log.Info("loading bundle file") - var ( - obj = &unstructured.Unstructured{} - path = filepath.Join(dir, f.Name()) - ) - if err = DecodeFile(path, obj); err != nil { - log.WithError(err).Debugf("could not decode file contents for %s", path) - continue - } - - // Don't include other CSVs in the bundle - if obj.GetKind() == "ClusterServiceVersion" && obj.GetName() != csvName { - continue - } - - if obj.Object != nil { - bundle.Add(obj) - } - } - - return bundle, nil -} - -// findCSV looks through the bundle directory to find a csv -func (i *ImageInput) findCSV(manifests string) (*unstructured.Unstructured, error) { - log := logrus.WithFields(logrus.Fields{"dir": i.from, "find": "csv"}) - - files, err := ioutil.ReadDir(manifests) - if err != nil { - return nil, fmt.Errorf("unable to read directory %s: %s", manifests, err) - } - - for _, f := range files { - log = log.WithField("file", f.Name()) - if f.IsDir() { - log.Info("skipping directory") - continue - } - - if strings.HasPrefix(f.Name(), ".") { - log.Info("skipping hidden file") - continue - } - - var ( - obj = &unstructured.Unstructured{} - path = filepath.Join(manifests, f.Name()) - ) - if err = DecodeFile(path, obj); err != nil { - log.WithError(err).Debugf("could not decode file contents for %s", path) - continue - } - - if obj.GetKind() != clusterServiceVersionKind { - continue - } - - return obj, nil - } - - return nil, fmt.Errorf("no csv found in bundle") -} - -// loadOperatorBundle adds the package information to the loader's store -func (i *DirectoryPopulator) loadOperatorBundle(manifest PackageManifest, bundle *Bundle) error { - if manifest.PackageName == "" { - return nil - } - - if err := i.loader.AddBundlePackageChannels(manifest, bundle); err != nil { - return fmt.Errorf("error loading bundle into db: %s", err) - } - - return nil -} - -// translateAnnotationsIntoPackage attempts to translate the channels.yaml file at the given path into a package.yaml -func translateAnnotationsIntoPackage(annotations *AnnotationsFile, csv *ClusterServiceVersion, existingPackageChannels map[string]string) (PackageManifest, error) { - manifest := PackageManifest{} - - for _, ch := range annotations.GetChannels() { - existingPackageChannels[ch] = csv.GetName() - } - - channels := []PackageChannel{} - for c, current := range existingPackageChannels { - channels = append(channels, - PackageChannel{ - Name: c, - CurrentCSVName: current, - }) - } - - manifest = PackageManifest{ - PackageName: annotations.GetName(), - DefaultChannelName: annotations.GetDefaultChannelName(), - Channels: channels, - } - - return manifest, nil -} - -// DecodeFile decodes the file at a path into the given interface. -func DecodeFile(path string, into interface{}) error { - if into == nil { - panic("programmer error: decode destination must be instantiated before decode") - } - - fileReader, err := os.Open(path) - if err != nil { - return fmt.Errorf("unable to read file %s: %s", path, err) - } - defer fileReader.Close() - - decoder := yaml.NewYAMLOrJSONDecoder(fileReader, 30) - - return decoder.Decode(into) -} - -func parseDependenciesFile(path string, depFile *DependenciesFile) error { - deps := Dependencies{} - err := DecodeFile(path, &deps) - if err != nil || len(deps.RawMessage) == 0 { - return fmt.Errorf("Unable to decode the dependencies file %s", path) - } - depList := []Dependency{} - for _, v := range deps.RawMessage { - // convert map to json - jsonStr, _ := json.Marshal(v) - - // Check dependency type - dep := Dependency{} - err := json.Unmarshal(jsonStr, &dep) - if err != nil { - return err - } - - switch dep.GetType() { - case GVKType, PackageType: - dep.Value = string(jsonStr) - default: - return fmt.Errorf("Unsupported dependency type %s", dep.GetType()) - } - depList = append(depList, dep) - } - - depFile.Dependencies = depList - - return nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/replacesgraphloader.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/replacesgraphloader.go deleted file mode 100644 index a57df6e13..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/replacesgraphloader.go +++ /dev/null @@ -1,40 +0,0 @@ -package registry - -import ( - "fmt" - - utilerrors "k8s.io/apimachinery/pkg/util/errors" -) - -type ReplacesGraphLoader struct { -} - -// CanAdd checks that a new bundle can be added in replaces mode (i.e. the replaces -// defined for the bundle already exists) -func (r *ReplacesGraphLoader) CanAdd(bundle *Bundle, graph *Package) (bool, error) { - replaces, err := bundle.Replaces() - if err != nil { - return false, fmt.Errorf("Invalid content, unable to parse bundle") - } - - csvName := bundle.Name - - // adding the first bundle in the graph - if replaces == "" { - return true, nil - } - - var errs []error - - // check that the bundle can be added - if !graph.HasCsv(replaces) { - err := fmt.Errorf("Invalid bundle %s, bundle specifies a non-existent replacement %s", csvName, replaces) - errs = append(errs, err) - } - - if len(errs) > 0 { - return false, utilerrors.NewAggregate(errs) - } - - return true, nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/types.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/types.go deleted file mode 100644 index 5672b2a03..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/types.go +++ /dev/null @@ -1,270 +0,0 @@ -package registry - -import ( - "encoding/json" - "errors" - "fmt" - "strings" - - "github.com/blang/semver" -) - -var ( - // ErrPackageNotInDatabase is an error that describes a package not found error when querying the registry - ErrPackageNotInDatabase = errors.New("Package not in database") -) - -const ( - GVKType = "olm.gvk" - PackageType = "olm.package" -) - -// APIKey stores GroupVersionKind for use as map keys -type APIKey struct { - Group string - Version string - Kind string - Plural string -} - -func (k APIKey) String() string { - return fmt.Sprintf("%s/%s/%s (%s)", k.Group, k.Version, k.Kind, k.Plural) -} - -// DefinitionKey represents the metadata for either an APIservice or a CRD from a CSV spec -type DefinitionKey struct { - Group string `json:"group"` - Kind string `json:"kind"` - Name string `json:"name"` - Version string `json:"version"` -} - -// PackageManifest holds information about a package, which is a reference to one (or more) -// channels under a single package. -type PackageManifest struct { - // PackageName is the name of the overall package, ala `etcd`. - PackageName string `json:"packageName" yaml:"packageName"` - - // Channels are the declared channels for the package, ala `stable` or `alpha`. - Channels []PackageChannel `json:"channels" yaml:"channels"` - - // DefaultChannelName is, if specified, the name of the default channel for the package. The - // default channel will be installed if no other channel is explicitly given. If the package - // has a single channel, then that channel is implicitly the default. - DefaultChannelName string `json:"defaultChannel" yaml:"defaultChannel"` -} - -// GetDefaultChannel gets the default channel or returns the only one if there's only one. returns empty string if it -// can't determine the default -func (m PackageManifest) GetDefaultChannel() string { - if m.DefaultChannelName != "" { - return m.DefaultChannelName - } - if len(m.Channels) == 1 { - return m.Channels[0].Name - } - return "" -} - -// PackageChannel defines a single channel under a package, pointing to a version of that -// package. -type PackageChannel struct { - // Name is the name of the channel, e.g. `alpha` or `stable` - Name string `json:"name" yaml:"name"` - - // CurrentCSVName defines a reference to the CSV holding the version of this package currently - // for the channel. - CurrentCSVName string `json:"currentCSV" yaml:"currentCSV"` -} - -// IsDefaultChannel returns true if the PackageChennel is the default for the PackageManifest -func (pc PackageChannel) IsDefaultChannel(pm PackageManifest) bool { - return pc.Name == pm.DefaultChannelName || len(pm.Channels) == 1 -} - -// ChannelEntry is a denormalized node in a channel graph -type ChannelEntry struct { - PackageName string - ChannelName string - BundleName string - Replaces string -} - -// ChannelEntryAnnotated is a denormalized node in a channel graph annotated with additional entry level info -type ChannelEntryAnnotated struct { - PackageName string - ChannelName string - BundleName string - BundlePath string - Version string - Replaces string - ReplacesVersion string - ReplacesBundlePath string -} - -// AnnotationsFile holds annotation information about a bundle -type AnnotationsFile struct { - // annotations is a list of annotations for a given bundle - Annotations Annotations `json:"annotations" yaml:"annotations"` -} - -// Annotations is a list of annotations for a given bundle -type Annotations struct { - // PackageName is the name of the overall package, ala `etcd`. - PackageName string `json:"operators.operatorframework.io.bundle.package.v1" yaml:"operators.operatorframework.io.bundle.package.v1"` - - // Channels are a comma separated list of the declared channels for the bundle, ala `stable` or `alpha`. - Channels string `json:"operators.operatorframework.io.bundle.channels.v1" yaml:"operators.operatorframework.io.bundle.channels.v1"` - - // DefaultChannelName is, if specified, the name of the default channel for the package. The - // default channel will be installed if no other channel is explicitly given. If the package - // has a single channel, then that channel is implicitly the default. - DefaultChannelName string `json:"operators.operatorframework.io.bundle.channel.default.v1" yaml:"operators.operatorframework.io.bundle.channel.default.v1"` -} - -// DependenciesFile holds dependency information about a bundle -type DependenciesFile struct { - // Dependencies is a list of dependencies for a given bundle - Dependencies []Dependency `json:"dependencies" yaml:"dependencies"` -} - -// Dependencies is a list of dependencies for a given bundle -type Dependency struct { - // The type of dependency. It can be `olm.package` for operator-version based - // dependency or `olm.gvk` for gvk based dependency. This field is required. - Type string `json:"type" yaml:"type"` - - // The value of the dependency (either GVKDependency or PackageDependency) - Value string `json:"value" yaml:"value"` -} - -type GVKDependency struct { - // The group of GVK based dependency - Group string `json:"group" yaml:"group"` - - // The kind of GVK based dependency - Kind string `json:"kind" yaml:"kind"` - - // The version of dependency in semver format - Version string `json:"version" yaml:"version"` -} - -type PackageDependency struct { - // The name of dependency such as 'etcd' - PackageName string `json:"packageName" yaml:"packageName"` - - // The version of dependency in semver format - Version string `json:"version" yaml:"version"` -} - -// Validate will validate GVK dependency type and return error(s) -func (gd *GVKDependency) Validate() []error { - errs := []error{} - if gd.Group == "" { - errs = append(errs, fmt.Errorf("API Group is empty")) - } - if gd.Version == "" { - errs = append(errs, fmt.Errorf("API Version is empty")) - } - if gd.Kind == "" { - errs = append(errs, fmt.Errorf("API Kind is empty")) - } - return errs -} - -// Validate will validate package dependency type and return error(s) -func (pd *PackageDependency) Validate() []error { - errs := []error{} - if pd.PackageName == "" { - errs = append(errs, fmt.Errorf("Package name is empty")) - } - if pd.Version == "" { - errs = append(errs, fmt.Errorf("Package version is empty")) - } else { - _, err := semver.Parse(pd.Version) - if err != nil { - _, err := semver.ParseRange(pd.Version) - if err != nil { - errs = append(errs, fmt.Errorf("Invalid semver format version")) - } - } - } - return errs -} - -// GetDependencies returns the list of dependency -func (d *DependenciesFile) GetDependencies() []*Dependency { - var dependencies []*Dependency - for _, item := range d.Dependencies { - dependencies = append(dependencies, &item) - } - return dependencies -} - -// GetType returns the type of dependency -func (e *Dependency) GetType() string { - if e.Type != "" { - return e.Type - } - return "" -} - -// GetTypeValue returns the dependency object that is converted -// from value string -func (e *Dependency) GetTypeValue() interface{} { - if e.Type != "" { - switch e.GetType() { - case GVKType: - dep := GVKDependency{} - err := json.Unmarshal([]byte(e.GetValue()), &dep) - if err != nil { - return nil - } - return dep - case PackageType: - dep := PackageDependency{} - err := json.Unmarshal([]byte(e.GetValue()), &dep) - if err != nil { - return nil - } - return dep - } - } - return nil -} - -// GetValue returns the value content of dependency -func (e *Dependency) GetValue() string { - if e.Value != "" { - return e.Value - } - return "" -} - -// GetName returns the package name of the bundle -func (a *AnnotationsFile) GetName() string { - if a.Annotations.PackageName != "" { - return a.Annotations.PackageName - } - return "" -} - -// GetChannels returns the channels that this bundle should be added to -func (a *AnnotationsFile) GetChannels() []string { - if a.Annotations.Channels != "" { - return strings.Split(a.Annotations.Channels, ",") - } - return []string{} -} - -// GetDefaultChannelName returns the name of the default channel -func (a *AnnotationsFile) GetDefaultChannelName() string { - if a.Annotations.DefaultChannelName != "" { - return a.Annotations.DefaultChannelName - } - channels := a.GetChannels() - if len(channels) == 1 { - return channels[0] - } - return "" -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/configmap.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/configmap.go deleted file mode 100644 index 687902b98..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/configmap.go +++ /dev/null @@ -1,187 +0,0 @@ -package sqlite - -import ( - "encoding/json" - "fmt" - "strings" - - "github.com/ghodss/yaml" - "github.com/sirupsen/logrus" - "k8s.io/api/core/v1" - "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - - "github.com/operator-framework/operator-registry/pkg/registry" -) - -const ( - ConfigMapCRDName = "customResourceDefinitions" - ConfigMapCSVName = "clusterServiceVersions" - ConfigMapPackageName = "packages" -) - -// ConfigMapLoader loads a configmap of resources into the database -// entries under "customResourceDefinitions" will be parsed as CRDs -// entries under "clusterServiceVersions" will be parsed as CSVs -// entries under "packages" will be parsed as Packages -type ConfigMapLoader struct { - log *logrus.Entry - store registry.Load - configMapData map[string]string - crds map[registry.APIKey]*unstructured.Unstructured -} - -var _ SQLPopulator = &ConfigMapLoader{} - -// NewSQLLoaderForConfigMapData is useful when the operator manifest(s) -// originate from a different source than a configMap. For example, operator -// manifest(s) can be downloaded from a remote registry like quay.io. -func NewSQLLoaderForConfigMapData(logger *logrus.Entry, store registry.Load, configMapData map[string]string) *ConfigMapLoader { - return &ConfigMapLoader{ - log: logger, - store: store, - configMapData: configMapData, - crds: map[registry.APIKey]*unstructured.Unstructured{}, - } -} - -func NewSQLLoaderForConfigMap(store registry.Load, configMap v1.ConfigMap) *ConfigMapLoader { - logger := logrus.WithFields(logrus.Fields{"configmap": configMap.GetName(), "ns": configMap.GetNamespace()}) - return &ConfigMapLoader{ - log: logger, - store: store, - configMapData: configMap.Data, - crds: map[registry.APIKey]*unstructured.Unstructured{}, - } -} - -func (c *ConfigMapLoader) Populate() error { - c.log.Info("loading CRDs") - - // first load CRDs into memory; these will be added to the bundle that owns them - crdListYaml, ok := c.configMapData[ConfigMapCRDName] - if !ok { - return fmt.Errorf("couldn't find expected key %s in configmap", ConfigMapCRDName) - } - - crdListJson, err := yaml.YAMLToJSON([]byte(crdListYaml)) - if err != nil { - c.log.WithError(err).Debug("error loading CRD list") - return err - } - - var parsedCRDList []v1beta1.CustomResourceDefinition - if err := json.Unmarshal(crdListJson, &parsedCRDList); err != nil { - c.log.WithError(err).Debug("error parsing CRD list") - return err - } - - var errs []error - for _, crd := range parsedCRDList { - if crd.Spec.Versions == nil && crd.Spec.Version != "" { - crd.Spec.Versions = []v1beta1.CustomResourceDefinitionVersion{{Name: crd.Spec.Version, Served: true, Storage: true}} - } - for _, version := range crd.Spec.Versions { - gvk := registry.APIKey{Group: crd.Spec.Group, Version: version.Name, Kind: crd.Spec.Names.Kind, Plural: crd.Spec.Names.Plural} - c.log.WithField("gvk", gvk).Debug("loading CRD") - if _, ok := c.crds[gvk]; ok { - c.log.WithField("gvk", gvk).Debug("crd added twice") - errs = append(errs, fmt.Errorf("can't add the same CRD twice in one configmap: %v", gvk)) - continue - } - crdUnst, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&crd) - if err != nil { - errs = append(errs, fmt.Errorf("error marshaling crd: %s", err)) - continue - } - c.crds[gvk] = &unstructured.Unstructured{Object: crdUnst} - } - } - - c.log.Info("loading Bundles") - csvListYaml, ok := c.configMapData[ConfigMapCSVName] - if !ok { - errs = append(errs, fmt.Errorf("couldn't find expected key %s in configmap", ConfigMapCSVName)) - return utilerrors.NewAggregate(errs) - } - csvListJson, err := yaml.YAMLToJSON([]byte(csvListYaml)) - if err != nil { - errs = append(errs, fmt.Errorf("error loading CSV list: %s", err)) - return utilerrors.NewAggregate(errs) - } - - var parsedCSVList []registry.ClusterServiceVersion - err = json.Unmarshal(csvListJson, &parsedCSVList) - if err != nil { - errs = append(errs, fmt.Errorf("error parsing CSV list: %s", err)) - return utilerrors.NewAggregate(errs) - } - - for _, csv := range parsedCSVList { - c.log.WithField("csv", csv.GetName()).Debug("loading CSV") - csvUnst, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&csv) - if err != nil { - errs = append(errs, fmt.Errorf("error marshaling csv: %s", err)) - continue - } - - bundle := registry.NewBundle(csv.GetName(), "", nil, &unstructured.Unstructured{Object: csvUnst}) - ownedCRDs, _, err := csv.GetCustomResourceDefintions() - if err != nil { - errs = append(errs, err) - continue - } - for _, owned := range ownedCRDs { - split := strings.SplitN(owned.Name, ".", 2) - if len(split) < 2 { - c.log.WithError(err).Debug("error parsing owned name") - errs = append(errs, fmt.Errorf("error parsing owned name: %s", err)) - continue - } - - gvk := registry.APIKey{Group: split[1], Version: owned.Version, Kind: owned.Kind, Plural: split[0]} - crdUnst, ok := c.crds[gvk] - if !ok { - errs = append(errs, fmt.Errorf("couldn't find owned CRD in crd list %v: %s", gvk, err)) - continue - } - - bundle.Add(crdUnst) - } - - if err := c.store.AddOperatorBundle(bundle); err != nil { - version, _ := bundle.Version() - errs = append(errs, fmt.Errorf("error adding operator bundle %s/%s/%s: %s", csv.GetName(), version, bundle.BundleImage, err)) - } - } - - c.log.Info("loading Packages") - packageListYaml, ok := c.configMapData[ConfigMapPackageName] - if !ok { - errs = append(errs, fmt.Errorf("couldn't find expected key %s in configmap", ConfigMapPackageName)) - return utilerrors.NewAggregate(errs) - } - - packageListJson, err := yaml.YAMLToJSON([]byte(packageListYaml)) - if err != nil { - errs = append(errs, fmt.Errorf("error loading package list: %s", err)) - return utilerrors.NewAggregate(errs) - } - - var parsedPackageManifests []registry.PackageManifest - err = json.Unmarshal(packageListJson, &parsedPackageManifests) - if err != nil { - errs = append(errs, fmt.Errorf("error parsing package list: %s", err)) - return utilerrors.NewAggregate(errs) - } - for _, packageManifest := range parsedPackageManifests { - c.log.WithField("package", packageManifest.PackageName).Debug("loading package") - if err := c.store.AddPackageChannels(packageManifest); err != nil { - errs = append(errs, fmt.Errorf("error loading package %s: %s", packageManifest.PackageName, err)) - } - } - - return utilerrors.NewAggregate(errs) -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/db_options.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/db_options.go deleted file mode 100644 index 889f550e0..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/db_options.go +++ /dev/null @@ -1,24 +0,0 @@ -package sqlite - -import ( - "database/sql" -) - -type DbOptions struct { - // MigratorBuilder is a function that returns a migrator instance - MigratorBuilder func(*sql.DB) (Migrator, error) -} - -type DbOption func(*DbOptions) - -func defaultDBOptions() *DbOptions { - return &DbOptions{ - MigratorBuilder: NewSQLLiteMigrator, - } -} - -func WithMigratorBuilder(m func(loader *sql.DB) (Migrator, error)) DbOption { - return func(o *DbOptions) { - o.MigratorBuilder = m - } -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/directory.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/directory.go deleted file mode 100644 index c79f66f93..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/directory.go +++ /dev/null @@ -1,229 +0,0 @@ -package sqlite - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/sirupsen/logrus" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/yaml" - - "github.com/operator-framework/operator-registry/pkg/registry" -) - -const ClusterServiceVersionKind = "ClusterServiceVersion" - -type SQLPopulator interface { - Populate() error -} - -// DirectoryLoader loads a directory of resources into the database -type DirectoryLoader struct { - store registry.Load - directory string -} - -var _ SQLPopulator = &DirectoryLoader{} - -func NewSQLLoaderForDirectory(store registry.Load, directory string) *DirectoryLoader { - return &DirectoryLoader{ - store: store, - directory: directory, - } -} - -func (d *DirectoryLoader) Populate() error { - log := logrus.WithField("dir", d.directory) - - log.Info("loading Bundles") - errs := make([]error, 0) - if err := filepath.Walk(d.directory, collectWalkErrs(d.LoadBundleWalkFunc, &errs)); err != nil { - errs = append(errs, err) - } - - log.Info("loading Packages and Entries") - if err := filepath.Walk(d.directory, collectWalkErrs(d.LoadPackagesWalkFunc, &errs)); err != nil { - errs = append(errs, err) - } - - return utilerrors.NewAggregate(errs) -} - -// collectWalkErrs calls the given walk func and appends any non-nil, non skip dir error returned to the given errors slice. -func collectWalkErrs(walk filepath.WalkFunc, errs *[]error) filepath.WalkFunc { - return func(path string, f os.FileInfo, err error) (walkErr error) { - if walkErr = walk(path, f, err); walkErr != nil && walkErr != filepath.SkipDir { - *errs = append(*errs, walkErr) - return nil - } - - return walkErr - } -} - -// LoadBundleWalkFunc walks the directory. When it sees a `.clusterserviceversion.yaml` file, it -// attempts to load the surrounding files in the same directory as a bundle, and stores them in the -// db for querying -func (d *DirectoryLoader) LoadBundleWalkFunc(path string, f os.FileInfo, err error) error { - if f == nil { - return fmt.Errorf("invalid file: %v", f) - } - - log := logrus.WithFields(logrus.Fields{"dir": d.directory, "file": f.Name(), "load": "bundles"}) - if f.IsDir() { - if strings.HasPrefix(f.Name(), ".") { - log.Info("skipping hidden directory") - return filepath.SkipDir - } - log.Info("directory") - return nil - } - - if strings.HasPrefix(f.Name(), ".") { - log.Info("skipping hidden file") - return nil - } - - fileReader, err := os.Open(path) - if err != nil { - return fmt.Errorf("unable to load file %s: %s", path, err) - } - - decoder := yaml.NewYAMLOrJSONDecoder(fileReader, 30) - csv := unstructured.Unstructured{} - - if err = decoder.Decode(&csv); err != nil { - return nil - } - - if csv.GetKind() != ClusterServiceVersionKind { - return nil - } - - log.Info("found csv, loading bundle") - - var errs []error - bundle, err := loadBundle(csv.GetName(), filepath.Dir(path)) - if err != nil { - errs = append(errs, fmt.Errorf("error loading objs in directory: %s", err)) - } - - if bundle == nil || bundle.Size() == 0 { - errs = append(errs, fmt.Errorf("no bundle objects found")) - return utilerrors.NewAggregate(errs) - } - - if err := bundle.AllProvidedAPIsInBundle(); err != nil { - errs = append(errs, fmt.Errorf("error checking provided apis in bundle %s: %s", bundle.Name, err)) - } - - if err := d.store.AddOperatorBundle(bundle); err != nil { - version, _ := bundle.Version() - errs = append(errs, fmt.Errorf("error adding operator bundle %s/%s/%s: %s", csv.GetName(), version, bundle.BundleImage, err)) - } - - return utilerrors.NewAggregate(errs) -} - -// LoadPackagesWalkFunc attempts to unmarshal the file at the given path into a PackageManifest resource. -// If unmarshaling is successful, the PackageManifest is added to the loader's store. -func (d *DirectoryLoader) LoadPackagesWalkFunc(path string, f os.FileInfo, err error) error { - if f == nil { - return fmt.Errorf("invalid file: %v", f) - } - - log := logrus.WithFields(logrus.Fields{"dir": d.directory, "file": f.Name(), "load": "package"}) - if f.IsDir() { - if strings.HasPrefix(f.Name(), ".") { - log.Info("skipping hidden directory") - return filepath.SkipDir - } - log.Info("directory") - return nil - } - - if strings.HasPrefix(f.Name(), ".") { - log.Info("skipping hidden file") - return nil - } - - fileReader, err := os.Open(path) - if err != nil { - return fmt.Errorf("unable to load package from file %s: %s", path, err) - } - - decoder := yaml.NewYAMLOrJSONDecoder(fileReader, 30) - manifest := registry.PackageManifest{} - if err = decoder.Decode(&manifest); err != nil { - if err != nil { - return fmt.Errorf("could not decode contents of file %s into package: %s", path, err) - } - - } - if manifest.PackageName == "" { - return nil - } - - if err := d.store.AddPackageChannels(manifest); err != nil { - return fmt.Errorf("error loading package into db: %s", err) - } - - return nil -} - -// loadBundle takes the directory that a CSV is in and assumes the rest of the objects in that directory -// are part of the bundle. -func loadBundle(csvName string, dir string) (*registry.Bundle, error) { - log := logrus.WithFields(logrus.Fields{"dir": dir, "load": "bundle", "name": csvName}) - files, err := ioutil.ReadDir(dir) - if err != nil { - return nil, err - } - - var errs []error - bundle := ®istry.Bundle{ - Name: csvName, - } - for _, f := range files { - log = log.WithField("file", f.Name()) - if f.IsDir() { - log.Info("skipping directory") - continue - } - - if strings.HasPrefix(f.Name(), ".") { - log.Info("skipping hidden file") - continue - } - - log.Info("loading bundle file") - path := filepath.Join(dir, f.Name()) - fileReader, err := os.Open(path) - if err != nil { - errs = append(errs, fmt.Errorf("unable to load file %s: %s", path, err)) - continue - } - - decoder := yaml.NewYAMLOrJSONDecoder(fileReader, 30) - obj := &unstructured.Unstructured{} - if err = decoder.Decode(obj); err != nil { - logrus.WithError(err).Debugf("could not decode file contents for %s", path) - continue - } - - // Don't include other CSVs in the bundle - if obj.GetKind() == "ClusterServiceVersion" && obj.GetName() != csvName { - continue - } - - if obj.Object != nil { - bundle.Add(obj) - } - } - - return bundle, utilerrors.NewAggregate(errs) -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/graphloader.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/graphloader.go deleted file mode 100644 index e5795550f..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/graphloader.go +++ /dev/null @@ -1,138 +0,0 @@ -package sqlite - -import ( - "context" - "database/sql" - "fmt" - - "github.com/operator-framework/operator-registry/pkg/registry" -) - -type SQLGraphLoader struct { - Querier registry.Query -} - -func NewSQLGraphLoader(dbFilename string) (*SQLGraphLoader, error) { - querier, err := NewSQLLiteQuerier(dbFilename) - if err != nil { - return nil, err - } - - return &SQLGraphLoader{ - Querier: querier, - }, nil -} - -func NewSQLGraphLoaderFromDB(db *sql.DB) (*SQLGraphLoader, error) { - return &SQLGraphLoader{ - Querier: NewSQLLiteQuerierFromDb(db), - }, nil -} - -func (g *SQLGraphLoader) Generate(packageName string) (*registry.Package, error) { - graph := ®istry.Package{ - Name: packageName, - Channels: make(map[string]registry.Channel, 0), - } - - ctx := context.TODO() - defaultChannel, err := g.Querier.GetDefaultPackage(ctx, packageName) - if err != nil { - return graph, registry.ErrPackageNotInDatabase - } - graph.DefaultChannel = defaultChannel - - channelEntries, err := g.Querier.GetChannelEntriesFromPackage(ctx, packageName) - if err != nil { - return graph, err - } - - existingBundles, err := g.Querier.GetBundlesForPackage(ctx, packageName) - if err != nil { - return graph, err - } - - channels, err := graphFromEntries(channelEntries, existingBundles) - if err != nil { - return graph, err - } - graph.Channels = channels - - return graph, nil -} - -// graphFromEntries builds the graph from a set of channel entries -func graphFromEntries(channelEntries []registry.ChannelEntryAnnotated, existingBundles map[registry.BundleKey]struct{}) (map[string]registry.Channel, error) { - channels := map[string]registry.Channel{} - - type replaces map[registry.BundleKey]map[registry.BundleKey]struct{} - - channelGraph := map[string]replaces{} - channelHeadCandidates := map[string]map[registry.BundleKey]struct{}{} - - // add all channels and nodes to the graph - for _, entry := range channelEntries { - // create channel if we haven't seen it yet - if _, ok := channelGraph[entry.ChannelName]; !ok { - channelGraph[entry.ChannelName] = replaces{} - } - - key := registry.BundleKey{ - BundlePath: entry.BundlePath, - Version: entry.Version, - CsvName: entry.BundleName, - } - - // skip synthetic channelentries that aren't pointers to actual bundles - if _, ok := existingBundles[key]; !ok { - continue - } - - channelGraph[entry.ChannelName][key] = map[registry.BundleKey]struct{}{} - - // every bundle in a channel is a potential head of that channel - if _, ok := channelHeadCandidates[entry.ChannelName]; !ok { - channelHeadCandidates[entry.ChannelName] = map[registry.BundleKey]struct{}{key: {}} - } else { - channelHeadCandidates[entry.ChannelName][key] = struct{}{} - } - } - - for _, entry := range channelEntries { - key := registry.BundleKey{ - BundlePath: entry.BundlePath, - Version: entry.Version, - CsvName: entry.BundleName, - } - replacesKey := registry.BundleKey{ - BundlePath: entry.ReplacesBundlePath, - Version: entry.ReplacesVersion, - CsvName: entry.Replaces, - } - - if !replacesKey.IsEmpty() { - channelGraph[entry.ChannelName][key][replacesKey] = struct{}{} - } - - delete(channelHeadCandidates[entry.ChannelName], replacesKey) - } - - for channelName, candidates := range channelHeadCandidates { - if len(candidates) == 0 { - return nil, fmt.Errorf("no channel head found for %s", channelName) - } - if len(candidates) > 1 { - return nil, fmt.Errorf("multiple candidate channel heads found for %s: %v", channelName, candidates) - } - - for head := range candidates { - channel := registry.Channel{ - Head: head, - Nodes: channelGraph[channelName], - } - channels[channelName] = channel - } - } - - return channels, nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/load.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/load.go deleted file mode 100644 index 6c881a116..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/load.go +++ /dev/null @@ -1,719 +0,0 @@ -package sqlite - -import ( - "context" - "database/sql" - "encoding/json" - "fmt" - "strings" - - _ "github.com/mattn/go-sqlite3" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - - "github.com/operator-framework/operator-registry/pkg/registry" -) - -type SQLLoader struct { - db *sql.DB - migrator Migrator -} - -var _ registry.Load = &SQLLoader{} - -func NewSQLLiteLoader(db *sql.DB, opts ...DbOption) (*SQLLoader, error) { - options := defaultDBOptions() - for _, o := range opts { - o(options) - } - - if _, err := db.Exec("PRAGMA foreign_keys = ON", nil); err != nil { - return nil, err - } - - migrator, err := options.MigratorBuilder(db) - if err != nil { - return nil, err - } - - return &SQLLoader{db: db, migrator: migrator}, nil -} - -func (s *SQLLoader) Migrate(ctx context.Context) error { - if s.migrator == nil { - return fmt.Errorf("no migrator configured") - } - return s.migrator.Migrate(ctx) -} - -func (s *SQLLoader) AddOperatorBundle(bundle *registry.Bundle) error { - tx, err := s.db.Begin() - if err != nil { - return err - } - defer func() { - tx.Rollback() - }() - - if err := s.addOperatorBundle(tx, bundle); err != nil { - return err - } - - return tx.Commit() -} - -func (s *SQLLoader) addOperatorBundle(tx *sql.Tx, bundle *registry.Bundle) error { - addBundle, err := tx.Prepare("insert into operatorbundle(name, csv, bundle, bundlepath, version, skiprange, replaces, skips) values(?, ?, ?, ?, ?, ?, ?, ?)") - if err != nil { - return err - } - defer addBundle.Close() - - addImage, err := tx.Prepare("insert into related_image(image, operatorbundle_name) values(?,?)") - if err != nil { - return err - } - defer addImage.Close() - - csvName, bundleImage, csvBytes, bundleBytes, err := bundle.Serialize() - if err != nil { - return err - } - - if csvName == "" { - return fmt.Errorf("csv name not found") - } - - version, err := bundle.Version() - if err != nil { - return err - } - skiprange, err := bundle.SkipRange() - if err != nil { - return err - } - replaces, err := bundle.Replaces() - if err != nil { - return err - } - skips, err := bundle.Skips() - if err != nil { - return err - } - - if _, err := addBundle.Exec(csvName, csvBytes, bundleBytes, bundleImage, version, skiprange, replaces, strings.Join(skips, ",")); err != nil { - return err - } - - imgs, err := bundle.Images() - if err != nil { - return err - } - for img := range imgs { - if _, err := addImage.Exec(img, csvName); err != nil { - return err - } - } - - // Add dependencies information - err = s.addDependencies(tx, bundle) - if err != nil { - return err - } - - return s.addAPIs(tx, bundle) -} - -func (s *SQLLoader) AddPackageChannelsFromGraph(graph *registry.Package) error { - tx, err := s.db.Begin() - if err != nil { - return err - } - defer func() { - tx.Rollback() - }() - - var errs []error - - if err := addPackageIfNotExists(tx, graph.Name); err != nil { - errs = append(errs, err) - } - - for name, channel := range graph.Channels { - if err := addOrUpdateChannel(tx, name, graph.Name, channel.Head.CsvName); err != nil { - errs = append(errs, err) - continue - } - } - - if err := updateDefaultChannel(tx, graph.DefaultChannel, graph.Name); err != nil { - errs = append(errs, err) - } - - // update each channel's graph - for channelName, channel := range graph.Channels { - currentNode := channel.Head - depth := 1 - - var previousNodeID int64 - - // first clear the current channel graph - err := truncChannelGraph(tx, channelName, graph.Name) - if err != nil { - errs = append(errs, err) - break - } - - // iterate into the replacement chain of the channel to insert or update all entries - for { - // create real channel entry for node - id, err := addChannelEntry(tx, channelName, graph.Name, currentNode.CsvName, depth) - if err != nil { - errs = append(errs, err) - break - } - - // If the previous node was created, use the entryId of the current node to update - // the replaces for the previous node - if previousNodeID != 0 { - err := addReplaces(tx, id, previousNodeID) - if err != nil { - errs = append(errs, err) - } - } - - syntheticReplaces := make([]registry.BundleKey, 0) // for CSV skips - nextNode := registry.BundleKey{} - - currentNodeReplaces := channel.Nodes[currentNode] - - // Iterate over all replaces for the node in the graph - // It should only contain one real replacement, so let's find it and - // follow the chain. For the rest, they are fake entries and should be - // generated as synthetic replacements - for replace := range currentNodeReplaces { - if _, ok := channel.Nodes[replace]; !ok { - syntheticReplaces = append(syntheticReplaces, replace) - } else { - nextNode = replace - } - } - - // create synthetic channel entries for nodes - // also create channel entry to replace that node - syntheticDepth := depth + 1 - for _, synthetic := range syntheticReplaces { - syntheticReplacesID, err := addChannelEntry(tx, channelName, graph.Name, synthetic.CsvName, syntheticDepth) - if err != nil { - errs = append(errs, err) - break - } - - syntheticNodeID, err := addChannelEntry(tx, channelName, graph.Name, currentNode.CsvName, syntheticDepth) - if err != nil { - errs = append(errs, err) - break - } - - err = addReplaces(tx, syntheticReplacesID, syntheticNodeID) - if err != nil { - errs = append(errs, err) - } - syntheticDepth++ - } - - // we got to the end of the channel graph - if nextNode.IsEmpty() { - if len(channel.Nodes) != depth { - err := fmt.Errorf("Invalid graph: some (non-bottom) nodes defined in the graph were not mentioned as replacements of any node") - errs = append(errs, err) - } - break - } - - // increase depth and continue - currentNode = nextNode - previousNodeID = id - depth++ - } - } - - if err := tx.Commit(); err != nil { - errs = append(errs, err) - } - - return utilerrors.NewAggregate(errs) -} - -func (s *SQLLoader) AddPackageChannels(manifest registry.PackageManifest) error { - tx, err := s.db.Begin() - if err != nil { - return err - } - defer func() { - tx.Rollback() - }() - - if err := s.addPackageChannels(tx, manifest); err != nil { - return err - } - - return tx.Commit() -} - -func (s *SQLLoader) addPackageChannels(tx *sql.Tx, manifest registry.PackageManifest) error { - addPackage, err := tx.Prepare("insert into package(name) values(?)") - if err != nil { - return err - } - defer addPackage.Close() - - addDefaultChannel, err := tx.Prepare("update package set default_channel = ? where name = ?") - if err != nil { - return err - } - defer addDefaultChannel.Close() - - addChannel, err := tx.Prepare("insert into channel(name, package_name, head_operatorbundle_name) values(?, ?, ?)") - if err != nil { - return err - } - defer addChannel.Close() - - addChannelEntry, err := tx.Prepare("insert into channel_entry(channel_name, package_name, operatorbundle_name, depth) values(?, ?, ?, ?)") - if err != nil { - return err - } - defer addChannelEntry.Close() - - addReplaces, err := tx.Prepare("update channel_entry set replaces = ? where entry_id = ?") - if err != nil { - return err - } - defer addReplaces.Close() - - getReplaces, err := tx.Prepare(` - SELECT DISTINCT operatorbundle.csv - FROM operatorbundle - WHERE operatorbundle.name=? LIMIT 1`) - defer getReplaces.Close() - - var errs []error - - if _, err := addPackage.Exec(manifest.PackageName); err != nil { - errs = append(errs, err) - return utilerrors.NewAggregate(errs) - } - - hasDefault := false - for _, c := range manifest.Channels { - if _, err := addChannel.Exec(c.Name, manifest.PackageName, c.CurrentCSVName); err != nil { - errs = append(errs, err) - continue - } - if c.IsDefaultChannel(manifest) { - hasDefault = true - if _, err := addDefaultChannel.Exec(c.Name, manifest.PackageName); err != nil { - errs = append(errs, err) - continue - } - } - } - if !hasDefault { - errs = append(errs, fmt.Errorf("no default channel specified for %s", manifest.PackageName)) - } - - for _, c := range manifest.Channels { - res, err := addChannelEntry.Exec(c.Name, manifest.PackageName, c.CurrentCSVName, 0) - if err != nil { - errs = append(errs, err) - continue - } - currentID, err := res.LastInsertId() - if err != nil { - errs = append(errs, err) - continue - } - - channelEntryCSVName := c.CurrentCSVName - depth := 1 - - // Since this loop depends on following 'replaces', keep track of where it's been - replaceCycle := map[string]bool{channelEntryCSVName: true} - for { - // Get CSV for current entry - replaces, skips, err := s.getBundleSkipsReplaces(tx, channelEntryCSVName) - if err != nil { - errs = append(errs, err) - break - } - - for _, skip := range skips { - // add dummy channel entry for the skipped version - skippedChannelEntry, err := addChannelEntry.Exec(c.Name, manifest.PackageName, skip, depth) - if err != nil { - errs = append(errs, err) - continue - } - - skippedID, err := skippedChannelEntry.LastInsertId() - if err != nil { - errs = append(errs, err) - continue - } - - // add another channel entry for the parent, which replaces the skipped - synthesizedChannelEntry, err := addChannelEntry.Exec(c.Name, manifest.PackageName, channelEntryCSVName, depth) - if err != nil { - errs = append(errs, err) - continue - } - - synthesizedID, err := synthesizedChannelEntry.LastInsertId() - if err != nil { - errs = append(errs, err) - continue - } - - if _, err = addReplaces.Exec(skippedID, synthesizedID); err != nil { - errs = append(errs, err) - continue - } - - depth++ - } - - // create real replacement chain - if replaces == "" { - // we've walked the channel until there was no replacement - break - } - - replacedChannelEntry, err := addChannelEntry.Exec(c.Name, manifest.PackageName, replaces, depth) - if err != nil { - errs = append(errs, err) - break - } - - // If we find 'replaces' in the circuit list then we've seen it already, break out - if _, ok := replaceCycle[replaces]; ok { - errs = append(errs, fmt.Errorf("Cycle detected, %s replaces %s", channelEntryCSVName, replaces)) - break - } - replaceCycle[replaces] = true - - replacedID, err := replacedChannelEntry.LastInsertId() - if err != nil { - errs = append(errs, err) - break - } - if _, err = addReplaces.Exec(replacedID, currentID); err != nil { - errs = append(errs, err) - break - } - if _, _, err := s.getBundleSkipsReplaces(tx, replaces); err != nil { - errs = append(errs, fmt.Errorf("%s specifies replacement that couldn't be found", c.CurrentCSVName)) - break - } - - currentID = replacedID - channelEntryCSVName = replaces - depth++ - } - } - return utilerrors.NewAggregate(errs) -} - -func (s *SQLLoader) ClearNonHeadBundles() error { - tx, err := s.db.Begin() - if err != nil { - return err - } - defer func() { - tx.Rollback() - }() - - removeNonHeadBundles, err := tx.Prepare(` - update operatorbundle set bundle = null, csv = null - where (bundlepath != null or bundlepath != "") - and name not in ( - select operatorbundle.name from operatorbundle - join channel on channel.head_operatorbundle_name = operatorbundle.name - ) - `) - if err != nil { - return err - } - defer removeNonHeadBundles.Close() - - _, err = removeNonHeadBundles.Exec() - if err != nil { - return err - } - return tx.Commit() -} - -func (s *SQLLoader) getBundleSkipsReplaces(tx *sql.Tx, bundleName string) (replaces string, skips []string, err error) { - getReplacesAndSkips, err := tx.Prepare(` - SELECT replaces, skips - FROM operatorbundle - WHERE operatorbundle.name=? LIMIT 1`) - if err != nil { - return - } - defer getReplacesAndSkips.Close() - - rows, rerr := getReplacesAndSkips.Query(bundleName) - if err != nil { - err = rerr - return - } - if !rows.Next() { - err = fmt.Errorf("no bundle found for bundlename %s", bundleName) - return - } - - var replacesStringSQL sql.NullString - var skipsStringSql sql.NullString - if err = rows.Scan(&replacesStringSQL, &skipsStringSql); err != nil { - return - } - - if replacesStringSQL.Valid { - replaces = replacesStringSQL.String - } - if skipsStringSql.Valid && len(skipsStringSql.String) > 0 { - skips = strings.Split(skipsStringSql.String, ",") - } - - return -} - -func (s *SQLLoader) addAPIs(tx *sql.Tx, bundle *registry.Bundle) error { - if bundle.Name == "" { - return fmt.Errorf("cannot add apis for bundle with no name: %#v", bundle) - } - addAPI, err := tx.Prepare("insert or ignore into api(group_name, version, kind, plural) values(?, ?, ?, ?)") - if err != nil { - return err - } - defer addAPI.Close() - - addAPIProvider, err := tx.Prepare("insert into api_provider(group_name, version, kind, operatorbundle_name, operatorbundle_version, operatorbundle_path) values(?, ?, ?, ?, ?, ?)") - if err != nil { - return err - } - defer addAPIProvider.Close() - - addAPIRequirer, err := tx.Prepare("insert into api_requirer(group_name, version, kind, operatorbundle_name, operatorbundle_version, operatorbundle_path) values(?, ?, ?, ?, ?, ?)") - if err != nil { - return err - } - defer addAPIRequirer.Close() - - providedApis, err := bundle.ProvidedAPIs() - if err != nil { - return err - } - requiredApis, err := bundle.RequiredAPIs() - if err != nil { - return err - } - bundleVersion, err := bundle.Version() - if err != nil { - return err - } - - sqlString := func(s string) sql.NullString { - return sql.NullString{String: s, Valid: s != ""} - } - for api := range providedApis { - if _, err := addAPI.Exec(api.Group, api.Version, api.Kind, api.Plural); err != nil { - return err - } - - if _, err := addAPIProvider.Exec(api.Group, api.Version, api.Kind, bundle.Name, sqlString(bundleVersion), sqlString(bundle.BundleImage)); err != nil { - return err - } - } - for api := range requiredApis { - if _, err := addAPI.Exec(api.Group, api.Version, api.Kind, api.Plural); err != nil { - return err - } - - if _, err := addAPIRequirer.Exec(api.Group, api.Version, api.Kind, bundle.Name, sqlString(bundleVersion), sqlString(bundle.BundleImage)); err != nil { - return err - } - } - - return nil -} - -func (s *SQLLoader) getCSVNames(tx *sql.Tx, packageName string) ([]string, error) { - getID, err := tx.Prepare(` - SELECT DISTINCT channel_entry.operatorbundle_name - FROM channel_entry - WHERE channel_entry.package_name=?`) - - if err != nil { - return nil, err - } - defer getID.Close() - - rows, err := getID.Query(packageName) - if err != nil { - return nil, err - } - - var csvName string - csvNames := []string{} - for rows.Next() { - err := rows.Scan(&csvName) - if err != nil { - return nil, err - } - csvNames = append(csvNames, csvName) - } - - if err := rows.Close(); err != nil { - return nil, err - } - - return csvNames, nil -} - -func (s *SQLLoader) RemovePackage(packageName string) error { - tx, err := s.db.Begin() - if err != nil { - return err - } - defer func() { - tx.Rollback() - }() - - csvNames, err := s.getCSVNames(tx, packageName) - if err != nil { - return err - } - for _, csvName := range csvNames { - err = s.rmBundle(tx, csvName) - if err != nil { - return err - } - } - - return tx.Commit() -} - -func (s *SQLLoader) rmBundle(tx *sql.Tx, csvName string) error { - stmt, err := tx.Prepare("DELETE FROM operatorbundle WHERE operatorbundle.name=?") - if err != nil { - return err - } - defer stmt.Close() - - if _, err := stmt.Exec(csvName); err != nil { - return err - } - - return nil -} - -func (s *SQLLoader) AddBundleSemver(graph *registry.Package, bundle *registry.Bundle) error { - err := s.AddOperatorBundle(bundle) - if err != nil { - return err - } - - err = s.AddPackageChannelsFromGraph(graph) - if err != nil { - return err - } - - return nil -} - -func (s *SQLLoader) AddBundlePackageChannels(manifest registry.PackageManifest, bundle *registry.Bundle) error { - tx, err := s.db.Begin() - if err != nil { - return err - } - defer func() { - tx.Rollback() - }() - - if err := s.addOperatorBundle(tx, bundle); err != nil { - return err - } - - // Delete package and channels (entries will cascade) - they will be recalculated - deletePkg, err := tx.Prepare("delete from package where name = ?") - if err != nil { - return err - } - defer deletePkg.Close() - _, err = deletePkg.Exec(manifest.PackageName) - if err != nil { - return err - } - deleteChan, err := tx.Prepare("delete from channel where package_name = ?") - if err != nil { - return err - } - defer deleteChan.Close() - _, err = deleteChan.Exec(manifest.PackageName) - if err != nil { - return err - } - - if err := s.addPackageChannels(tx, manifest); err != nil { - return err - } - - return tx.Commit() -} - -func (s *SQLLoader) addDependencies(tx *sql.Tx, bundle *registry.Bundle) error { - addDep, err := tx.Prepare("insert into dependencies(type, value, operatorbundle_name, operatorbundle_version, operatorbundle_path) values(?, ?, ?, ?, ?)") - if err != nil { - return err - } - defer addDep.Close() - - bundleVersion, err := bundle.Version() - if err != nil { - return err - } - - sqlString := func(s string) sql.NullString { - return sql.NullString{String: s, Valid: s != ""} - } - for _, dep := range bundle.Dependencies { - if _, err := addDep.Exec(dep.Type, dep.Value, bundle.Name, sqlString(bundleVersion), sqlString(bundle.BundleImage)); err != nil { - return err - } - } - - // Look up requiredAPIs in CSV and add them in dependencies table - requiredApis, err := bundle.RequiredAPIs() - if err != nil { - return err - } - - for api := range requiredApis { - valueMap := map[string]string{ - "type": registry.GVKType, - "group": api.Group, - "version": api.Version, - "kind": api.Kind, - } - value, err := json.Marshal(valueMap) - if err != nil { - return err - } - if _, err := addDep.Exec(registry.GVKType, value, bundle.Name, sqlString(bundleVersion), sqlString(bundle.BundleImage)); err != nil { - return err - } - } - - return nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/loadprocs.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/loadprocs.go deleted file mode 100644 index f24e917b0..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/loadprocs.go +++ /dev/null @@ -1,146 +0,0 @@ -package sqlite - -import ( - "database/sql" -) - -// TODO: Finish separating procedures from loader layer: make this a type to make -// unit tests more granular? -func addChannelEntry(tx *sql.Tx, channelName, packageName, csvName string, depth int) (int64, error) { - addChannelEntry, err := tx.Prepare("insert into channel_entry(channel_name, package_name, operatorbundle_name, depth) values(?, ?, ?, ?)") - if err != nil { - return 0, err - } - defer addChannelEntry.Close() - - res, err := addChannelEntry.Exec(channelName, packageName, csvName, depth) - if err != nil { - return 0, err - } - currentID, err := res.LastInsertId() - if err != nil { - return 0, err - } - - return currentID, err -} - -func addReplaces(tx *sql.Tx, replacesID, entryID int64) error { - addReplaces, err := tx.Prepare("update channel_entry set replaces = ? where entry_id = ?") - if err != nil { - return err - } - defer addReplaces.Close() - - _, err = addReplaces.Exec(replacesID, entryID) - if err != nil { - return err - } - - return nil -} - -func addPackage(tx *sql.Tx, packageName string) error { - addPackage, err := tx.Prepare("insert into package(name) values(?)") - if err != nil { - return err - } - defer addPackage.Close() - - _, err = addPackage.Exec(packageName) - if err != nil { - return err - } - - return nil -} - -func addPackageIfNotExists(tx *sql.Tx, packageName string) error { - addPackage, err := tx.Prepare("insert or replace into package(name) values(?)") - if err != nil { - return err - } - defer addPackage.Close() - - _, err = addPackage.Exec(packageName) - if err != nil { - return err - } - - return nil -} - -func addChannel(tx *sql.Tx, channelName, packageName, headCsvName string) error { - addChannel, err := tx.Prepare("insert into channel(name, package_name, head_operatorbundle_name) values(?, ?, ?)") - if err != nil { - return err - } - defer addChannel.Close() - - _, err = addChannel.Exec(channelName, packageName, headCsvName) - if err != nil { - return err - } - - return nil -} - -func updateChannel(tx *sql.Tx, channelName, packageName, headCsvName string) error { - updateChannel, err := tx.Prepare("update channel set head_operatorbundle_name = ? where name = ? and package_name = ?") - if err != nil { - return err - } - defer updateChannel.Close() - - _, err = updateChannel.Exec(channelName, packageName, headCsvName) - if err != nil { - return err - } - - return nil -} - -func addOrUpdateChannel(tx *sql.Tx, channelName, packageName, headCsvName string) error { - addChannel, err := tx.Prepare("insert or replace into channel(name, package_name, head_operatorbundle_name) values(?, ?, ?)") - if err != nil { - return err - } - defer addChannel.Close() - - _, err = addChannel.Exec(channelName, packageName, headCsvName) - if err != nil { - return err - } - - return nil -} - -func updateDefaultChannel(tx *sql.Tx, channelName, packageName string) error { - updateDefaultChannel, err := tx.Prepare("update package set default_channel = ? where name = ?") - if err != nil { - return err - } - defer updateDefaultChannel.Close() - - _, err = updateDefaultChannel.Exec(channelName, packageName) - if err != nil { - return err - } - - return nil -} - -func truncChannelGraph(tx *sql.Tx, channelName, packageName string) error { - truncChannelGraph, err := tx.Prepare("delete from channel_entry where channel_name = ? and package_name = ?") - if err != nil { - return err - } - defer truncChannelGraph.Close() - - _, err = truncChannelGraph.Exec(channelName, packageName) - if err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/000_init.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/000_init.go deleted file mode 100644 index 00986acae..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/000_init.go +++ /dev/null @@ -1,78 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" -) - -var InitMigrationKey = 0 - -func init() { - registerMigration(InitMigrationKey, initMigration) -} - -var initMigration = &Migration{ - Id: InitMigrationKey, - Up: func(ctx context.Context, tx *sql.Tx) error { - sql := ` - CREATE TABLE IF NOT EXISTS operatorbundle ( - name TEXT PRIMARY KEY, - csv TEXT UNIQUE, - bundle TEXT - ); - CREATE TABLE IF NOT EXISTS package ( - name TEXT PRIMARY KEY, - default_channel TEXT, - FOREIGN KEY(name, default_channel) REFERENCES channel(package_name,name) - ); - CREATE TABLE IF NOT EXISTS channel ( - name TEXT, - package_name TEXT, - head_operatorbundle_name TEXT, - PRIMARY KEY(name, package_name), - FOREIGN KEY(package_name) REFERENCES package(name), - FOREIGN KEY(head_operatorbundle_name) REFERENCES operatorbundle(name) - ); - CREATE TABLE IF NOT EXISTS channel_entry ( - entry_id INTEGER PRIMARY KEY, - channel_name TEXT, - package_name TEXT, - operatorbundle_name TEXT, - replaces INTEGER, - depth INTEGER, - FOREIGN KEY(replaces) REFERENCES channel_entry(entry_id) DEFERRABLE INITIALLY DEFERRED, - FOREIGN KEY(channel_name, package_name) REFERENCES channel(name, package_name) - ); - CREATE TABLE IF NOT EXISTS api ( - group_name TEXT, - version TEXT, - kind TEXT, - plural TEXT NOT NULL, - PRIMARY KEY(group_name, version, kind) - ); - CREATE TABLE IF NOT EXISTS api_provider ( - group_name TEXT, - version TEXT, - kind TEXT, - channel_entry_id INTEGER, - FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id), - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) - ); - ` - _, err := tx.ExecContext(ctx, sql) - return err - }, - Down: func(ctx context.Context, tx *sql.Tx) error { - sql := ` - DROP TABLE operatorbundle; - DROP TABLE package; - DROP TABLE channel; - DROP TABLE channel_entry; - DROP TABLE api; - DROP TABLE api_provider; - ` - _, err := tx.ExecContext(ctx, sql) - - return err - }, -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/001_related_images.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/001_related_images.go deleted file mode 100644 index 3b3c8c36b..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/001_related_images.go +++ /dev/null @@ -1,123 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" - "encoding/json" - "fmt" - - "github.com/sirupsen/logrus" - - "github.com/operator-framework/operator-registry/pkg/registry" -) - -const RelatedImagesMigrationKey = 1 - -func init() { - registerMigration(RelatedImagesMigrationKey, relatedImagesMigration) -} - -// listBundles returns a list of operatorbundles as strings -func listBundles(ctx context.Context, tx *sql.Tx) ([]string, error) { - query := "SELECT DISTINCT name FROM operatorbundle" - rows, err := tx.QueryContext(ctx, query) - if err != nil { - return nil, err - } - bundles := []string{} - for rows.Next() { - var bundleName sql.NullString - if err := rows.Scan(&bundleName); err != nil { - return nil, err - } - if bundleName.Valid { - bundles = append(bundles, bundleName.String) - } - } - return bundles, nil -} - -// getCSV pulls the csv from by name -func getCSV(ctx context.Context, tx *sql.Tx, name string) (*registry.ClusterServiceVersion, error) { - query := `SELECT csv FROM operatorbundle WHERE operatorbundle.name=?` - rows, err := tx.QueryContext(ctx, query, name) - if err != nil { - return nil, err - } - - var csvJson sql.NullString - if !rows.Next() { - return nil, fmt.Errorf("bundle %s not found", name) - } - if err := rows.Scan(&csvJson); err != nil { - return nil, err - } - if !csvJson.Valid { - return nil, fmt.Errorf("bad value for csv") - } - csv := ®istry.ClusterServiceVersion{} - if err := json.Unmarshal([]byte(csvJson.String), csv); err != nil { - return nil, err - } - return csv, nil -} - -func extractRelatedImages(ctx context.Context, tx *sql.Tx, name string) error { - addSql := `insert into related_image(image, operatorbundle_name) values(?,?)` - csv, err := getCSV(ctx, tx, name) - if err != nil { - logrus.Warnf("error backfilling related images: %v", err) - return err - } - images, err := csv.GetOperatorImages() - if err != nil { - logrus.Warnf("error backfilling related images: %v", err) - return err - } - related, err := csv.GetRelatedImages() - if err != nil { - logrus.Warnf("error backfilling related images: %v", err) - return err - } - for k := range related { - images[k] = struct{}{} - } - for img := range images { - if _, err := tx.ExecContext(ctx, addSql, img, name); err != nil { - logrus.Warnf("error backfilling related images: %v", err) - continue - } - } - return nil -} - -var relatedImagesMigration = &Migration{ - Id: RelatedImagesMigrationKey, - Up: func(ctx context.Context, tx *sql.Tx) error { - sql := ` - CREATE TABLE IF NOT EXISTS related_image ( - image TEXT, - operatorbundle_name TEXT, - FOREIGN KEY(operatorbundle_name) REFERENCES operatorbundle(name) - ); - ` - _, err := tx.ExecContext(ctx, sql) - - bundles, err := listBundles(ctx, tx) - if err != nil { - return err - } - for _, bundle := range bundles { - if err := extractRelatedImages(ctx, tx, bundle); err != nil { - logrus.Warnf("error backfilling related images: %v", err) - continue - } - } - return err - }, - Down: func(ctx context.Context, tx *sql.Tx) error { - sql := `DROP TABLE related_image;` - _, err := tx.ExecContext(ctx, sql) - return err - }, -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/002_bundle_path.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/002_bundle_path.go deleted file mode 100644 index b16c13d76..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/002_bundle_path.go +++ /dev/null @@ -1,55 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" -) - -const BundlePathMigrationKey = 2 - -// Register this migration -func init() { - registerMigration(BundlePathMigrationKey, bundlePathMigration) -} - -var bundlePathMigration = &Migration{ - Id: BundlePathMigrationKey, - Up: func(ctx context.Context, tx *sql.Tx) error { - sql := ` - ALTER TABLE operatorbundle - ADD COLUMN bundlepath TEXT; - ` - _, err := tx.ExecContext(ctx, sql) - return err - }, - Down: func(ctx context.Context, tx *sql.Tx) error { - foreignKeyOff := `PRAGMA foreign_keys = 0` - createTempTable := `CREATE TABLE operatorbundle_backup (name TEXT,csv TEXT,bundle TEXT)` - backupTargetTable := `INSERT INTO operatorbundle_backup SELECT name,csv,bundle FROM operatorbundle` - dropTargetTable := `DROP TABLE operatorbundle` - renameBackUpTable := `ALTER TABLE operatorbundle_backup RENAME TO operatorbundle;` - foreignKeyOn := `PRAGMA foreign_keys = 1` - _, err := tx.ExecContext(ctx, foreignKeyOff) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, createTempTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, backupTargetTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, dropTargetTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, renameBackUpTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, foreignKeyOn) - return err - }, -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/003_required_apis.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/003_required_apis.go deleted file mode 100644 index 0253c5119..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/003_required_apis.go +++ /dev/null @@ -1,147 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" - "fmt" - "strings" - - "github.com/sirupsen/logrus" -) - -const RequiredApiMigrationKey = 3 - -// Register this migration -func init() { - registerMigration(RequiredApiMigrationKey, requiredApiMigration) -} - -var requiredApiMigration = &Migration{ - Id: RequiredApiMigrationKey, - Up: func(ctx context.Context, tx *sql.Tx) error { - sql := ` - CREATE TABLE IF NOT EXISTS api_requirer ( - group_name TEXT, - version TEXT, - kind TEXT, - channel_entry_id INTEGER, - FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id), - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) - ); - ` - _, err := tx.ExecContext(ctx, sql) - if err != nil { - return err - } - bundles, err := getChannelEntryBundles(ctx, tx) - if err != nil { - return err - } - for entryId, bundle := range bundles { - if err := extractRequiredApis(ctx, tx, entryId, bundle); err != nil { - logrus.Warnf("error backfilling required apis: %v", err) - continue - } - } - return nil - }, - Down: func(ctx context.Context, tx *sql.Tx) error { - _, err := tx.ExecContext(ctx, `DROP TABLE api_requirer`) - if err != nil { - return err - } - - return err - }, -} - -func getChannelEntryBundles(ctx context.Context, tx *sql.Tx) (map[int64]string, error) { - query := `SELECT DISTINCT channel_entry.entry_id, operatorbundle.name FROM channel_entry - INNER JOIN operatorbundle ON operatorbundle.name = channel_entry.operatorbundle_name` - - rows, err := tx.QueryContext(ctx, query) - if err != nil { - return nil, err - } - - entries := map[int64]string{} - - for rows.Next() { - var entryId sql.NullInt64 - var name sql.NullString - if err = rows.Scan(&entryId, &name); err != nil { - return nil, err - } - if !entryId.Valid || !name.Valid { - continue - } - entries[entryId.Int64] = name.String - } - return entries, nil -} - -func extractRequiredApis(ctx context.Context, tx *sql.Tx, entryId int64, name string) error { - addAPI, err := tx.Prepare("insert or replace into api(group_name, version, kind, plural) values(?, ?, ?, ?)") - if err != nil { - return err - } - defer func() { - if err := addAPI.Close(); err != nil { - logrus.WithError(err).Warningf("error closing prepared statement") - } - }() - - addApiRequirer, err := tx.Prepare("insert into api_requirer(group_name, version, kind, channel_entry_id) values(?, ?, ?, ?)") - if err != nil { - return err - } - defer func() { - if err := addApiRequirer.Close(); err != nil { - logrus.WithError(err).Warningf("error closing prepared statement") - } - }() - - csv, err := getCSV(ctx, tx, name) - if err != nil { - logrus.Warnf("error backfilling required apis: %v", err) - return err - } - - _, requiredCRDs, err := csv.GetCustomResourceDefintions() - for _, crd := range requiredCRDs { - plural, group, err := SplitCRDName(crd.Name) - if err != nil { - return err - } - if _, err := addAPI.Exec(group, crd.Version, crd.Kind, plural); err != nil { - return err - } - if _, err := addApiRequirer.Exec(group, crd.Version, crd.Kind, entryId); err != nil { - return err - } - } - - _, requiredAPIs, err := csv.GetApiServiceDefinitions() - for _, api := range requiredAPIs { - if _, err := addAPI.Exec(api.Group, api.Version, api.Kind, api.Name); err != nil { - return err - } - if _, err := addApiRequirer.Exec(api.Group, api.Version, api.Kind, entryId); err != nil { - return err - } - } - - return nil -} - -func SplitCRDName(crdName string) (plural, group string, err error) { - pluralGroup := strings.SplitN(crdName, ".", 2) - if len(pluralGroup) != 2 { - err = fmt.Errorf("can't split bad CRD name %s", crdName) - return - } - - plural = pluralGroup[0] - group = pluralGroup[1] - return -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/004_cascade_delete.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/004_cascade_delete.go deleted file mode 100644 index 6cdd9bed2..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/004_cascade_delete.go +++ /dev/null @@ -1,453 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" -) - -var CascadeDeleteMigrationKey = 4 - -// Register this migration -func init() { - registerMigration(CascadeDeleteMigrationKey, cascadeDeleteMigration) -} - -var cascadeDeleteMigration = &Migration{ - Id: CascadeDeleteMigrationKey, - Up: func(ctx context.Context, tx *sql.Tx) error { - foreingKeyOff := `PRAGMA foreign_keys = 0` - renameTable := func(table string) string { - return `ALTER TABLE ` + table + ` RENAME TO ` + table + `_old;` - } - createNewOperatorBundleTable := ` - CREATE TABLE operatorbundle ( - name TEXT PRIMARY KEY, - csv TEXT, - bundle TEXT, - bundlepath TEXT);` - createNewPackageTable := ` - CREATE TABLE package ( - name TEXT PRIMARY KEY, - default_channel TEXT, - FOREIGN KEY(name, default_channel) REFERENCES channel(package_name,name) ON DELETE CASCADE - );` - createNewChannelTable := ` - CREATE TABLE channel ( - name TEXT, - package_name TEXT, - head_operatorbundle_name TEXT, - PRIMARY KEY(name, package_name), - FOREIGN KEY(head_operatorbundle_name) REFERENCES operatorbundle(name) ON DELETE CASCADE - );` - createNewChannelEntryTable := ` - CREATE TABLE channel_entry ( - entry_id INTEGER PRIMARY KEY, - channel_name TEXT, - package_name TEXT, - operatorbundle_name TEXT, - replaces INTEGER, - depth INTEGER, - FOREIGN KEY(replaces) REFERENCES channel_entry(entry_id) DEFERRABLE INITIALLY DEFERRED, - FOREIGN KEY(channel_name, package_name) REFERENCES channel(name, package_name) ON DELETE CASCADE - );` - createNewAPIProviderTable := ` - CREATE TABLE api_provider ( - group_name TEXT, - version TEXT, - kind TEXT, - channel_entry_id INTEGER, - PRIMARY KEY(group_name, version, kind, channel_entry_id), - FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id) ON DELETE CASCADE, - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) - );` - createNewRelatedImageTable := ` - CREATE TABLE related_image ( - image TEXT, - operatorbundle_name TEXT, - FOREIGN KEY(operatorbundle_name) REFERENCES operatorbundle(name) ON DELETE CASCADE - );` - createNewAPIRequirerTable := ` - CREATE TABLE api_requirer ( - group_name TEXT, - version TEXT, - kind TEXT, - channel_entry_id INTEGER, - PRIMARY KEY(group_name, version, kind, channel_entry_id), - FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id) ON DELETE CASCADE, - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) - );` - newTableTransfer := func(table string) string { - return `INSERT INTO ` + table + ` SELECT * FROM "` + table + `_old"` - } - dropTable := func(table string) string { - return `DROP TABLE "` + table + `_old"` - } - foreingKeyOn := `PRAGMA foreign_keys = 1` - - _, err := tx.ExecContext(ctx, foreingKeyOff) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`operatorbundle`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`package`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`channel`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`channel_entry`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`api_provider`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`related_image`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`api_requirer`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createNewOperatorBundleTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createNewPackageTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createNewChannelTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createNewChannelEntryTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createNewAPIProviderTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createNewRelatedImageTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createNewAPIRequirerTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, newTableTransfer(`operatorbundle`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`operatorbundle`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, newTableTransfer(`package`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`package`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, newTableTransfer(`channel`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`channel`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, newTableTransfer(`channel_entry`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`channel_entry`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, newTableTransfer(`api_provider`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`api_provider`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, newTableTransfer(`related_image`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`related_image`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, newTableTransfer(`api_requirer`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`api_requirer`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, foreingKeyOn) - return err - }, - Down: func(ctx context.Context, tx *sql.Tx) error { - foreingKeyOff := `PRAGMA foreign_keys = 0` - renameTable := func(table string) string { - return `ALTER TABLE ` + table + ` RENAME TO ` + table + `_old;` - } - createBackupOperatorBundleTable := ` - CREATE TABLE operatorbundle ( - name TEXT PRIMARY KEY, - csv TEXT UNIQUE, - bundle TEXT, - bundlepath TEXT);` - createBackupPackageTable := ` - CREATE TABLE IF NOT EXISTS package ( - name TEXT PRIMARY KEY, - default_channel TEXT, - FOREIGN KEY(name, default_channel) REFERENCES channel(package_name,name) - );` - createBackupChannelTable := ` - CREATE TABLE IF NOT EXISTS channel ( - name TEXT, - package_name TEXT, - head_operatorbundle_name TEXT, - PRIMARY KEY(name, package_name), - FOREIGN KEY(package_name) REFERENCES package(name), - FOREIGN KEY(head_operatorbundle_name) REFERENCES operatorbundle(name) - );` - createBackupChannelEntryTable := ` - CREATE TABLE IF NOT EXISTS channel_entry ( - entry_id INTEGER PRIMARY KEY, - channel_name TEXT, - package_name TEXT, - operatorbundle_name TEXT, - replaces INTEGER, - depth INTEGER, - FOREIGN KEY(replaces) REFERENCES channel_entry(entry_id) DEFERRABLE INITIALLY DEFERRED, - FOREIGN KEY(channel_name, package_name) REFERENCES channel(name, package_name) - );` - createBackupAPIProviderTable := ` - CREATE TABLE IF NOT EXISTS api_provider ( - group_name TEXT, - version TEXT, - kind TEXT, - channel_entry_id INTEGER, - FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id), - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) - );` - createBackupRelatedImageTable := ` - CREATE TABLE IF NOT EXISTS related_image ( - image TEXT, - operatorbundle_name TEXT, - FOREIGN KEY(operatorbundle_name) REFERENCES operatorbundle(name) - );` - createBackupAPIRequirerTable := ` - CREATE TABLE IF NOT EXISTS api_requirer ( - group_name TEXT, - version TEXT, - kind TEXT, - channel_entry_id INTEGER, - FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id), - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) - );` - backupTableTransfer := func(table string) string { - return `INSERT INTO ` + table + ` SELECT * FROM "` + table + `_old"` - } - dropTable := func(table string) string { - return `DROP TABLE "` + table + `_old"` - } - - foreingKeyOn := `PRAGMA foreign_keys = 1` - - _, err := tx.ExecContext(ctx, foreingKeyOff) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`operatorbundle`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`package`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`channel`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`channel_entry`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`api_provider`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`related_image`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, renameTable(`api_requirer`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createBackupOperatorBundleTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createBackupPackageTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createBackupChannelTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createBackupChannelEntryTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createBackupAPIProviderTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createBackupRelatedImageTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, createBackupAPIRequirerTable) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, backupTableTransfer(`operatorbundle`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`operatorbundle`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, backupTableTransfer(`package`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`package`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, backupTableTransfer(`channel`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`channel`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, backupTableTransfer(`channel_entry`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`channel_entry`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, backupTableTransfer(`api_provider`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`api_provider`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, backupTableTransfer(`related_image`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`related_image`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, backupTableTransfer(`api_requirer`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, dropTable(`api_requirer`)) - if err != nil { - return err - } - - _, err = tx.ExecContext(ctx, foreingKeyOn) - return err - }, -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/005_version_skiprange.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/005_version_skiprange.go deleted file mode 100644 index 60b3c87ad..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/005_version_skiprange.go +++ /dev/null @@ -1,94 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" - - "github.com/sirupsen/logrus" -) - -const VersionSkipRangeMigrationKey = 5 -const SkipRangeAnnotationKey = "olm.skipRange" - -// Register this migration -func init() { - registerMigration(VersionSkipRangeMigrationKey, versionSkipRangeMigration) -} - -var versionSkipRangeMigration = &Migration{ - Id: VersionSkipRangeMigrationKey, - Up: func(ctx context.Context, tx *sql.Tx) error { - sql := ` - ALTER TABLE operatorbundle - ADD COLUMN skiprange TEXT; - - ALTER TABLE operatorbundle - ADD COLUMN version TEXT; - ` - _, err := tx.ExecContext(ctx, sql) - if err != nil { - return err - } - - bundles, err := listBundles(ctx, tx) - if err != nil { - return err - } - for _, bundle := range bundles { - if err := extractVersioning(ctx, tx, bundle); err != nil { - logrus.Warnf("error backfilling versioning: %v", err) - continue - } - } - return err - }, - Down: func(ctx context.Context, tx *sql.Tx) error { - foreignKeyOff := `PRAGMA foreign_keys = 0` - createTempTable := `CREATE TABLE operatorbundle_backup (name TEXT, csv TEXT, bundle TEXT, bundlepath TEXT)` - backupTargetTable := `INSERT INTO operatorbundle_backup SELECT name, csv, bundle, bundlepath FROM operatorbundle` - dropTargetTable := `DROP TABLE operatorbundle` - renameBackUpTable := `ALTER TABLE operatorbundle_backup RENAME TO operatorbundle;` - foreignKeyOn := `PRAGMA foreign_keys = 1` - _, err := tx.ExecContext(ctx, foreignKeyOff) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, createTempTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, backupTargetTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, dropTargetTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, renameBackUpTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, foreignKeyOn) - return err - }, -} - -func extractVersioning(ctx context.Context, tx *sql.Tx, name string) error { - addSql := `insert into operatorbundle(version, skiprange) values(?,?)` - csv, err := getCSV(ctx, tx, name) - if err != nil { - logrus.Warnf("error backfilling versioning: %v", err) - return err - } - skiprange, ok := csv.Annotations[SkipRangeAnnotationKey] - if !ok { - skiprange = "" - } - version, err := csv.GetVersion() - if err != nil { - version = "" - } - _, err = tx.ExecContext(ctx, addSql, version, skiprange) - return err -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/006_associate_apis_with_bundle.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/006_associate_apis_with_bundle.go deleted file mode 100644 index 221d90e48..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/006_associate_apis_with_bundle.go +++ /dev/null @@ -1,335 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" - "github.com/operator-framework/operator-registry/pkg/registry" -) - -const AssociateApisWithBundleMigrationKey = 6 - -// Register this migration -func init() { - registerMigration(AssociateApisWithBundleMigrationKey, bundleApiMigration) -} - -// This migration moves the link between the provided and required apis table from the channel_entry to the -// bundle itself. This simplifies loading and minimizes changes that need to happen when a new bundle is -// inserted into an existing database. -// Before: -// api_provider: FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id), -// api_requirer: FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id), -// After: -// api_provider: FOREIGN KEY(operatorbundle_name, operatorbundle_version, operatorbundle_path) REFERENCES operatorbundle(name, version, bundlepath), -// api_requirer: FOREIGN KEY(operatorbundle_name, operatorbundle_version, operatorbundle_path) REFERENCES operatorbundle(name, version, bundlepath), - -var bundleApiMigration = &Migration{ - Id: AssociateApisWithBundleMigrationKey, - Up: func(ctx context.Context, tx *sql.Tx) error { - createNew := ` - CREATE TABLE api_provider_new ( - group_name TEXT, - version TEXT, - kind TEXT, - operatorbundle_name TEXT, - operatorbundle_version TEXT, - operatorbundle_path TEXT, - FOREIGN KEY(operatorbundle_name, operatorbundle_version, operatorbundle_path) REFERENCES operatorbundle(name, version, bundlepath) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) ON DELETE CASCADE - ); - CREATE TABLE api_requirer_new ( - group_name TEXT, - version TEXT, - kind TEXT, - operatorbundle_name TEXT, - operatorbundle_version TEXT, - operatorbundle_path TEXT, - FOREIGN KEY(operatorbundle_name, operatorbundle_version, operatorbundle_path) REFERENCES operatorbundle(name, version, bundlepath) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) ON DELETE CASCADE - ); --- these three fields are used as the target of a foreign key, so they need an index - CREATE UNIQUE INDEX pk ON operatorbundle(name, version, bundlepath); - ` - _, err := tx.ExecContext(ctx, createNew) - if err != nil { - return err - } - - insertProvided := `INSERT INTO api_provider_new(group_name, version, kind, operatorbundle_name, operatorbundle_version, operatorbundle_path) VALUES (?, ?, ?, ?, ?, ?)` - insertRequired := `INSERT INTO api_requirer_new(group_name, version, kind, operatorbundle_name, operatorbundle_version, operatorbundle_path) VALUES (?, ?, ?, ?, ?, ?)` - - bundleApis, err := mapBundlesToApisFromOldSchema(ctx, tx) - if err != nil { - return err - } - for bundle, apis := range bundleApis { - for provided := range apis.provided { - _, err := tx.ExecContext(ctx, insertProvided, provided.Group, provided.Version, provided.Kind, bundle.CsvName, bundle.Version, bundle.BundlePath) - if err != nil { - return err - } - } - for required := range apis.required { - _, err := tx.ExecContext(ctx, insertRequired, required.Group, required.Version, required.Kind, bundle.CsvName, bundle.Version, bundle.BundlePath) - if err != nil { - return err - } - } - } - - renameNewAndDropOld := ` - DROP TABLE api_provider; - DROP TABLE api_requirer; - ALTER TABLE api_provider_new RENAME TO api_provider; - ALTER TABLE api_requirer_new RENAME TO api_requirer; - ` - _, err = tx.ExecContext(ctx, renameNewAndDropOld) - if err != nil { - return err - } - - return err - }, - Down: func(ctx context.Context, tx *sql.Tx) error { - createOld := ` - CREATE TABLE api_provider_old ( - group_name TEXT, - version TEXT, - kind TEXT, - channel_entry_id INTEGER, - FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id), - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) ON DELETE CASCADE - ); - CREATE TABLE api_requirer_old ( - group_name TEXT, - version TEXT, - kind TEXT, - channel_entry_id INTEGER, - FOREIGN KEY(channel_entry_id) REFERENCES channel_entry(entry_id), - FOREIGN KEY(group_name, version, kind) REFERENCES api(group_name, version, kind) ON DELETE CASCADE - ); - ` - _, err := tx.ExecContext(ctx, createOld) - if err != nil { - return err - } - - insertProvided := `INSERT INTO api_provider_old(group_name, version, kind, channel_entry_id) VALUES (?, ?, ?, ?)` - insertRequired := `INSERT INTO api_requirer_old(group_name, version, kind, channel_entry_id) VALUES (?, ?, ?, ?)` - - entryApis, err := mapChannelEntryToApisFromNewSchema(ctx, tx) - if err != nil { - return err - } - for entry, apis := range entryApis { - for provided := range apis.provided { - _, err := tx.ExecContext(ctx, insertProvided, provided.Group, provided.Version, provided.Kind, entry) - if err != nil { - return err - } - } - for required := range apis.required { - _, err := tx.ExecContext(ctx, insertRequired, required.Group, required.Version, required.Kind, entry) - if err != nil { - return err - } - } - } - - renameOldAndDrop := ` - DROP TABLE api_provider; - DROP TABLE api_requirer; - ALTER TABLE api_provider_old RENAME TO api_provider; - ALTER TABLE api_requirer_old RENAME TO api_requirer; - ` - _, err = tx.ExecContext(ctx, renameOldAndDrop) - if err != nil { - return err - } - - return err - }, -} - -type bundleKey struct { - BundlePath sql.NullString - Version sql.NullString - CsvName sql.NullString -} - -type apis struct { - provided map[registry.APIKey]struct{} - required map[registry.APIKey]struct{} -} - -func mapBundlesToApisFromOldSchema(ctx context.Context, tx *sql.Tx) (map[bundleKey]apis, error) { - bundles := map[bundleKey]apis{} - - providedQuery := `SELECT api_provider.group_name, api_provider.version, api_provider.kind, operatorbundle.name, operatorbundle.version, operatorbundle.bundlepath - FROM api_provider - INNER JOIN channel_entry ON channel_entry.entry_id = api_provider.channel_entry_id - INNER JOIN operatorbundle ON operatorbundle.name = channel_entry.operatorbundle_name` - - requiredQuery := `SELECT api_requirer.group_name, api_requirer.version, api_requirer.kind, operatorbundle.name, operatorbundle.version, operatorbundle.bundlepath - FROM api_requirer - INNER JOIN channel_entry ON channel_entry.entry_id = api_requirer.channel_entry_id - INNER JOIN operatorbundle ON operatorbundle.name = channel_entry.operatorbundle_name` - - providedRows, err := tx.QueryContext(ctx, providedQuery) - if err != nil { - return nil, err - } - for providedRows.Next() { - var group, apiVersion, kind, name, bundleVersion, path sql.NullString - - if err = providedRows.Scan(&group, &apiVersion, &kind, &name, &bundleVersion, &path); err != nil { - return nil, err - } - if !group.Valid || !apiVersion.Valid || !kind.Valid || !name.Valid { - continue - } - key := bundleKey{ - BundlePath: path, - Version: bundleVersion, - CsvName: name, - } - bundleApis, ok := bundles[key] - if !ok { - bundleApis = apis{ - provided: map[registry.APIKey]struct{}{}, - required: map[registry.APIKey]struct{}{}, - } - } - - bundleApis.provided[registry.APIKey{ - Group: group.String, - Version: apiVersion.String, - Kind: kind.String, - }] = struct{}{} - - bundles[key] = bundleApis - } - - requiredRows, err := tx.QueryContext(ctx, requiredQuery) - if err != nil { - return nil, err - } - for requiredRows.Next() { - var group sql.NullString - var apiVersion sql.NullString - var kind sql.NullString - var name sql.NullString - var bundleVersion sql.NullString - var path sql.NullString - if err = requiredRows.Scan(&group, &apiVersion, &kind, &name, &bundleVersion, &path); err != nil { - return nil, err - } - if !group.Valid || !apiVersion.Valid || !kind.Valid || !name.Valid { - continue - } - key := bundleKey{ - BundlePath: path, - Version: bundleVersion, - CsvName: name, - } - bundleApis, ok := bundles[key] - if !ok { - bundleApis = apis{ - provided: map[registry.APIKey]struct{}{}, - required: map[registry.APIKey]struct{}{}, - } - } - - bundleApis.required[registry.APIKey{ - Group: group.String, - Version: apiVersion.String, - Kind: kind.String, - }] = struct{}{} - - bundles[key] = bundleApis - } - - return bundles, nil -} - -func mapChannelEntryToApisFromNewSchema(ctx context.Context, tx *sql.Tx) (map[int64]apis, error) { - bundles := map[int64]apis{} - - providedQuery := `SELECT api_provider.group_name, api_provider.version, api_provider.kind, channel_entry.entry_id - FROM api_provider - INNER JOIN operatorbundle ON operatorbundle.name = channel_entry.operatorbundle_name - INNER JOIN channel_entry ON channel_entry.operatorbundle_name = api_provider.operatorbundle_name` - - requiredQuery := `SELECT api_requirer.group_name, api_requirer.version, api_requirer.kind, channel_entry.entry_id - FROM api_requirer - INNER JOIN channel_entry ON channel_entry.operatorbundle_name = api_requirer.operatorbundle_name - INNER JOIN operatorbundle ON operatorbundle.name = channel_entry.operatorbundle_name` - - providedRows, err := tx.QueryContext(ctx, providedQuery) - if err != nil { - return nil, err - } - for providedRows.Next() { - var ( - group, apiVersion, kind sql.NullString - entryID sql.NullInt64 - ) - if err = providedRows.Scan(&group, &apiVersion, &kind, &entryID); err != nil { - return nil, err - } - if !group.Valid || !apiVersion.Valid || !kind.Valid { - continue - } - - bundleApis, ok := bundles[entryID.Int64] - if !ok { - bundleApis = apis{ - provided: map[registry.APIKey]struct{}{}, - required: map[registry.APIKey]struct{}{}, - } - } - - bundleApis.provided[registry.APIKey{ - Group: group.String, - Version: apiVersion.String, - Kind: kind.String, - }] = struct{}{} - - bundles[entryID.Int64] = bundleApis - } - - requiredRows, err := tx.QueryContext(ctx, requiredQuery) - if err != nil { - return nil, err - } - for requiredRows.Next() { - var ( - group, apiVersion, kind sql.NullString - entryID sql.NullInt64 - ) - if err = providedRows.Scan(&group, &apiVersion, &kind, &entryID); err != nil { - return nil, err - } - if !group.Valid || !apiVersion.Valid || !kind.Valid { - continue - } - - bundleApis, ok := bundles[entryID.Int64] - if !ok { - bundleApis = apis{ - provided: map[registry.APIKey]struct{}{}, - required: map[registry.APIKey]struct{}{}, - } - } - - bundleApis.required[registry.APIKey{ - Group: group.String, - Version: apiVersion.String, - Kind: kind.String, - }] = struct{}{} - - bundles[entryID.Int64] = bundleApis - } - - return bundles, nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/007_replaces_skips.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/007_replaces_skips.go deleted file mode 100644 index 7825e89fe..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/007_replaces_skips.go +++ /dev/null @@ -1,142 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" - "fmt" - "strings" -) - -const ReplacesSkipsMigrationKey = 7 - -// Register this migration -func init() { - registerMigration(ReplacesSkipsMigrationKey, replacesSkipsMigration) -} - -// This migration adds a replaces and skips field to the operatorbundle table -// Two triggers are added to clean up the api table when no bundles require or provide them anymore -var replacesSkipsMigration = &Migration{ - Id: ReplacesSkipsMigrationKey, - Up: func(ctx context.Context, tx *sql.Tx) error { - sql := ` - ALTER TABLE operatorbundle - ADD COLUMN replaces TEXT; - - ALTER TABLE operatorbundle - ADD COLUMN skips TEXT; - - CREATE TRIGGER api_provider_cleanup - AFTER DELETE ON api_provider - WHEN NOT EXISTS (SELECT 1 FROM api_provider JOIN api_requirer WHERE - (api_provider.group_name = OLD.group_name AND api_provider.version = OLD.version AND api_provider.kind = OLD.kind) OR - (api_requirer.group_name = OLD.group_name AND api_requirer.version = OLD.version AND api_requirer.kind = OLD.kind)) - BEGIN - DELETE FROM api WHERE group_name = OLD.group_name AND version = OLD.version AND kind = OLD.kind; - END; - - CREATE TRIGGER api_requirer_cleanup - AFTER DELETE ON api_requirer - WHEN NOT EXISTS (SELECT 1 FROM api_provider JOIN api_requirer WHERE - (api_provider.group_name = OLD.group_name AND api_provider.version = OLD.version AND api_provider.kind = OLD.kind) OR - (api_requirer.group_name = OLD.group_name AND api_requirer.version = OLD.version AND api_requirer.kind = OLD.kind)) - BEGIN - DELETE FROM api WHERE group_name = OLD.group_name AND version = OLD.version AND kind = OLD.kind; - END; - ` - _, err := tx.ExecContext(ctx, sql) - if err != nil { - return err - } - - bundles, err := listBundles(ctx, tx) - if err != nil { - return err - } - for _, bundle := range bundles { - if err := extractReplaces(ctx, tx, bundle); err != nil { - return fmt.Errorf("error backfilling replaces and skips: %v", err) - } - } - return err - }, - Down: func(ctx context.Context, tx *sql.Tx) error { - foreignKeyOff := `PRAGMA foreign_keys = 0` - createTempTable := `CREATE TABLE operatorbundle_backup (name TEXT, csv TEXT, bundle TEXT, bundlepath TEXT, version TEXT, skiprange TEXT)` - backupTargetTable := `INSERT INTO operatorbundle_backup SELECT name, csv, bundle, bundlepath, version, skiprange FROM operatorbundle` - dropTargetTable := `DROP TABLE operatorbundle` - renameBackUpTable := `ALTER TABLE operatorbundle_backup RENAME TO operatorbundle;` - foreignKeyOn := `PRAGMA foreign_keys = 1` - _, err := tx.ExecContext(ctx, foreignKeyOff) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, createTempTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, backupTargetTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, dropTargetTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, renameBackUpTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, foreignKeyOn) - return err - }, -} - -func extractReplaces(ctx context.Context, tx *sql.Tx, name string) error { - replaces, skips, err := getReplacesAndSkips(ctx, tx, name) - if err != nil { - return err - } - updateSql := `update operatorbundle SET replaces = ?, skips = ? WHERE name = ?;` - _, err = tx.ExecContext(ctx, updateSql, replaces, strings.Join(skips, ","), name) - return err -} - -func getReplacesAndSkips(ctx context.Context, tx *sql.Tx, name string) (replaces string, skips []string, err error) { - getReplacees := ` - SELECT DISTINCT replaces.operatorbundle_name - FROM channel_entry - LEFT OUTER JOIN channel_entry replaces ON channel_entry.replaces = replaces.entry_id - WHERE channel_entry.operatorbundle_name = ? - ORDER BY channel_entry.depth ASC - ` - - rows, err := tx.QueryContext(ctx, getReplacees, name) - if err != nil { - return "", nil, fmt.Errorf("error backfilling replaces and skips: %v", err) - } - defer rows.Close() - - if rows.Next() { - var replaceeName sql.NullString - if err = rows.Scan(&replaceeName); err != nil { - return - } - if replaceeName.Valid { - replaces = replaceeName.String - } - } - - skips = []string{} - for rows.Next() { - var skipName sql.NullString - if err = rows.Scan(&skipName); err != nil { - return - } - if !skipName.Valid { - continue - } - skips = append(skips, skipName.String) - } - return -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/008_dependencies.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/008_dependencies.go deleted file mode 100644 index 3df3bd64d..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/008_dependencies.go +++ /dev/null @@ -1,119 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" - "encoding/json" - - "github.com/operator-framework/operator-registry/pkg/registry" -) - -const DependenciesMigrationKey = 8 - -// Register this migration -func init() { - registerMigration(DependenciesMigrationKey, dependenciesMigration) -} - -var dependenciesMigration = &Migration{ - Id: DependenciesMigrationKey, - Up: func(ctx context.Context, tx *sql.Tx) error { - sql := ` - CREATE TABLE IF NOT EXISTS dependencies ( - type TEXT, - value TEXT, - operatorbundle_name TEXT, - operatorbundle_version TEXT, - operatorbundle_path TEXT, - FOREIGN KEY(operatorbundle_name, operatorbundle_version, operatorbundle_path) REFERENCES operatorbundle(name, version, bundlepath) ON DELETE CASCADE - ); - ` - _, err := tx.ExecContext(ctx, sql) - if err != nil { - return err - } - - insertRequired := `INSERT INTO dependencies(type, value, operatorbundle_name, operatorbundle_version, operatorbundle_path) VALUES (?, ?, ?, ?, ?)` - - bundleApis, err := getRequiredAPIs(ctx, tx) - if err != nil { - return err - } - for bundle, apis := range bundleApis { - for required := range apis.required { - valueMap := map[string]string{ - "type": registry.GVKType, - "group": required.Group, - "version": required.Version, - "kind": required.Kind, - } - value, err := json.Marshal(valueMap) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, insertRequired, registry.GVKType, value, bundle.CsvName, bundle.Version, bundle.BundlePath) - if err != nil { - return err - } - } - } - - return nil - }, - Down: func(ctx context.Context, tx *sql.Tx) error { - _, err := tx.ExecContext(ctx, `DROP TABLE dependencies`) - if err != nil { - return err - } - - return err - }, -} - -func getRequiredAPIs(ctx context.Context, tx *sql.Tx) (map[bundleKey]apis, error) { - bundles := map[bundleKey]apis{} - - requiredQuery := `SELECT api_requirer.group_name, api_requirer.version, api_requirer.kind, api_requirer.operatorbundle_name, api_requirer.operatorbundle_version, api_requirer.operatorbundle_path - FROM api_requirer` - - requiredRows, err := tx.QueryContext(ctx, requiredQuery) - if err != nil { - return nil, err - } - for requiredRows.Next() { - var group sql.NullString - var apiVersion sql.NullString - var kind sql.NullString - var name sql.NullString - var bundleVersion sql.NullString - var path sql.NullString - if err = requiredRows.Scan(&group, &apiVersion, &kind, &name, &bundleVersion, &path); err != nil { - return nil, err - } - if !group.Valid || !apiVersion.Valid || !kind.Valid || !name.Valid { - continue - } - key := bundleKey{ - BundlePath: path, - Version: bundleVersion, - CsvName: name, - } - bundleApis, ok := bundles[key] - if !ok { - bundleApis = apis{ - provided: map[registry.APIKey]struct{}{}, - required: map[registry.APIKey]struct{}{}, - } - } - - bundleApis.required[registry.APIKey{ - Group: group.String, - Version: apiVersion.String, - Kind: kind.String, - }] = struct{}{} - - bundles[key] = bundleApis - } - - return bundles, nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/migrations.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/migrations.go deleted file mode 100644 index b9bb60fba..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrations/migrations.go +++ /dev/null @@ -1,93 +0,0 @@ -package migrations - -import ( - "context" - "database/sql" - "fmt" - "sort" -) - -type Migration struct { - Id int - Up func(context.Context, *sql.Tx) error - Down func(context.Context, *sql.Tx) error -} - -type MigrationSet map[int]*Migration - -type Migrations []*Migration - -func (m Migrations) Len() int { return len(m) } -func (m Migrations) Swap(i, j int) { m[i], m[j] = m[j], m[i] } -func (m Migrations) Less(i, j int) bool { return m[i].Id < m[j].Id } - -var migrations MigrationSet = make(map[int]*Migration) - -// From returns a set of migrations, starting at key -func (m MigrationSet) From(key int) Migrations { - keys := make([]int, 0) - for k := range m { - keys = append(keys, k) - } - sort.Ints(keys) - sorted := []*Migration{} - for _, k := range keys { - if k < key { - continue - } - sorted = append(sorted, m[k]) - } - return sorted -} - -// To returns a set of migrations, up to and including key -func (m MigrationSet) To(key int) Migrations { - keys := make([]int, 0) - for k := range m { - keys = append(keys, k) - } - sort.Ints(keys) - sorted := []*Migration{} - for _, k := range keys { - if k > key { - continue - } - sorted = append(sorted, m[k]) - } - return sorted -} - -// Only returns a set of one migration -func (m MigrationSet) Only(key int) Migrations { - return []*Migration{m[key]} -} - -// From returns a set of migrations, starting at key -func From(key int) Migrations { - return migrations.From(key) -} - -// To returns a set of migrations, up to and including key -func To(key int) Migrations { - return migrations.To(key) -} - -// Only returns a set of one migration -func Only(key int) Migrations { - return migrations.Only(key) -} - -// All returns the full set -func All() MigrationSet { - return migrations -} - -func registerMigration(key int, m *Migration) { - if _, ok := migrations[key]; ok { - panic(fmt.Sprintf("already have a migration registered with id %d", key)) - } - if m.Id != key { - panic(fmt.Sprintf("migration has wrong id for key. key: %d, id: %d", key, m.Id)) - } - migrations[key] = m -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrator.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrator.go deleted file mode 100644 index 82bacc834..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/migrator.go +++ /dev/null @@ -1,209 +0,0 @@ -package sqlite - -import ( - "context" - "database/sql" - "fmt" - "strings" - - _ "github.com/golang-migrate/migrate/v4/source/file" // indirect import required by golang-migrate package - "github.com/sirupsen/logrus" - - "github.com/operator-framework/operator-registry/pkg/sqlite/migrations" -) - -type Migrator interface { - Migrate(ctx context.Context) error - Up(ctx context.Context, migrations migrations.Migrations) error - Down(ctx context.Context, migrations migrations.Migrations) error -} - -type SQLLiteMigrator struct { - db *sql.DB - migrationsTable string - migrations migrations.MigrationSet -} - -var _ Migrator = &SQLLiteMigrator{} - -const ( - DefaultMigrationsTable = "schema_migrations" - NilVersion = -1 -) - -// NewSQLLiteMigrator returns a SQLLiteMigrator. -func NewSQLLiteMigrator(db *sql.DB) (Migrator, error) { - return &SQLLiteMigrator{ - db: db, - migrationsTable: DefaultMigrationsTable, - migrations: migrations.All(), - }, nil -} - -// Migrate gets the current version from the database, the latest version from the migrations, -// and migrates up the the latest -func (m *SQLLiteMigrator) Migrate(ctx context.Context) error { - tx, err := m.db.Begin() - if err != nil { - return err - } - defer func() { - if err := tx.Rollback(); err != nil && !strings.Contains(err.Error(), "transaction has already been committed") { - logrus.WithError(err).Warnf("couldn't rollback") - } - }() - - version, err := m.version(ctx, tx) - if err != nil { - return err - } - - if err := tx.Commit(); err != nil { - return tx.Rollback() - } - return m.Up(ctx, m.migrations.From(version+1)) -} - -// Up runs a specific set of migrations. -func (m *SQLLiteMigrator) Up(ctx context.Context, migrations migrations.Migrations) error { - tx, err := m.db.Begin() - if err != nil { - return err - } - var commitErr error - defer func() { - if commitErr == nil { - return - } - logrus.WithError(commitErr).Warningf("tx commit failed") - if err := tx.Rollback(); err != nil { - logrus.WithError(err).Warningf("couldn't rollback after failed commit") - } - }() - - if err := m.ensureMigrationTable(ctx, tx); err != nil { - return err - } - - for _, migration := range migrations { - current_version, err := m.version(ctx, tx) - if err != nil { - return err - } - - if migration.Id != current_version+1 { - return fmt.Errorf("migration applied out of order") - } - - if err := migration.Up(ctx, tx); err != nil { - return err - } - - if err := m.setVersion(ctx, tx, migration.Id); err != nil { - return err - } - } - commitErr = tx.Commit() - return commitErr -} - -func (m *SQLLiteMigrator) Down(ctx context.Context, migrations migrations.Migrations) error { - tx, err := m.db.Begin() - if err != nil { - return err - } - var commitErr error - defer func() { - if commitErr == nil { - return - } - logrus.WithError(commitErr).Warningf("tx commit failed") - if err := tx.Rollback(); err != nil { - logrus.WithError(err).Warningf("couldn't rollback after failed commit") - } - }() - if err := m.ensureMigrationTable(ctx, tx); err != nil { - return err - } - - for _, migration := range migrations { - current_version, err := m.version(ctx, tx) - if err != nil { - return err - } - - if migration.Id != current_version { - return fmt.Errorf("migration applied out of order") - } - - if err := migration.Down(ctx, tx); err != nil { - return err - } - - if err := m.setVersion(ctx, tx, migration.Id-1); err != nil { - return err - } - } - commitErr = tx.Commit() - return commitErr -} - -func (m *SQLLiteMigrator) ensureMigrationTable(ctx context.Context, tx *sql.Tx) error { - sql := fmt.Sprintf(` - CREATE TABLE IF NOT EXISTS %s ( - version bigint NOT NULL, - timestamp DATETIME DEFAULT CURRENT_TIMESTAMP - ); - `, m.migrationsTable) - _, err := tx.ExecContext(ctx, sql) - return err -} - -func (m *SQLLiteMigrator) tableExists(tx *sql.Tx, table string) (bool, error) { - query := `SELECT count(*) - FROM sqlite_master - WHERE name = ?` - row := tx.QueryRow(query, table) - - var count int - err := row.Scan(&count) - if err != nil { - return false, err - } - - exists := count > 0 - return exists, nil -} - -func (m *SQLLiteMigrator) version(ctx context.Context, tx *sql.Tx) (version int, err error) { - tableExists, err := m.tableExists(tx, m.migrationsTable) - if err != nil { - return NilVersion, err - } - if !tableExists { - return NilVersion, nil - } - - query := `SELECT version FROM ` + m.migrationsTable + ` LIMIT 1` - err = tx.QueryRowContext(ctx, query).Scan(&version) - switch { - case err == sql.ErrNoRows: - return NilVersion, nil - case err != nil: - return NilVersion, err - default: - return version, nil - } -} - -func (m *SQLLiteMigrator) setVersion(ctx context.Context, tx *sql.Tx, version int) error { - if err := m.ensureMigrationTable(ctx, tx); err != nil { - return err - } - _, err := tx.ExecContext(ctx, "DELETE FROM "+m.migrationsTable) - if err != nil { - return err - } - _, err = tx.ExecContext(ctx, "INSERT INTO "+m.migrationsTable+"(version) values(?)", version) - return err -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/query.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/query.go deleted file mode 100644 index 7e35f333a..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/query.go +++ /dev/null @@ -1,924 +0,0 @@ -package sqlite - -import ( - "context" - "database/sql" - "fmt" - - _ "github.com/mattn/go-sqlite3" - - "github.com/operator-framework/operator-registry/pkg/api" - "github.com/operator-framework/operator-registry/pkg/registry" -) - -type SQLQuerier struct { - db *sql.DB -} - -var _ registry.Query = &SQLQuerier{} - -func NewSQLLiteQuerier(dbFilename string) (*SQLQuerier, error) { - db, err := sql.Open("sqlite3", "file:"+dbFilename+"?immutable=true") - if err != nil { - return nil, err - } - - return &SQLQuerier{db}, nil -} - -func NewSQLLiteQuerierFromDb(db *sql.DB) *SQLQuerier { - return &SQLQuerier{db} -} - -func (s *SQLQuerier) ListTables(ctx context.Context) ([]string, error) { - query := "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;" - rows, err := s.db.QueryContext(ctx, query) - if err != nil { - return nil, err - } - defer rows.Close() - - tables := []string{} - for rows.Next() { - var tableName sql.NullString - if err := rows.Scan(&tableName); err != nil { - return nil, err - } - if tableName.Valid { - tables = append(tables, tableName.String) - } - } - return tables, nil -} - -// ListPackages returns a list of package names as strings -func (s *SQLQuerier) ListPackages(ctx context.Context) ([]string, error) { - query := "SELECT DISTINCT name FROM package" - rows, err := s.db.QueryContext(ctx, query) - if err != nil { - return nil, err - } - defer rows.Close() - - packages := []string{} - for rows.Next() { - var pkgName sql.NullString - if err := rows.Scan(&pkgName); err != nil { - return nil, err - } - if pkgName.Valid { - packages = append(packages, pkgName.String) - } - } - return packages, nil -} - -func (s *SQLQuerier) GetPackage(ctx context.Context, name string) (*registry.PackageManifest, error) { - query := `SELECT DISTINCT package.name, default_channel, channel.name, channel.head_operatorbundle_name - FROM package INNER JOIN channel ON channel.package_name=package.name - WHERE package.name=?` - rows, err := s.db.QueryContext(ctx, query, name) - if err != nil { - return nil, err - } - defer rows.Close() - - var pkgName sql.NullString - var defaultChannel sql.NullString - var channelName sql.NullString - var bundleName sql.NullString - if !rows.Next() { - return nil, fmt.Errorf("package %s not found", name) - } - if err := rows.Scan(&pkgName, &defaultChannel, &channelName, &bundleName); err != nil { - return nil, err - } - pkg := ®istry.PackageManifest{ - PackageName: pkgName.String, - DefaultChannelName: defaultChannel.String, - Channels: []registry.PackageChannel{ - { - Name: channelName.String, - CurrentCSVName: bundleName.String, - }, - }, - } - - for rows.Next() { - if err := rows.Scan(&pkgName, &defaultChannel, &channelName, &bundleName); err != nil { - return nil, err - } - pkg.Channels = append(pkg.Channels, registry.PackageChannel{Name: channelName.String, CurrentCSVName: bundleName.String}) - } - return pkg, nil -} - -func (s *SQLQuerier) GetDefaultPackage(ctx context.Context, name string) (string, error) { - query := `SELECT default_channel - FROM package WHERE package.name=?` - rows, err := s.db.QueryContext(ctx, query, name) - if err != nil { - return "", err - } - defer rows.Close() - - var defaultChannel sql.NullString - if !rows.Next() { - return "", fmt.Errorf("package %s not found", name) - } - if err := rows.Scan(&defaultChannel); err != nil { - return "", err - } - - if !defaultChannel.Valid { - return "", fmt.Errorf("default channel not valid") - } - - return defaultChannel.String, nil -} - -func (s *SQLQuerier) GetChannelEntriesFromPackage(ctx context.Context, packageName string) ([]registry.ChannelEntryAnnotated, error) { - query := `SELECT channel_entry.package_name, channel_entry.channel_name, channel_entry.operatorbundle_name, op_bundle.version, op_bundle.bundlepath, replaces.operatorbundle_name, replacesbundle.version, replacesbundle.bundlepath - FROM channel_entry - LEFT JOIN channel_entry replaces ON channel_entry.replaces = replaces.entry_id - LEFT JOIN operatorbundle op_bundle ON channel_entry.operatorbundle_name = op_bundle.name - LEFT JOIN operatorbundle replacesbundle ON replaces.operatorbundle_name = replacesbundle.name - WHERE channel_entry.package_name = ?;` - - var entries []registry.ChannelEntryAnnotated - rows, err := s.db.QueryContext(ctx, query, packageName) - if err != nil { - return nil, err - } - defer rows.Close() - - var pkgName sql.NullString - var channelName sql.NullString - var bundleName sql.NullString - var replaces sql.NullString - var version sql.NullString - var bundlePath sql.NullString - var replacesVersion sql.NullString - var replacesBundlePath sql.NullString - - for rows.Next() { - if err := rows.Scan(&pkgName, &channelName, &bundleName, &version, &bundlePath, &replaces, &replacesVersion, &replacesBundlePath); err != nil { - return nil, err - } - - channelEntryNode := registry.ChannelEntryAnnotated{ - PackageName: pkgName.String, - ChannelName: channelName.String, - BundleName: bundleName.String, - Version: version.String, - BundlePath: bundlePath.String, - Replaces: replaces.String, - ReplacesVersion: replacesVersion.String, - ReplacesBundlePath: replacesBundlePath.String, - } - - entries = append(entries, channelEntryNode) - } - - return entries, nil -} - -func (s *SQLQuerier) GetBundle(ctx context.Context, pkgName, channelName, csvName string) (*api.Bundle, error) { - query := `SELECT DISTINCT channel_entry.entry_id, operatorbundle.name, operatorbundle.bundle, operatorbundle.bundlepath, operatorbundle.version, operatorbundle.skiprange - FROM operatorbundle INNER JOIN channel_entry ON operatorbundle.name=channel_entry.operatorbundle_name - WHERE channel_entry.package_name=? AND channel_entry.channel_name=? AND operatorbundle_name=? LIMIT 1` - rows, err := s.db.QueryContext(ctx, query, pkgName, channelName, csvName) - if err != nil { - return nil, err - } - defer rows.Close() - - if !rows.Next() { - return nil, fmt.Errorf("no entry found for %s %s %s", pkgName, channelName, csvName) - } - var entryId sql.NullInt64 - var name sql.NullString - var bundle sql.NullString - var bundlePath sql.NullString - var version sql.NullString - var skipRange sql.NullString - if err := rows.Scan(&entryId, &name, &bundle, &bundlePath, &version, &skipRange); err != nil { - return nil, err - } - - out := &api.Bundle{} - if bundle.Valid && bundle.String != "" { - out, err = registry.BundleStringToAPIBundle(bundle.String) - if err != nil { - return nil, err - } - } - out.CsvName = name.String - out.PackageName = pkgName - out.ChannelName = channelName - out.BundlePath = bundlePath.String - out.Version = version.String - out.SkipRange = skipRange.String - - provided, required, err := s.GetApisForEntry(ctx, entryId.Int64) - if err != nil { - return nil, err - } - out.ProvidedApis = provided - out.RequiredApis = required - - dependencies, err := s.GetDependenciesForBundle(ctx, name.String, version.String, bundlePath.String) - if err != nil { - return nil, err - } - - out.Dependencies = dependencies - - return out, nil -} - -func (s *SQLQuerier) GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (*api.Bundle, error) { - query := `SELECT DISTINCT channel_entry.entry_id, operatorbundle.name, operatorbundle.bundle, operatorbundle.bundlepath, operatorbundle.version, operatorbundle.skiprange FROM channel - INNER JOIN operatorbundle ON channel.head_operatorbundle_name=operatorbundle.name - INNER JOIN channel_entry ON (channel_entry.channel_name = channel.name and channel_entry.package_name=channel.package_name and channel_entry.operatorbundle_name=operatorbundle.name) - WHERE channel.package_name=? AND channel.name=? LIMIT 1` - rows, err := s.db.QueryContext(ctx, query, pkgName, channelName) - if err != nil { - return nil, err - } - defer rows.Close() - - if !rows.Next() { - return nil, fmt.Errorf("no entry found for %s %s", pkgName, channelName) - } - var entryId sql.NullInt64 - var name sql.NullString - var bundle sql.NullString - var bundlePath sql.NullString - var version sql.NullString - var skipRange sql.NullString - if err := rows.Scan(&entryId, &name, &bundle, &bundlePath, &version, &skipRange); err != nil { - return nil, err - } - - out := &api.Bundle{} - if bundle.Valid && bundle.String != "" { - out, err = registry.BundleStringToAPIBundle(bundle.String) - if err != nil { - return nil, err - } - } - out.CsvName = name.String - out.PackageName = pkgName - out.ChannelName = channelName - out.BundlePath = bundlePath.String - out.Version = version.String - out.SkipRange = skipRange.String - - provided, required, err := s.GetApisForEntry(ctx, entryId.Int64) - if err != nil { - return nil, err - } - out.ProvidedApis = provided - out.RequiredApis = required - - dependencies, err := s.GetDependenciesForBundle(ctx, name.String, version.String, bundlePath.String) - if err != nil { - return nil, err - } - - out.Dependencies = dependencies - - return out, nil -} - -func (s *SQLQuerier) GetChannelEntriesThatReplace(ctx context.Context, name string) (entries []*registry.ChannelEntry, err error) { - query := `SELECT DISTINCT channel_entry.package_name, channel_entry.channel_name, channel_entry.operatorbundle_name - FROM channel_entry - LEFT OUTER JOIN channel_entry replaces ON channel_entry.replaces = replaces.entry_id - WHERE replaces.operatorbundle_name = ?` - rows, err := s.db.QueryContext(ctx, query, name) - if err != nil { - return - } - defer rows.Close() - - entries = []*registry.ChannelEntry{} - - for rows.Next() { - var pkgNameSQL sql.NullString - var channelNameSQL sql.NullString - var bundleNameSQL sql.NullString - - if err = rows.Scan(&pkgNameSQL, &channelNameSQL, &bundleNameSQL); err != nil { - return - } - entries = append(entries, ®istry.ChannelEntry{ - PackageName: pkgNameSQL.String, - ChannelName: channelNameSQL.String, - BundleName: bundleNameSQL.String, - Replaces: name, - }) - } - if len(entries) == 0 { - err = fmt.Errorf("no channel entries found that replace %s", name) - return - } - return -} - -func (s *SQLQuerier) GetBundleThatReplaces(ctx context.Context, name, pkgName, channelName string) (*api.Bundle, error) { - query := `SELECT DISTINCT replaces.entry_id, operatorbundle.name, operatorbundle.bundle, operatorbundle.bundlepath, operatorbundle.version, operatorbundle.skiprange - FROM channel_entry - LEFT OUTER JOIN channel_entry replaces ON replaces.replaces = channel_entry.entry_id - INNER JOIN operatorbundle ON replaces.operatorbundle_name = operatorbundle.name - WHERE channel_entry.operatorbundle_name = ? AND channel_entry.package_name = ? AND channel_entry.channel_name = ? LIMIT 1` - rows, err := s.db.QueryContext(ctx, query, name, pkgName, channelName) - if err != nil { - return nil, err - } - defer rows.Close() - - if !rows.Next() { - return nil, fmt.Errorf("no entry found for %s %s", pkgName, channelName) - } - var entryId sql.NullInt64 - var outName sql.NullString - var bundle sql.NullString - var bundlePath sql.NullString - var version sql.NullString - var skipRange sql.NullString - if err := rows.Scan(&entryId, &outName, &bundle, &bundlePath, &version, &skipRange); err != nil { - return nil, err - } - - out := &api.Bundle{} - if bundle.Valid && bundle.String != "" { - out, err = registry.BundleStringToAPIBundle(bundle.String) - if err != nil { - return nil, err - } - } - out.CsvName = outName.String - out.PackageName = pkgName - out.ChannelName = channelName - out.BundlePath = bundlePath.String - out.Version = version.String - out.SkipRange = skipRange.String - - provided, required, err := s.GetApisForEntry(ctx, entryId.Int64) - if err != nil { - return nil, err - } - out.ProvidedApis = provided - out.RequiredApis = required - - dependencies, err := s.GetDependenciesForBundle(ctx, outName.String, version.String, bundlePath.String) - if err != nil { - return nil, err - } - - out.Dependencies = dependencies - - return out, nil -} - -func (s *SQLQuerier) GetChannelEntriesThatProvide(ctx context.Context, group, version, kind string) (entries []*registry.ChannelEntry, err error) { - query := `SELECT DISTINCT channel_entry.package_name, channel_entry.channel_name, channel_entry.operatorbundle_name, replaces.operatorbundle_name - FROM channel_entry - INNER JOIN api_provider ON channel_entry.operatorbundle_name = api_provider.operatorbundle_name - LEFT OUTER JOIN channel_entry replaces ON channel_entry.replaces = replaces.entry_id - WHERE api_provider.group_name = ? AND api_provider.version = ? AND api_provider.kind = ?` - - rows, err := s.db.QueryContext(ctx, query, group, version, kind) - if err != nil { - return - } - defer rows.Close() - - entries = []*registry.ChannelEntry{} - - for rows.Next() { - var pkgNameSQL sql.NullString - var channelNameSQL sql.NullString - var bundleNameSQL sql.NullString - var replacesSQL sql.NullString - if err = rows.Scan(&pkgNameSQL, &channelNameSQL, &bundleNameSQL, &replacesSQL); err != nil { - return - } - - entries = append(entries, ®istry.ChannelEntry{ - PackageName: pkgNameSQL.String, - ChannelName: channelNameSQL.String, - BundleName: bundleNameSQL.String, - Replaces: replacesSQL.String, - }) - } - if len(entries) == 0 { - err = fmt.Errorf("no channel entries found that provide %s %s %s", group, version, kind) - return - } - return -} - -// Get latest channel entries that provide an api -func (s *SQLQuerier) GetLatestChannelEntriesThatProvide(ctx context.Context, group, version, kind string) (entries []*registry.ChannelEntry, err error) { - query := `SELECT DISTINCT channel_entry.package_name, channel_entry.channel_name, channel_entry.operatorbundle_name, replaces.operatorbundle_name, MIN(channel_entry.depth) - FROM channel_entry - INNER JOIN api_provider ON channel_entry.operatorbundle_name = api_provider.operatorbundle_name - LEFT OUTER JOIN channel_entry replaces ON channel_entry.replaces = replaces.entry_id - WHERE api_provider.group_name = ? AND api_provider.version = ? AND api_provider.kind = ? - GROUP BY channel_entry.package_name, channel_entry.channel_name` - rows, err := s.db.QueryContext(ctx, query, group, version, kind) - if err != nil { - return nil, err - } - defer rows.Close() - - entries = []*registry.ChannelEntry{} - - for rows.Next() { - var pkgNameSQL sql.NullString - var channelNameSQL sql.NullString - var bundleNameSQL sql.NullString - var replacesSQL sql.NullString - var min_depth sql.NullInt64 - if err = rows.Scan(&pkgNameSQL, &channelNameSQL, &bundleNameSQL, &replacesSQL, &min_depth); err != nil { - return nil, err - } - - entries = append(entries, ®istry.ChannelEntry{ - PackageName: pkgNameSQL.String, - ChannelName: channelNameSQL.String, - BundleName: bundleNameSQL.String, - Replaces: replacesSQL.String, - }) - } - if len(entries) == 0 { - err = fmt.Errorf("no channel entries found that provide %s %s %s", group, version, kind) - return nil, err - } - return entries, nil -} - -// Get the the latest bundle that provides the API in a default channel, error unless there is ONLY one -func (s *SQLQuerier) GetBundleThatProvides(ctx context.Context, group, apiVersion, kind string) (*api.Bundle, error) { - query := `SELECT DISTINCT channel_entry.entry_id, operatorbundle.bundle, operatorbundle.bundlepath, MIN(channel_entry.depth), channel_entry.operatorbundle_name, channel_entry.package_name, channel_entry.channel_name, channel_entry.replaces, operatorbundle.version, operatorbundle.skiprange - FROM channel_entry - INNER JOIN operatorbundle ON operatorbundle.name = channel_entry.operatorbundle_name - INNER JOIN api_provider ON channel_entry.operatorbundle_name = api_provider.operatorbundle_name - INNER JOIN package ON package.name = channel_entry.package_name - WHERE api_provider.group_name = ? AND api_provider.version = ? AND api_provider.kind = ? AND package.default_channel = channel_entry.channel_name - GROUP BY channel_entry.package_name, channel_entry.channel_name` - - rows, err := s.db.QueryContext(ctx, query, group, apiVersion, kind) - if err != nil { - return nil, err - } - defer rows.Close() - - if !rows.Next() { - return nil, fmt.Errorf("no entry found that provides %s %s %s", group, apiVersion, kind) - } - var entryId sql.NullInt64 - var bundle sql.NullString - var bundlePath sql.NullString - var min_depth sql.NullInt64 - var bundleName sql.NullString - var pkgName sql.NullString - var channelName sql.NullString - var replaces sql.NullString - var version sql.NullString - var skipRange sql.NullString - if err := rows.Scan(&entryId, &bundle, &bundlePath, &min_depth, &bundleName, &pkgName, &channelName, &replaces, &version, &skipRange); err != nil { - return nil, err - } - - if !bundle.Valid { - return nil, fmt.Errorf("no entry found that provides %s %s %s", group, apiVersion, kind) - } - - out := &api.Bundle{} - if bundle.Valid && bundle.String != "" { - out, err = registry.BundleStringToAPIBundle(bundle.String) - if err != nil { - return nil, err - } - } - out.CsvName = bundleName.String - out.PackageName = pkgName.String - out.ChannelName = channelName.String - out.BundlePath = bundlePath.String - out.Version = version.String - out.SkipRange = skipRange.String - - provided, required, err := s.GetApisForEntry(ctx, entryId.Int64) - if err != nil { - return nil, err - } - out.ProvidedApis = provided - out.RequiredApis = required - - dependencies, err := s.GetDependenciesForBundle(ctx, bundleName.String, version.String, bundlePath.String) - if err != nil { - return nil, err - } - - out.Dependencies = dependencies - - return out, nil -} - -func (s *SQLQuerier) ListImages(ctx context.Context) ([]string, error) { - query := "SELECT DISTINCT image FROM related_image" - rows, err := s.db.QueryContext(ctx, query) - if err != nil { - return nil, err - } - defer rows.Close() - - images := []string{} - for rows.Next() { - var imgName sql.NullString - if err := rows.Scan(&imgName); err != nil { - return nil, err - } - if imgName.Valid { - images = append(images, imgName.String) - } - } - return images, nil -} - -func (s *SQLQuerier) GetImagesForBundle(ctx context.Context, csvName string) ([]string, error) { - query := "SELECT DISTINCT image FROM related_image WHERE operatorbundle_name=?" - rows, err := s.db.QueryContext(ctx, query, csvName) - if err != nil { - return nil, err - } - defer rows.Close() - images := []string{} - for rows.Next() { - var imgName sql.NullString - if err := rows.Scan(&imgName); err != nil { - return nil, err - } - if imgName.Valid { - images = append(images, imgName.String) - } - } - return images, nil -} - -func (s *SQLQuerier) GetApisForEntry(ctx context.Context, entryID int64) (provided []*api.GroupVersionKind, required []*api.GroupVersionKind, err error) { - providedQuery := `SELECT DISTINCT api.group_name, api.version, api.kind, api.plural FROM api - INNER JOIN channel_entry ON channel_entry.operatorbundle_name = api_provider.operatorbundle_name - INNER JOIN operatorbundle ON operatorbundle.name=channel_entry.operatorbundle_name - INNER JOIN api_provider ON (api.group_name=api_provider.group_name AND api.version=api_provider.version AND api.kind=api_provider.kind AND operatorbundle.name=api_provider.operatorbundle_name) - WHERE channel_entry.entry_id=?` - - providedRows, err := s.db.QueryContext(ctx, providedQuery, entryID) - if err != nil { - return nil, nil, err - } - - provided = []*api.GroupVersionKind{} - for providedRows.Next() { - var groupName sql.NullString - var versionName sql.NullString - var kindName sql.NullString - var pluralName sql.NullString - - if err := providedRows.Scan(&groupName, &versionName, &kindName, &pluralName); err != nil { - return nil, nil, err - } - if !groupName.Valid || !versionName.Valid || !kindName.Valid || !pluralName.Valid { - return nil, nil, err - } - provided = append(provided, &api.GroupVersionKind{ - Group: groupName.String, - Version: versionName.String, - Kind: kindName.String, - Plural: pluralName.String, - }) - } - if err := providedRows.Close(); err != nil { - return nil, nil, err - } - - requiredQuery := `SELECT DISTINCT api.group_name, api.version, api.kind, api.plural FROM api - INNER JOIN channel_entry ON channel_entry.operatorbundle_name = api_requirer.operatorbundle_name - INNER JOIN operatorbundle ON operatorbundle.name=channel_entry.operatorbundle_name - INNER JOIN api_requirer ON (api.group_name=api_requirer.group_name AND api.version=api_requirer.version AND api.kind=api_requirer.kind AND operatorbundle.name=api_requirer.operatorbundle_name) - WHERE channel_entry.entry_id=?` - - requiredRows, err := s.db.QueryContext(ctx, requiredQuery, entryID) - if err != nil { - return nil, nil, err - } - required = []*api.GroupVersionKind{} - for requiredRows.Next() { - var groupName sql.NullString - var versionName sql.NullString - var kindName sql.NullString - var pluralName sql.NullString - - if err := requiredRows.Scan(&groupName, &versionName, &kindName, &pluralName); err != nil { - return nil, nil, err - } - if !groupName.Valid || !versionName.Valid || !kindName.Valid || !pluralName.Valid { - return nil, nil, err - } - required = append(required, &api.GroupVersionKind{ - Group: groupName.String, - Version: versionName.String, - Kind: kindName.String, - Plural: pluralName.String, - }) - } - if err := requiredRows.Close(); err != nil { - return nil, nil, err - } - - return -} - -func (s *SQLQuerier) GetBundleVersion(ctx context.Context, image string) (string, error) { - query := `SELECT version FROM operatorbundle WHERE bundlepath=? LIMIT 1` - rows, err := s.db.QueryContext(ctx, query, image) - if err != nil { - return "", err - } - defer rows.Close() - - var version sql.NullString - if rows.Next() { - if err := rows.Scan(&version); err != nil { - return "", err - } - } - if version.Valid { - return version.String, nil - } - return "", fmt.Errorf("bundle %s not found", image) -} - -func (s *SQLQuerier) GetBundlePathsForPackage(ctx context.Context, pkgName string) ([]string, error) { - query := `SELECT DISTINCT bundlepath FROM operatorbundle - INNER JOIN channel_entry ON operatorbundle.name=channel_entry.operatorbundle_name - WHERE channel_entry.package_name=?` - rows, err := s.db.QueryContext(ctx, query, pkgName) - if err != nil { - return nil, err - } - defer rows.Close() - images := []string{} - for rows.Next() { - var imgName sql.NullString - if err := rows.Scan(&imgName); err != nil { - return nil, err - } - if imgName.Valid && imgName.String != "" { - images = append(images, imgName.String) - } else { - return nil, fmt.Errorf("Index malformed: cannot find paths to bundle images") - } - } - return images, nil -} - -func (s *SQLQuerier) GetBundlesForPackage(ctx context.Context, pkgName string) (map[registry.BundleKey]struct{}, error) { - query := `SELECT DISTINCT name, bundlepath, version FROM operatorbundle - INNER JOIN channel_entry ON operatorbundle.name=channel_entry.operatorbundle_name - WHERE channel_entry.package_name=?` - rows, err := s.db.QueryContext(ctx, query, pkgName) - if err != nil { - return nil, err - } - defer rows.Close() - bundles := map[registry.BundleKey]struct{}{} - for rows.Next() { - var name sql.NullString - var bundlepath sql.NullString - var version sql.NullString - if err := rows.Scan(&name, &bundlepath, &version); err != nil { - return nil, err - } - key := registry.BundleKey{} - if name.Valid && name.String != "" { - key.CsvName = name.String - } - if bundlepath.Valid && bundlepath.String != "" { - key.BundlePath = bundlepath.String - } - if version.Valid && version.String != "" { - key.Version = version.String - } - if key.IsEmpty() { - return nil, fmt.Errorf("Index malformed: cannot find identifier for bundle in package %s", pkgName) - } - bundles[key] = struct{}{} - } - return bundles, nil -} - -func (s *SQLQuerier) GetDefaultChannelForPackage(ctx context.Context, pkgName string) (string, error) { - query := `SELECT DISTINCT default_channel FROM package WHERE name=? LIMIT 1` - rows, err := s.db.QueryContext(ctx, query, pkgName) - if err != nil { - return "", err - } - defer rows.Close() - - var defaultChannel sql.NullString - if rows.Next() { - if err := rows.Scan(&defaultChannel); err != nil { - return "", err - } - } - if defaultChannel.Valid { - return defaultChannel.String, nil - } - return "", nil -} - -func (s *SQLQuerier) ListChannels(ctx context.Context, pkgName string) ([]string, error) { - query := `SELECT DISTINCT name FROM channel WHERE channel.package_name=?` - rows, err := s.db.QueryContext(ctx, query, pkgName) - if err != nil { - return nil, err - } - defer rows.Close() - channels := []string{} - for rows.Next() { - var chName sql.NullString - if err := rows.Scan(&chName); err != nil { - return nil, err - } - if chName.Valid { - channels = append(channels, chName.String) - } - } - return channels, nil -} - -func (s *SQLQuerier) GetCurrentCSVNameForChannel(ctx context.Context, pkgName, channel string) (string, error) { - query := `SELECT DISTINCT head_operatorbundle_name FROM channel WHERE channel.package_name=? AND channel.name=?` - rows, err := s.db.QueryContext(ctx, query, pkgName, channel) - if err != nil { - return "", err - } - defer rows.Close() - var csvName sql.NullString - if rows.Next() { - if err := rows.Scan(&csvName); err != nil { - return "", err - } - } - if csvName.Valid { - return csvName.String, nil - } - return "", nil -} - -func (s *SQLQuerier) ListBundles(ctx context.Context) (bundles []*api.Bundle, err error) { - query := `SELECT DISTINCT channel_entry.entry_id, operatorbundle.bundle, operatorbundle.bundlepath, - channel_entry.operatorbundle_name, channel_entry.package_name, channel_entry.channel_name, channel_entry.replaces, - operatorbundle.version, operatorbundle.skiprange, - dependencies.type, dependencies.value - FROM channel_entry - INNER JOIN operatorbundle ON operatorbundle.name = channel_entry.operatorbundle_name - LEFT OUTER JOIN dependencies ON dependencies.operatorbundle_name = channel_entry.operatorbundle_name - INNER JOIN package ON package.name = channel_entry.package_name` - - rows, err := s.db.QueryContext(ctx, query) - if err != nil { - return nil, err - } - defer rows.Close() - - bundles = []*api.Bundle{} - bundlesMap := map[string]*api.Bundle{} - for rows.Next() { - var entryID sql.NullInt64 - var bundle sql.NullString - var bundlePath sql.NullString - var bundleName sql.NullString - var pkgName sql.NullString - var channelName sql.NullString - var replaces sql.NullString - var version sql.NullString - var skipRange sql.NullString - var depType sql.NullString - var depValue sql.NullString - if err := rows.Scan(&entryID, &bundle, &bundlePath, &bundleName, &pkgName, &channelName, &replaces, &version, &skipRange, &depType, &depValue); err != nil { - return nil, err - } - - bundleKey := fmt.Sprintf("%s/%s/%s", bundleName.String, version.String, bundlePath.String) - bundleItem, ok := bundlesMap[bundleKey] - if ok { - // Create new dependency object - dep := &api.Dependency{} - if !depType.Valid || !depValue.Valid { - continue - } - dep.Type = depType.String - dep.Value = depValue.String - - // Add new dependency to the existing list - existingDeps := bundleItem.Dependencies - existingDeps = append(existingDeps, dep) - bundleItem.Dependencies = existingDeps - } else { - // Create new bundle - out := &api.Bundle{} - if bundle.Valid && bundle.String != "" { - out, err = registry.BundleStringToAPIBundle(bundle.String) - if err != nil { - return nil, err - } - } - - out.CsvName = bundleName.String - out.PackageName = pkgName.String - out.ChannelName = channelName.String - out.BundlePath = bundlePath.String - out.Version = version.String - out.SkipRange = skipRange.String - - provided, required, err := s.GetApisForEntry(ctx, entryID.Int64) - if err != nil { - return nil, err - } - out.ProvidedApis = provided - out.RequiredApis = required - - // Create new dependency and dependency list - dep := &api.Dependency{} - dependencies := []*api.Dependency{} - dep.Type = depType.String - dep.Value = depValue.String - dependencies = append(dependencies, dep) - out.Dependencies = dependencies - - bundlesMap[bundleKey] = out - } - } - - for _, v := range bundlesMap { - if len(v.Dependencies) > 1 { - newDeps := unique(v.Dependencies) - v.Dependencies = newDeps - } - bundles = append(bundles, v) - } - - return -} - -func unique(deps []*api.Dependency) []*api.Dependency { - keys := make(map[string]bool) - list := []*api.Dependency{} - for _, entry := range deps { - depKey := fmt.Sprintf("%s/%s", entry.Type, entry.Value) - if _, value := keys[depKey]; !value { - keys[depKey] = true - list = append(list, entry) - } - } - return list -} - -func (s *SQLQuerier) GetDependenciesForBundle(ctx context.Context, name, version, path string) (dependencies []*api.Dependency, err error) { - depQuery := `SELECT DISTINCT dependencies.type, dependencies.value FROM dependencies - WHERE dependencies.operatorbundle_name=? - AND (dependencies.operatorbundle_version=? OR dependencies.operatorbundle_version is NULL) - AND (dependencies.operatorbundle_path=? OR dependencies.operatorbundle_path is NULL)` - - rows, err := s.db.QueryContext(ctx, depQuery, name, version, path) - if err != nil { - return nil, err - } - dependencies = []*api.Dependency{} - for rows.Next() { - var typeName sql.NullString - var value sql.NullString - - if err := rows.Scan(&typeName, &value); err != nil { - return nil, err - } - if !typeName.Valid || !value.Valid { - return nil, err - } - dependencies = append(dependencies, &api.Dependency{ - Type: typeName.String, - Value: value.String, - }) - } - if err := rows.Close(); err != nil { - return nil, err - } - - return -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/remove.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/remove.go deleted file mode 100644 index 7d2cfdd49..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/remove.go +++ /dev/null @@ -1,67 +0,0 @@ -package sqlite - -import ( - "fmt" - "strings" - - "github.com/sirupsen/logrus" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - - "github.com/operator-framework/operator-registry/pkg/registry" -) - -type SQLRemover interface { - Remove() error -} - -// PackageRemover removes a package from the database -type PackageRemover struct { - store registry.Load - packages string -} - -var _ SQLRemover = &PackageRemover{} - -func NewSQLRemoverForPackages(store registry.Load, packages string) *PackageRemover { - return &PackageRemover{ - store: store, - packages: packages, - } -} - -func (d *PackageRemover) Remove() error { - log := logrus.WithField("pkg", d.packages) - - log.Info("deleting packages") - - var errs []error - packages := sanitizePackageList(strings.Split(d.packages, ",")) - log.Info("input has been sanitized") - log.Infof("packages: %s", packages) - - for _, pkg := range packages { - if err := d.store.RemovePackage(pkg); err != nil { - errs = append(errs, fmt.Errorf("error removing operator package %s: %s", pkg, err)) - } - } - - return utilerrors.NewAggregate(errs) -} - -// sanitizePackageList sanitizes the set of package(s) specified. It removes -// duplicates and ignores empty string. -func sanitizePackageList(in []string) []string { - out := make([]string, 0) - - inMap := map[string]bool{} - for _, item := range in { - if _, ok := inMap[item]; ok || item == "" { - continue - } - - inMap[item] = true - out = append(out, item) - } - - return out -} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/test.txt b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/test.txt deleted file mode 100644 index f64226b0f..000000000 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/test.txt +++ /dev/null @@ -1 +0,0 @@ -expected:[]registry.OperatorBundle{registry.OperatorBundle{BundlePath: "", Version: semver.Version{Major: 0x0, Minor: 0x9, Patch: 0x2, Pre: []semver.PRVersion(nil), Build: []string(nil)}, CsvName: "etcdoperator.v0.9.2", ReplacesBundles: []registry.OperatorBundle{}, Replaces: []registry.BundleRef{registry.BundleRef{BundlePath: "", Version: semver.Version{Major: 0x0, Minor: 0x9, Patch: 0x0, Pre: []semver.PRVersion(nil), Build: []string(nil)}, CsvName: "etcdoperator.v0.9.0"}}}, registry.OperatorBundle{BundlePath: "", Version: semver.Version{Major: 0x0, Minor: 0x0, Patch: 0x0, Pre: []semver.PRVersion(nil), Build: []string(nil)}, CsvName: "etcdoperator.v0.9.1", ReplacesBundles: []registry.OperatorBundle{}, Replaces: []registry.BundleRef{}}, registry.OperatorBundle{BundlePath: "", Version: semver.Version{Major: 0x0, Minor: 0x9, Patch: 0x0, Pre: []semver.PRVersion(nil), Build: []string(nil)}, CsvName: "etcdoperator.v0.9.0", ReplacesBundles: []registry.OperatorBundle{}, Replaces: []registry.BundleRef{registry.BundleRef{BundlePath: "", Version: semver.Version{Major: 0x0, Minor: 0x6, Patch: 0x1, Pre: []semver.PRVersion(nil), Build: []string(nil)}, CsvName: "etcdoperator.v0.6.1"}}}, registry.OperatorBundle{BundlePath: "", Version: semver.Version{Major: 0x0, Minor: 0x6, Patch: 0x1, Pre: []semver.PRVersion(nil), Build: []string(nil)}, CsvName: "etcdoperator.v0.6.1", ReplacesBundles: []registry.OperatorBundle{}, Replaces: []registry.BundleRef{}}} \ No newline at end of file