From ab55bc5e86b151b281f9656eda3591ff9a859125 Mon Sep 17 00:00:00 2001 From: Ruslan Aliev Date: Sun, 30 May 2021 17:01:31 -0500 Subject: [PATCH] Move clustetctl to KRM Change-Id: I79ccb7b7c92f27cf6fdaaa540d86db80a0a62b41 Signed-off-by: Ruslan Aliev Closes: #568 --- Makefile | 12 +- go.mod | 3 - go.sum | 122 +------ krm-functions/clusterctl/Dockerfile | 44 +++ krm-functions/clusterctl/Makefile | 78 +++++ krm-functions/clusterctl/README.md | 22 ++ krm-functions/clusterctl/certs/README.md | 6 + krm-functions/clusterctl/image/go.mod | 5 + krm-functions/clusterctl/image/go.sum | 225 ++++++++++++ krm-functions/clusterctl/image/main.go | 97 ++++++ .../local-resource/example-use.yaml | 46 +++ krm-functions/kubeval-validator/Makefile | 2 +- .../cabpk/v0.3.7/data/kustomization.yaml | 2 + .../function/cabpk/v0.3.7/data/metadata.yaml | 12 +- .../function/cabpk/v0.3.7/kustomization.yaml | 1 + .../cacpk/v0.3.7/data/kustomization.yaml | 2 + .../function/cacpk/v0.3.7/data/metadata.yaml | 11 + .../function/cacpk/v0.3.7/kustomization.yaml | 1 + .../capi/v0.3.7/data/kustomization.yaml | 2 + .../function/capi/v0.3.7/data/metadata.yaml | 11 + .../function/capi/v0.3.7/kustomization.yaml | 1 + manifests/function/clusterctl/clusterctl.yaml | 25 +- manifests/phases/executors.yaml | 11 + pkg/api/v1alpha1/clusterctl_types.go | 89 ++--- pkg/api/v1alpha1/clusterctl_types_test.go | 76 ---- pkg/api/v1alpha1/zz_generated.deepcopy.go | 86 +++-- pkg/clusterctl/client/client.go | 166 --------- pkg/clusterctl/client/client_test.go | 174 ---------- pkg/clusterctl/client/errors.go | 38 -- pkg/clusterctl/client/factory.go | 105 ------ pkg/clusterctl/client/factory_test.go | 299 ---------------- pkg/clusterctl/client/move.go | 54 --- .../testdata/executor_init/kubeconfig.yaml | 24 -- .../testdata/executor_init/kustomization.yaml | 2 - .../testdata/executor_move/kubeconfig.yaml | 24 -- .../testdata/executor_move/kustomization.yaml | 2 - .../infrastructure/v0.3.1/kustomization.yaml | 2 - .../capi/infrastructure/v0.3.1/version.yaml | 14 - .../infrastructure/v0.3.2/kustomization.yaml | 2 - pkg/clusterctl/client/testdata/metadata.yaml | 2 - .../implementations/components_client.go | 41 --- pkg/clusterctl/implementations/errors.go | 55 --- pkg/clusterctl/implementations/reader.go | 155 --------- pkg/clusterctl/implementations/reader_test.go | 319 ----------------- pkg/clusterctl/implementations/repository.go | 139 -------- .../implementations/repository_client.go | 45 --- .../implementations/repository_client_test.go | 214 ------------ .../implementations/repository_test.go | 302 ---------------- .../testdata/functions/1/kustomization.yaml | 2 - .../testdata/functions/1/version.yaml | 7 - .../testdata/functions/2/kustomization.yaml | 2 - .../testdata/functions/3/kustomization.yaml | 2 - .../testdata/functions/3/version.yaml | 7 - .../testdata/functions/4/dnsmasq.conf | 1 - .../testdata/functions/4/kustomization.yaml | 12 - .../testdata/functions/4/resources.yaml | 17 - .../testdata/functions/5/azure-resources.yaml | 29 -- .../testdata/functions/5/kustomization.yaml | 3 - pkg/document/constants.go | 9 + pkg/document/selectors.go | 8 + pkg/k8s/kubeconfig/builder.go | 3 +- pkg/k8s/kubeconfig/kubeconfig.go | 3 +- pkg/k8s/kubeconfig/kubeconfig_test.go | 13 +- pkg/phase/executors/clusterctl.go | 320 +++++++++++------ pkg/phase/executors/clusterctl_test.go | 326 +++++++++++++++--- pkg/phase/executors/common.go | 0 pkg/phase/executors/common_test.go | 8 + pkg/phase/executors/errors/errors.go | 0 .../functions/capi/v0.3.2/kustomization.yaml | 3 + .../functions/capi/v0.3.2/metadata.yaml | 11 + .../v0.3.2/no-metadata}/kustomization.yaml | 0 .../functions/capi}/v0.3.2/version.yaml | 0 pkg/phase/ifc/executor.go | 2 + testutil/clusterctl/client.go | 68 ---- 74 files changed, 1241 insertions(+), 2785 deletions(-) create mode 100644 krm-functions/clusterctl/Dockerfile create mode 100644 krm-functions/clusterctl/Makefile create mode 100644 krm-functions/clusterctl/README.md create mode 100644 krm-functions/clusterctl/certs/README.md create mode 100644 krm-functions/clusterctl/image/go.mod create mode 100644 krm-functions/clusterctl/image/go.sum create mode 100644 krm-functions/clusterctl/image/main.go create mode 100755 krm-functions/clusterctl/local-resource/example-use.yaml create mode 100644 manifests/function/cabpk/v0.3.7/data/kustomization.yaml rename pkg/clusterctl/implementations/testdata/functions/2/version.yaml => manifests/function/cabpk/v0.3.7/data/metadata.yaml (52%) create mode 100644 manifests/function/cacpk/v0.3.7/data/kustomization.yaml create mode 100644 manifests/function/cacpk/v0.3.7/data/metadata.yaml create mode 100644 manifests/function/capi/v0.3.7/data/kustomization.yaml create mode 100644 manifests/function/capi/v0.3.7/data/metadata.yaml delete mode 100644 pkg/api/v1alpha1/clusterctl_types_test.go delete mode 100644 pkg/clusterctl/client/client.go delete mode 100644 pkg/clusterctl/client/client_test.go delete mode 100644 pkg/clusterctl/client/errors.go delete mode 100644 pkg/clusterctl/client/factory.go delete mode 100644 pkg/clusterctl/client/factory_test.go delete mode 100644 pkg/clusterctl/client/move.go delete mode 100644 pkg/clusterctl/client/testdata/executor_init/kubeconfig.yaml delete mode 100644 pkg/clusterctl/client/testdata/executor_init/kustomization.yaml delete mode 100644 pkg/clusterctl/client/testdata/executor_move/kubeconfig.yaml delete mode 100644 pkg/clusterctl/client/testdata/executor_move/kustomization.yaml delete mode 100644 pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.1/kustomization.yaml delete mode 100644 pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.1/version.yaml delete mode 100644 pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.2/kustomization.yaml delete mode 100644 pkg/clusterctl/client/testdata/metadata.yaml delete mode 100644 pkg/clusterctl/implementations/components_client.go delete mode 100644 pkg/clusterctl/implementations/errors.go delete mode 100644 pkg/clusterctl/implementations/reader.go delete mode 100644 pkg/clusterctl/implementations/reader_test.go delete mode 100644 pkg/clusterctl/implementations/repository.go delete mode 100644 pkg/clusterctl/implementations/repository_client.go delete mode 100644 pkg/clusterctl/implementations/repository_client_test.go delete mode 100644 pkg/clusterctl/implementations/repository_test.go delete mode 100644 pkg/clusterctl/implementations/testdata/functions/1/kustomization.yaml delete mode 100644 pkg/clusterctl/implementations/testdata/functions/1/version.yaml delete mode 100644 pkg/clusterctl/implementations/testdata/functions/2/kustomization.yaml delete mode 100644 pkg/clusterctl/implementations/testdata/functions/3/kustomization.yaml delete mode 100644 pkg/clusterctl/implementations/testdata/functions/3/version.yaml delete mode 100644 pkg/clusterctl/implementations/testdata/functions/4/dnsmasq.conf delete mode 100644 pkg/clusterctl/implementations/testdata/functions/4/kustomization.yaml delete mode 100644 pkg/clusterctl/implementations/testdata/functions/4/resources.yaml delete mode 100644 pkg/clusterctl/implementations/testdata/functions/5/azure-resources.yaml delete mode 100644 pkg/clusterctl/implementations/testdata/functions/5/kustomization.yaml mode change 100755 => 100644 pkg/phase/executors/clusterctl.go mode change 100755 => 100644 pkg/phase/executors/clusterctl_test.go mode change 100755 => 100644 pkg/phase/executors/common.go mode change 100755 => 100644 pkg/phase/executors/common_test.go mode change 100755 => 100644 pkg/phase/executors/errors/errors.go create mode 100644 pkg/phase/executors/testdata/functions/capi/v0.3.2/kustomization.yaml create mode 100644 pkg/phase/executors/testdata/functions/capi/v0.3.2/metadata.yaml rename pkg/{clusterctl/client/testdata/executor_init_empty => phase/executors/testdata/functions/capi/v0.3.2/no-metadata}/kustomization.yaml (100%) rename pkg/{clusterctl/client/testdata/functions/capi/infrastructure => phase/executors/testdata/functions/capi}/v0.3.2/version.yaml (100%) delete mode 100644 testutil/clusterctl/client.go diff --git a/Makefile b/Makefile index d5e22c07e..671bd4c12 100644 --- a/Makefile +++ b/Makefile @@ -165,7 +165,7 @@ golint: .PHONY: images images: docker-image -images: docker-image-kubeval-validator docker-image-cloud-init docker-image-replacement-transformer docker-image-templater docker-image-toolbox +images: docker-image-clusterctl docker-image-kubeval-validator docker-image-cloud-init docker-image-replacement-transformer docker-image-templater docker-image-toolbox .PHONY: docker-image docker-image: @@ -208,6 +208,16 @@ ifeq ($(PUBLISH), true) @docker push $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/cloud-init:$(DOCKER_IMAGE_TAG) endif +.PHONY: docker-image-clusterctl +docker-image-clusterctl: + @docker build $(PLUGINS_DIR)/clusterctl $(DOCKER_CMD_FLAGS) \ + --label $(LABEL) \ + --target $(DOCKER_TARGET_STAGE) \ + --tag $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/clusterctl:$(DOCKER_IMAGE_TAG) +ifeq ($(PUBLISH), true) + @docker push $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/clusterctl:$(DOCKER_IMAGE_TAG) +endif + .PHONY: docker-image-kubeval-validator docker-image-kubeval-validator: @docker build $(PLUGINS_DIR)/kubeval-validator $(DOCKER_CMD_FLAGS) \ diff --git a/go.mod b/go.mod index 0f658d2bd..899d706b4 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,6 @@ require ( github.com/go-git/go-git/v5 v5.0.0 github.com/go-logr/zapr v0.1.1 // indirect github.com/gophercloud/gophercloud v0.6.0 // indirect - github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de // indirect github.com/gorilla/mux v1.7.4 // indirect github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // indirect github.com/hashicorp/go-cleanhttp v0.5.1 // indirect @@ -29,7 +28,6 @@ require ( github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.1 - github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.0.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.6.1 @@ -46,7 +44,6 @@ require ( opendev.org/airship/go-redfish v0.0.0-20200318103738-db034d1d753a opendev.org/airship/go-redfish/client v0.0.0-20200318103738-db034d1d753a sigs.k8s.io/cli-utils v0.21.0 - sigs.k8s.io/cluster-api v0.3.13 sigs.k8s.io/controller-runtime v0.5.14 sigs.k8s.io/kustomize/api v0.7.2 sigs.k8s.io/kustomize/kyaml v0.10.6 diff --git a/go.sum b/go.sum index 19afe36e7..9612e78f5 100644 --- a/go.sum +++ b/go.sum @@ -33,12 +33,10 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -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 h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= @@ -67,10 +65,7 @@ github.com/ahmetb/dlog v0.0.0-20170105205344-4fb5f8204f26/go.mod h1:ymXt5bw5uSNu github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alessio/shellescape v0.0.0-20190409004728-b115ca0f9053/go.mod h1:xW8sBma2LE3QxFSzCnH9qe6gAE2yO9GvQaWwX89HxbE= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= @@ -88,22 +83,12 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM= -github.com/caddyserver/caddy v1.0.3/go.mod h1:G+ouvOY32gENkJC+jhgl62TyhvqEsFaDiZ4uw0RzP1E= -github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 h1:HD4PLRzjuCVW79mQ0/pdsalOLHJ+FaEoqJLxfltpb2U= github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= -github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -111,7 +96,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/containerd v1.4.1 h1:pASeJT3R3YyVn+94qEPk0SnU1OQ20Jd/T+SPKy9xehY= github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/coredns/corefile-migration v1.0.11/go.mod h1:RMy/mXdeDlYwzt0vdMEJvT2hGJ2I86/eO0UdXmH9XNI= 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/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -155,8 +139,6 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/drone/envsubst v1.0.3-0.20200709223903-efdb65b94e5a h1:pf3CyiWgjOLL7cjFos89AEOPCWSOoQt7tgbEk/SvBAg= -github.com/drone/envsubst v1.0.3-0.20200709223903-efdb65b94e5a/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= 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/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk= @@ -170,8 +152,6 @@ github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -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/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= @@ -193,7 +173,6 @@ github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-acme/lego v2.5.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -206,7 +185,6 @@ github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1 github.com/go-git/go-git/v5 v5.0.0 h1:k5RWPm4iJwYtfWoxIJy4wJX9ON7ihPeZZYC1fLYDnpg= github.com/go-git/go-git/v5 v5.0.0/go.mod h1:oYD8y9kWsGINPFJoLdaScGCN6dlKg23blmClfZwtUVA= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -280,24 +258,20 @@ github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoM github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= -github.com/gobuffalo/flect v0.2.2 h1:PAVD7sp0KOdfswjAw9BpLCU9hXo7wFSzgpQ+zNeks/A= -github.com/gobuffalo/flect v0.2.2/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI= github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 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/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/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/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= @@ -341,14 +315,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= -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= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -366,15 +335,11 @@ github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1a github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.6.0 h1:Xb2lcqZtml1XjgYZxbeayEemq7ASbeTp09m36gQFpEU= github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de h1:F7WD09S8QB4LrkEpka0dFPLSotH11HRpCsLIbIcJ7sU= -github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 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/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= 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/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc h1:f8eY6cV/x1x+HLjOp4r72s/31/V2aTUtg5oKRRPf8/Q= @@ -395,15 +360,12 @@ github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= @@ -418,19 +380,15 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= 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/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= @@ -452,21 +410,14 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= 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/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04= -github.com/lucas-clemente/quic-clients v0.1.0/go.mod h1:y5xVIEoObKqULIKivu+gD/LU90pL73bTdtQjPBvtCBk= -github.com/lucas-clemente/quic-go v0.10.2/go.mod h1:hvaRS9IHjFLMq76puFJeWNfmn+H70QZ/CXoxqw9bzao= -github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= github.com/lucasjones/reggen v0.0.0-20200904144131-37ba4fa293bb h1:w1g9wNDIE/pHSTmAaUhv4TZQuPBS6GV3mMz5hkgziIU= github.com/lucasjones/reggen v0.0.0-20200904144131-37ba4fa293bb/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= -github.com/magiconair/properties v1.8.1/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/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -476,19 +427,15 @@ github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno= github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= -github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= 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/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= -github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -499,7 +446,6 @@ github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdI github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= 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/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= @@ -522,8 +468,6 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m 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/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= -github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -546,16 +490,13 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +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/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= -github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -569,25 +510,20 @@ github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prY 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/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= -github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= 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.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= 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-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.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= @@ -598,7 +534,6 @@ github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uY github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -621,16 +556,11 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 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/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= 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/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= @@ -639,7 +569,6 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= 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/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -648,8 +577,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E= -github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= 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= @@ -662,8 +589,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -715,10 +640,8 @@ 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-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-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -762,11 +685,9 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r 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-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -786,9 +707,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/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-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -803,12 +723,10 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h 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-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/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-20190221075227-b4e8571b14e0/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-20190228124157-a34e9553db1e/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= @@ -825,8 +743,6 @@ golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -846,9 +762,8 @@ golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +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/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -865,7 +780,6 @@ golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3 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-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -900,9 +814,8 @@ google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 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-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -917,9 +830,8 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +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= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -940,9 +852,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy 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/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -955,7 +864,6 @@ gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= @@ -994,7 +902,6 @@ k8s.io/apimachinery v0.17.9 h1:knQxNgMu57Oxlm12J6DS375kmGMeuWV0VNzRRUBB2Yk= k8s.io/apimachinery v0.17.9/go.mod h1:Lg8zZ5iC/O8UjCqW6DNhcQG2m4TdjF9kwG3891OWbbA= k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg= k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo= -k8s.io/apiserver v0.17.9 h1:q50QEJ51xdHy2Gl1lo9yJexiyixxof/yDUFdWNnZxh0= k8s.io/apiserver v0.17.9/go.mod h1:Qaxd3EbeoPRBHVMtFyuKNAObqP6VAkzIMyWYz8KuE2k= k8s.io/cli-runtime v0.0.0-20191214191754-e6dc6d5c8724/go.mod h1:wzlq80lvjgHW9if6MlE4OIGC86MDKsy5jtl9nxz/IYY= k8s.io/cli-runtime v0.17.2/go.mod h1:aa8t9ziyQdbkuizkNLAw3qe3srSyWh9zlSB7zTqRNPI= @@ -1008,8 +915,6 @@ k8s.io/client-go v0.17.2/go.mod h1:QAzRgsa0C2xl4/eVpeVAZMvikCn8Nm81yqVx3Kk9XYI= k8s.io/client-go v0.17.4/go.mod h1:ouF6o5pz3is8qU0/qYL2RnoxOPqgfuidYLowytyLJmc= k8s.io/client-go v0.17.9 h1:qUPhohX4bUBx0L7pfye02aPnu3PQ0t+B8dqHfGvt++k= k8s.io/client-go v0.17.9/go.mod h1:3cM92qAd1XknA5IRkRfpJhl9OQjkYy97ZEUio70wVnI= -k8s.io/cluster-bootstrap v0.17.9 h1:IH/MwGor5/7bwHClz0PO/8pKq+SU1eSB1rs645pGu8Y= -k8s.io/cluster-bootstrap v0.17.9/go.mod h1:Q6nXn/sqVfMvT1VIJVPxFboYAoqH06PCjZnaYzbpZC0= k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE= k8s.io/code-generator v0.0.0-20191214185510-0b9b3c99f9f2/go.mod h1:BjGKcoq1MRUmcssvHiSxodCco1T6nVIt4YeCT5CMSao= k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= @@ -1054,12 +959,9 @@ opendev.org/airship/go-redfish/client v0.0.0-20200318103738-db034d1d753a/go.mod rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/cli-utils v0.21.0 h1:yvLvbzDyiFSmJFpjb6C6tqU2EqQ+hPK4GBUhS+myUm8= sigs.k8s.io/cli-utils v0.21.0/go.mod h1:0n6pW2yhMbb0HxIcg8UeI5/Bi+Dh+7NOsXFdTudB/KY= -sigs.k8s.io/cluster-api v0.3.13 h1:dyhvxgt3M00Co06jrM332i27Tfozu9a0EN/qcmQXUFg= -sigs.k8s.io/cluster-api v0.3.13/go.mod h1:qGxyPTEJWNpII9SBkeRwv+Xvy6EZRLLLzaxVfBLsBpA= sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns= sigs.k8s.io/controller-runtime v0.5.14 h1:lmoRaPvLg9877ZOnjFivjtyIdqyLbWfcCEilxHXTEj4= sigs.k8s.io/controller-runtime v0.5.14/go.mod h1:OTqxLuz7gVcrq+BHGUgedRu6b2VIKCEc7Pu4Jbwui0A= -sigs.k8s.io/kind v0.7.1-0.20200303021537-981bd80d3802/go.mod h1:HIZ3PWUezpklcjkqpFbnYOqaqsAE1JeCTEwkgvPLXjk= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/kustomize/api v0.7.2 h1:ItTD/2XaKO8CosOMFZdaGFdUGTCHdQriW7zQ7AR98rs= diff --git a/krm-functions/clusterctl/Dockerfile b/krm-functions/clusterctl/Dockerfile new file mode 100644 index 000000000..63e7cacfb --- /dev/null +++ b/krm-functions/clusterctl/Dockerfile @@ -0,0 +1,44 @@ +ARG GO_IMAGE=amd64/golang:1.16.6-alpine +ARG PLUGINS_BUILD_IMAGE=alpine:3.12.0 +ARG PLUGINS_RELEASE_IMAGE=alpine:3.12.0 + +FROM ${PLUGINS_BUILD_IMAGE} as ctls +# Inject custom root certificate authorities if needed +# Docker does not have a good conditional copy statement and requires that a source file exists +# to complete the copy function without error. Therefore the README.md file will be copied to +# the image every time even if there are no .crt files. +RUN apk update && apk add curl +COPY ./certs/* /usr/local/share/ca-certificates/ +RUN update-ca-certificates +ARG CCTL_VERSION=0.3.21 +RUN curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v${CCTL_VERSION}/clusterctl-linux-amd64 -o /clusterctl +RUN chmod +x /clusterctl + +FROM ${GO_IMAGE} as function +# Inject custom root certificate authorities if needed +# Docker does not have a good conditional copy statement and requires that a source file exists +# to complete the copy function without error. Therefore the README.md file will be copied to +# the image every time even if there are no .crt files. +COPY ./certs/* /usr/local/share/ca-certificates/ +RUN update-ca-certificates +ENV PATH "/usr/local/go/bin:$PATH" +ENV CGO_ENABLED=0 +WORKDIR /go/src/ +COPY image/ . +RUN go mod download +RUN go build -v -o /usr/local/bin/config-function ./ + +FROM ${PLUGINS_RELEASE_IMAGE} as release +# Inject custom root certificate authorities if needed +# Docker does not have a good conditional copy statement and requires that a source file exists +# to complete the copy function without error. Therefore the README.md file will be copied to +# the image every time even if there are no .crt files. +RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/* +COPY ./certs/* /usr/local/share/ca-certificates/ +RUN update-ca-certificates +COPY --from=ctls /clusterctl /usr/local/bin/ +COPY --from=function /usr/local/bin/config-function /usr/local/bin/config-function +ENV HOME=/workdir +WORKDIR $HOME/.cluster-api +RUN chmod -R a+w $HOME/.cluster-api +CMD ["config-function"] diff --git a/krm-functions/clusterctl/Makefile b/krm-functions/clusterctl/Makefile new file mode 100644 index 000000000..017c06ba4 --- /dev/null +++ b/krm-functions/clusterctl/Makefile @@ -0,0 +1,78 @@ +.PHONY: generate license fix vet fmt test build tidy image + +SHELL := /bin/bash +GOBIN := $(shell go env GOPATH)/bin + +# docker image options +DOCKER_REGISTRY ?= quay.io +DOCKER_IMAGE_NAME ?= clusterctl +DOCKER_IMAGE_PREFIX ?= airshipit +DOCKER_IMAGE_TAG ?= latest +DOCKER_IMAGE ?= $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG) +PUBLISH ?= false +DOCKER_FORCE_CLEAN ?= true + +# proxy options +PROXY ?= http://proxy.foo.com:8000 +NO_PROXY ?= localhost,127.0.0.1,.svc.cluster.local +USE_PROXY ?= false + +.PHONY: build +build: + (cd image && go build -v -o $(GOBIN)/config-function .) + +.PHONY: all +all: generate license build fix vet fmt test lint tidy + +.PHONY: fix +fix: + (cd image && go fix ./...) + +.PHONY: fmt +fmt: + (cd image && go fmt ./...) + +.PHONY: generate +generate: + (which $(GOBIN)/mdtogo || go get sigs.k8s.io/kustomize/cmd/mdtogo) + (cd image && GOBIN=$(GOBIN) go generate ./...) + +.PHONY: tidy +tidy: + (cd image && go mod tidy) + +.PHONY: fix +lint: + (which $(GOBIN)/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1) + (cd image && $(GOBIN)/golangci-lint run ./...) + +.PHONY: test +test: + (cd image && go test -cover ./...) + +.PHONY: vet +vet: + (cd image && go vet ./...) + +.PHONY: image +image: +ifeq ($(USE_PROXY), true) + cd image && \ + docker build . --network=host \ + --build-arg http_proxy=$(PROXY) \ + --build-arg https_proxy=$(PROXY) \ + --build-arg HTTP_PROXY=$(PROXY) \ + --build-arg HTTPS_PROXY=$(PROXY) \ + --build-arg no_proxy=$(NO_PROXY) \ + --build-arg NO_PROXY=$(NO_PROXY) \ + --tag $(DOCKER_IMAGE) \ + --force-rm=$(DOCKER_FORCE_CLEAN) +else + cd image && \ + docker build . --network=host \ + --tag $(DOCKER_IMAGE) \ + --force-rm=$(DOCKER_FORCE_CLEAN) +endif +ifeq ($(PUBLISH), true) + @docker push $(DOCKER_IMAGE) +endif diff --git a/krm-functions/clusterctl/README.md b/krm-functions/clusterctl/README.md new file mode 100644 index 000000000..6a29e228d --- /dev/null +++ b/krm-functions/clusterctl/README.md @@ -0,0 +1,22 @@ +# Clusterctl + +This is a KRM function which invokes +[clusterctl](https://github.com/kubernetes-sigs/cluster-api/tree/master/cmd/clusterctl) +with appropriate action and options. + +## Function implementation + +The function is implemented as an [image](image), and built using `make docker-image-clusterctl`. + +### Function configuration + +As input options, the KRM function receives a struct with command line options, configuration data and +repo components which is defined in airshipctl. See the `ClusterctlOptions` struct definition in v1alpha airshipctl API for the documentation. + +## Function invocation + +The function invoked by airshipctl command via `airshipctl phase run`: + + airshipctl phase run + +if appropriate phase has Clusterctl executor defined. diff --git a/krm-functions/clusterctl/certs/README.md b/krm-functions/clusterctl/certs/README.md new file mode 100644 index 000000000..7d04f7ec4 --- /dev/null +++ b/krm-functions/clusterctl/certs/README.md @@ -0,0 +1,6 @@ +# Additional Docker image root certificate authorities +If you require additional certificate authorities for your Docker image: +* Add ASCII PEM encoded .crt files to this directory + * The files will be copied into your docker image at build time. + +To update manually copy the .crt files to /usr/local/share/ca-certificates/ and run sudo update-ca-certificates. \ No newline at end of file diff --git a/krm-functions/clusterctl/image/go.mod b/krm-functions/clusterctl/image/go.mod new file mode 100644 index 000000000..32f8c42e6 --- /dev/null +++ b/krm-functions/clusterctl/image/go.mod @@ -0,0 +1,5 @@ +module opendev.org/airship/airshipctl/krm-functions/clusterctl/image + +go 1.16 + +require sigs.k8s.io/kustomize/kyaml v0.11.0 diff --git a/krm-functions/clusterctl/image/go.sum b/krm-functions/clusterctl/image/go.sum new file mode 100644 index 000000000..632ae1c2e --- /dev/null +++ b/krm-functions/clusterctl/image/go.sum @@ -0,0 +1,225 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +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/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/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +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/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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/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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +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/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +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/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0/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 v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +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/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= +github.com/spf13/cobra v1.0.0/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.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +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 v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +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/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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= +github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20181220203305-927f97764cc3/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-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +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-20180917221912-90fa682c2a6e/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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +sigs.k8s.io/kustomize/kyaml v0.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA= +sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/krm-functions/clusterctl/image/main.go b/krm-functions/clusterctl/image/main.go new file mode 100644 index 000000000..172b2bd23 --- /dev/null +++ b/krm-functions/clusterctl/image/main.go @@ -0,0 +1,97 @@ +/* + 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 + + https://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. +*/ + +package main + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + + "sigs.k8s.io/kustomize/kyaml/fn/framework" + "sigs.k8s.io/kustomize/kyaml/fn/framework/command" + "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +const ( + clusterctl = "clusterctl" + clusterAPIConfig = "clusterctl.yaml" + + dirPerm = 0755 + filePerm = 0644 +) + +// ClusterctlOptions holds all necessary data to run clusterctl inside of KRM +type ClusterctlOptions struct { + CmdOptions []string `json:"cmd-options,omitempty"` + Config []byte `json:"config,omitempty"` + Components map[string][]byte `json:"components,omitempty"` +} + +// Run prepares config, repo tree and executes clusterctl with appropriate options +func (c *ClusterctlOptions) Run([]*yaml.RNode) ([]*yaml.RNode, error) { + if err := c.buildRepoTree(); err != nil { + return nil, err + } + + if err := ioutil.WriteFile(clusterAPIConfig, c.Config, filePerm); err != nil { + return nil, err + } + + return nil, runCmd(clusterctl, c.CmdOptions) +} + +func (c *ClusterctlOptions) buildRepoTree() error { + for f, component := range c.Components { + componentDir := filepath.Dir(f) + if _, err := os.Stat(componentDir); os.IsNotExist(err) { + if err := os.MkdirAll(componentDir, dirPerm); err != nil { + return err + } + } + if err := ioutil.WriteFile(f, component, filePerm); err != nil { + return err + } + } + return nil +} + +func runCmd(cmd string, opts []string) error { + printMsg("#%s %s\n", cmd, strings.Join(opts, " ")) + c := exec.Command(cmd, opts...) + // allows to observe realtime output from script + w := io.Writer(os.Stderr) + c.Stdout = w + c.Stderr = w + return c.Run() +} + +// printMsg is a convenient function to print output to stderr +func printMsg(format string, a ...interface{}) { + if _, err := fmt.Fprintf(os.Stderr, format, a...); err != nil {} +} + +func main() { + cfg := &ClusterctlOptions{} + if err := command.Build(framework.SimpleProcessor{Filter: kio.FilterFunc(cfg.Run), Config: cfg}, + command.StandaloneDisabled, false).Execute(); err != nil { + printMsg("\n") + os.Exit(1) + } +} diff --git a/krm-functions/clusterctl/local-resource/example-use.yaml b/krm-functions/clusterctl/local-resource/example-use.yaml new file mode 100755 index 000000000..f4e1244ad --- /dev/null +++ b/krm-functions/clusterctl/local-resource/example-use.yaml @@ -0,0 +1,46 @@ +# 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. + +kind: Clusterctl +metadata: + annotations: + config.kubernetes.io/path: clusterctl_clusterctl_init.yaml + labels: + airshipit.org/deploy-k8s: "false" + name: clusterctl_init +images: + bootstrap-kubeadm/kube-rbac-proxy: + repository: gcr.io/kubebuilder + tag: v0.4.1 + bootstrap-kubeadm/kubeadm-bootstrap-controller: + repository: us.gcr.io/k8s-artifacts-prod/cluster-api + tag: v0.3.7 + cert-manager: + repository: quay.io/jetstack +init-options: + bootstrap-providers: kubeadm:v0.3.7 + control-plane-providers: kubeadm:v0.3.7 + core-provider: cluster-api:v0.3.7 + infrastructure-providers: metal3:v0.4.0 +providers: + - name: metal3 + type: InfrastructureProvider + url: airshipctl/manifests/function/capm3/v0.4.0 + - name: kubeadm + type: BootstrapProvider + url: airshipctl/manifests/function/cabpk/v0.3.7 + - name: cluster-api + type: CoreProvider + url: airshipctl/manifests/function/capi/v0.3.7 + - name: kubeadm + type: ControlPlaneProvider + url: airshipctl/manifests/function/cacpk/v0.3.7 diff --git a/krm-functions/kubeval-validator/Makefile b/krm-functions/kubeval-validator/Makefile index 97325850d..0e87cee24 100644 --- a/krm-functions/kubeval-validator/Makefile +++ b/krm-functions/kubeval-validator/Makefile @@ -7,7 +7,7 @@ GOBIN := $(shell go env GOPATH)/bin DOCKER_REGISTRY ?= quay.io DOCKER_IMAGE_NAME ?= kubeval-validator DOCKER_IMAGE_PREFIX ?= airshipit -DOCKER_IMAGE_TAG ?= v0.1.0 +DOCKER_IMAGE_TAG ?= latest DOCKER_IMAGE ?= $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG) PUBLISH ?= false DOCKER_FORCE_CLEAN ?= true diff --git a/manifests/function/cabpk/v0.3.7/data/kustomization.yaml b/manifests/function/cabpk/v0.3.7/data/kustomization.yaml new file mode 100644 index 000000000..65d5b6a21 --- /dev/null +++ b/manifests/function/cabpk/v0.3.7/data/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - metadata.yaml diff --git a/pkg/clusterctl/implementations/testdata/functions/2/version.yaml b/manifests/function/cabpk/v0.3.7/data/metadata.yaml similarity index 52% rename from pkg/clusterctl/implementations/testdata/functions/2/version.yaml rename to manifests/function/cabpk/v0.3.7/data/metadata.yaml index 2f73e855b..8afbc1921 100644 --- a/pkg/clusterctl/implementations/testdata/functions/2/version.yaml +++ b/manifests/function/cabpk/v0.3.7/data/metadata.yaml @@ -1,19 +1,11 @@ --- -apiVersion: airshipit.org/v1alpha1 -kind: Testversion -metadata: - name: version-2 -spec: - version: v0.0.2 ---- apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 kind: Metadata metadata: name: repository-metadata + labels: + airshipit.org/deploy-k8s: "false" releaseSeries: - major: 0 minor: 3 contract: v1alpha3 -- major: 0 - minor: 2 - contract: v1alpha2 \ No newline at end of file diff --git a/manifests/function/cabpk/v0.3.7/kustomization.yaml b/manifests/function/cabpk/v0.3.7/kustomization.yaml index f211307cf..63acf08c4 100644 --- a/manifests/function/cabpk/v0.3.7/kustomization.yaml +++ b/manifests/function/cabpk/v0.3.7/kustomization.yaml @@ -5,6 +5,7 @@ commonLabels: bases: - crd +- data - default - webhook diff --git a/manifests/function/cacpk/v0.3.7/data/kustomization.yaml b/manifests/function/cacpk/v0.3.7/data/kustomization.yaml new file mode 100644 index 000000000..65d5b6a21 --- /dev/null +++ b/manifests/function/cacpk/v0.3.7/data/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - metadata.yaml diff --git a/manifests/function/cacpk/v0.3.7/data/metadata.yaml b/manifests/function/cacpk/v0.3.7/data/metadata.yaml new file mode 100644 index 000000000..8afbc1921 --- /dev/null +++ b/manifests/function/cacpk/v0.3.7/data/metadata.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 +kind: Metadata +metadata: + name: repository-metadata + labels: + airshipit.org/deploy-k8s: "false" +releaseSeries: +- major: 0 + minor: 3 + contract: v1alpha3 diff --git a/manifests/function/cacpk/v0.3.7/kustomization.yaml b/manifests/function/cacpk/v0.3.7/kustomization.yaml index 15967b1c0..f9bdbeb74 100644 --- a/manifests/function/cacpk/v0.3.7/kustomization.yaml +++ b/manifests/function/cacpk/v0.3.7/kustomization.yaml @@ -5,6 +5,7 @@ commonLabels: bases: - crd +- data - default - webhook diff --git a/manifests/function/capi/v0.3.7/data/kustomization.yaml b/manifests/function/capi/v0.3.7/data/kustomization.yaml new file mode 100644 index 000000000..65d5b6a21 --- /dev/null +++ b/manifests/function/capi/v0.3.7/data/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - metadata.yaml diff --git a/manifests/function/capi/v0.3.7/data/metadata.yaml b/manifests/function/capi/v0.3.7/data/metadata.yaml new file mode 100644 index 000000000..8afbc1921 --- /dev/null +++ b/manifests/function/capi/v0.3.7/data/metadata.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 +kind: Metadata +metadata: + name: repository-metadata + labels: + airshipit.org/deploy-k8s: "false" +releaseSeries: +- major: 0 + minor: 3 + contract: v1alpha3 diff --git a/manifests/function/capi/v0.3.7/kustomization.yaml b/manifests/function/capi/v0.3.7/kustomization.yaml index 94df3ce22..75d349a5f 100644 --- a/manifests/function/capi/v0.3.7/kustomization.yaml +++ b/manifests/function/capi/v0.3.7/kustomization.yaml @@ -5,6 +5,7 @@ commonLabels: bases: - crd +- data - webhook - default diff --git a/manifests/function/clusterctl/clusterctl.yaml b/manifests/function/clusterctl/clusterctl.yaml index 8542c2e45..0c01307f6 100644 --- a/manifests/function/clusterctl/clusterctl.yaml +++ b/manifests/function/clusterctl/clusterctl.yaml @@ -6,33 +6,22 @@ metadata: name: clusterctl_init init-options: core-provider: "cluster-api:v0.3.7" - bootstrap-providers: - - "kubeadm:v0.3.7" - infrastructure-providers: - - "metal3:v0.4.0" - control-plane-providers: - - "kubeadm:v0.3.7" + bootstrap-providers: "kubeadm:v0.3.7" + infrastructure-providers: "metal3:v0.4.0" + control-plane-providers: "kubeadm:v0.3.7" providers: - name: "metal3" type: "InfrastructureProvider" - variable-substitution: true - versions: - v0.4.0: airshipctl/manifests/function/capm3/v0.4.0 + url: airshipctl/manifests/function/capm3/v0.4.0 - name: "kubeadm" type: "BootstrapProvider" - variable-substitution: true - versions: - v0.3.7: airshipctl/manifests/function/cabpk/v0.3.7 + url: airshipctl/manifests/function/cabpk/v0.3.7 - name: "cluster-api" type: "CoreProvider" - variable-substitution: true - versions: - v0.3.7: airshipctl/manifests/function/capi/v0.3.7 + url: airshipctl/manifests/function/capi/v0.3.7 - name: "kubeadm" type: "ControlPlaneProvider" - variable-substitution: true - versions: - v0.3.7: airshipctl/manifests/function/cacpk/v0.3.7 + url: airshipctl/manifests/function/cacpk/v0.3.7 # The default image repository and tag for a specific component # can be overriden here diff --git a/manifests/phases/executors.yaml b/manifests/phases/executors.yaml index 3c6e735b1..093c01dcc 100644 --- a/manifests/phases/executors.yaml +++ b/manifests/phases/executors.yaml @@ -512,3 +512,14 @@ configRef: kind: ConfigMap name: kubectl-check-ingress-ctrl apiVersion: v1 +--- +apiVersion: airshipit.org/v1alpha1 +kind: GenericContainer +metadata: + name: clusterctl + labels: + airshipit.org/deploy-k8s: "false" +spec: + type: krm + image: localhost/clusterctl:latest + hostNetwork: true diff --git a/pkg/api/v1alpha1/clusterctl_types.go b/pkg/api/v1alpha1/clusterctl_types.go index 473ee0152..777623502 100644 --- a/pkg/api/v1alpha1/clusterctl_types.go +++ b/pkg/api/v1alpha1/clusterctl_types.go @@ -15,9 +15,7 @@ package v1alpha1 import ( - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" ) // +kubebuilder:object:root=true @@ -33,13 +31,27 @@ type Clusterctl struct { MoveOptions *MoveOptions `json:"move-options,omitempty"` // AdditionalComponentVariables are variables that will be available to clusterctl // when reading provider components - AdditionalComponentVariables map[string]string `json:"additional-vars,omitempty"` - // EnvVars if set to true, allows to source variables for cluster-api components - // for environment variables. - EnvVars bool `json:"env-vars,omitempty"` - ImageMetas map[string]ImageMeta `json:"images,omitempty"` + AdditionalComponentVariables map[string]string `json:"additional-vars,omitempty"` + ImageMetas map[string]ImageMeta `json:"images,omitempty"` } +const ( + // CoreProviderType is a type reserved for Cluster API core repository. + CoreProviderType = "CoreProvider" + + // BootstrapProviderType is the type associated with codebases that provide + // bootstrapping capabilities. + BootstrapProviderType = "BootstrapProvider" + + // InfrastructureProviderType is the type associated with codebases that provide + // infrastructure capabilities. + InfrastructureProviderType = "InfrastructureProvider" + + // ControlPlaneProviderType is the type associated with codebases that provide + // control-plane capabilities. + ControlPlaneProviderType = "ControlPlaneProvider" +) + // ImageMeta is part of clusterctl config type ImageMeta struct { Repository string `json:"repository,omitempty"` @@ -50,20 +62,8 @@ type ImageMeta struct { type Provider struct { Name string `json:"name,"` Type string `json:"type,"` - URL string `json:"url,omitempty"` - - // IsClusterctlRepository if set to true, clusterctl provider's repository implementation will be used - // if omitted or set to false, airshipctl repository implementation will be used. - IsClusterctlRepository bool `json:"clusterctl-repository,omitempty"` - - // Map of versions where each key is a version and value is path relative to target path of the manifest - // ignored if IsClusterctlRepository is set to true - Versions map[string]string `json:"versions,omitempty"` - - // VariableSubstitution indicates weather you want to substitute variables in the cluster-api manifests - // if set to true, variables will be substituted only if they are defined either in Environment or - // in AdditionalComponentVariables, if not they will be left as is. - VariableSubstitution bool `json:"variable-substitution,omitempty"` + // URL can contain remote URL of upstream Provider or relative to target path of the manifest + URL string `json:"url,omitempty"` } // InitOptions container with exposed clusterctl InitOptions @@ -72,19 +72,17 @@ type InitOptions struct { // cluster-api core provider's latest release is used. CoreProvider string `json:"core-provider,omitempty"` - // BootstrapProviders and versions (e.g. kubeadm:v0.3.0) to add to the management cluster. + // BootstrapProviders and versions (comma separated, e.g. kubeadm:v0.3.0) to add to the management cluster. // If unspecified, the kubeadm bootstrap provider's latest release is used. - BootstrapProviders []string `json:"bootstrap-providers,omitempty"` + BootstrapProviders string `json:"bootstrap-providers,omitempty"` - // InfrastructureProviders and versions (e.g. aws:v0.5.0) to add to the management cluster. - InfrastructureProviders []string `json:"infrastructure-providers,omitempty"` + // InfrastructureProviders and versions (comma separated, e.g. aws:v0.5.0,metal3:v0.4.0) + // to add to the management cluster. + InfrastructureProviders string `json:"infrastructure-providers,omitempty"` - // ControlPlaneProviders and versions (e.g. kubeadm:v0.3.0) to add to the management cluster. + // ControlPlaneProviders and versions (comma separated, e.g. kubeadm:v0.3.0) to add to the management cluster. // If unspecified, the kubeadm control plane provider latest release is used. - ControlPlaneProviders []string `json:"control-plane-providers,omitempty"` - - // KubeConfigRef reference to KubeConfig document - KubeConfigRef *corev1.ObjectReference `json:"kubeConfigRef,omitempty"` + ControlPlaneProviders string `json:"control-plane-providers,omitempty"` } // ActionType for clusterctl @@ -96,20 +94,10 @@ const ( Move ActionType = "move" ) -// Provider returns provider filtering by name and type -func (c *Clusterctl) Provider(name string, providerType clusterctlv1.ProviderType) *Provider { - t := string(providerType) - for _, prov := range c.Providers { - if prov.Name == name && prov.Type == t { - return prov - } - } - return nil -} - // MoveOptions carries the options supported by move. type MoveOptions struct { - // The namespace where the workload cluster is hosted. If unspecified, the target context's namespace is used. + // Namespace where the objects describing the workload cluster exists. If unspecified, the current + // namespace will be used. Namespace string `json:"namespace,omitempty"` } @@ -122,3 +110,20 @@ func DefaultClusterctl() *Clusterctl { ImageMetas: make(map[string]ImageMeta), } } + +// ClusterctlOptions holds all necessary data to run clusterctl inside of KRM +type ClusterctlOptions struct { + CmdOptions []string `json:"cmd-options,omitempty"` + Config []byte `json:"config,omitempty"` + Components map[string][]byte `json:"components,omitempty"` +} + +// GetKubeconfigOptions carries all the options to retrieve kubeconfig from parent cluster +type GetKubeconfigOptions struct { + // Timeout is the maximum length of time to retrieve kubeconfig + Timeout string + // Namespace is the namespace in which secret is placed. + ManagedClusterNamespace string + // ManagedClusterName is the name of the managed cluster. + ManagedClusterName string +} diff --git a/pkg/api/v1alpha1/clusterctl_types_test.go b/pkg/api/v1alpha1/clusterctl_types_test.go deleted file mode 100644 index d0282fc8e..000000000 --- a/pkg/api/v1alpha1/clusterctl_types_test.go +++ /dev/null @@ -1,76 +0,0 @@ -/* - 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 - - https://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. -*/ - -package v1alpha1 - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" -) - -func TestProvider(t *testing.T) { - cctl := &Clusterctl{ - Providers: []*Provider{ - { - Name: "kubeadm", - URL: "/home/providers/kubeadm/v0.3.5/components.yaml", - Type: "BootstrapProvider", - IsClusterctlRepository: true, - }, - }, - } - tests := []struct { - name string - getName string - getType string - expectedProvider *Provider - }{ - { - name: "repo options exist", - getName: "kubeadm", - getType: "BootstrapProvider", - expectedProvider: &Provider{ - Name: "kubeadm", - URL: "/home/providers/kubeadm/v0.3.5/components.yaml", - Type: "BootstrapProvider", - IsClusterctlRepository: true, - }, - }, - { - name: "repo name does not exist", - getName: "does not exist", - getType: "BootstrapProvider", - expectedProvider: nil, - }, - { - name: "type does not exist", - getName: "kubeadm", - getType: "does not exist", - expectedProvider: nil, - }, - } - - for _, tt := range tests { - getName := tt.getName - getType := tt.getType - expectedProvider := tt.expectedProvider - t.Run(tt.name, func(t *testing.T) { - actualProvider := cctl.Provider(getName, clusterctlv1.ProviderType(getType)) - assert.Equal(t, expectedProvider, actualProvider) - }) - } -} diff --git a/pkg/api/v1alpha1/zz_generated.deepcopy.go b/pkg/api/v1alpha1/zz_generated.deepcopy.go index afaf002c5..cd54d2709 100644 --- a/pkg/api/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/api/v1alpha1/zz_generated.deepcopy.go @@ -444,14 +444,14 @@ func (in *Clusterctl) DeepCopyInto(out *Clusterctl) { if (*in)[i] != nil { in, out := &(*in)[i], &(*out)[i] *out = new(Provider) - (*in).DeepCopyInto(*out) + **out = **in } } } if in.InitOptions != nil { in, out := &in.InitOptions, &out.InitOptions *out = new(InitOptions) - (*in).DeepCopyInto(*out) + **out = **in } if in.MoveOptions != nil { in, out := &in.MoveOptions, &out.MoveOptions @@ -492,6 +492,46 @@ func (in *Clusterctl) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterctlOptions) DeepCopyInto(out *ClusterctlOptions) { + *out = *in + if in.CmdOptions != nil { + in, out := &in.CmdOptions, &out.CmdOptions + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.Components != nil { + in, out := &in.Components, &out.Components + *out = make(map[string][]byte, len(*in)) + for key, val := range *in { + var outVal []byte + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]byte, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterctlOptions. +func (in *ClusterctlOptions) DeepCopy() *ClusterctlOptions { + if in == nil { + return nil + } + out := new(ClusterctlOptions) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EndPointSpec) DeepCopyInto(out *EndPointSpec) { *out = *in @@ -626,6 +666,21 @@ func (in *GenericContainerSpec) DeepCopy() *GenericContainerSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GetKubeconfigOptions) DeepCopyInto(out *GetKubeconfigOptions) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GetKubeconfigOptions. +func (in *GetKubeconfigOptions) DeepCopy() *GetKubeconfigOptions { + if in == nil { + return nil + } + out := new(GetKubeconfigOptions) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HostNetworkingSpec) DeepCopyInto(out *HostNetworkingSpec) { *out = *in @@ -795,26 +850,6 @@ func (in *ImageURLSpec) DeepCopy() *ImageURLSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *InitOptions) DeepCopyInto(out *InitOptions) { *out = *in - if in.BootstrapProviders != nil { - in, out := &in.BootstrapProviders, &out.BootstrapProviders - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.InfrastructureProviders != nil { - in, out := &in.InfrastructureProviders, &out.InfrastructureProviders - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.ControlPlaneProviders != nil { - in, out := &in.ControlPlaneProviders, &out.ControlPlaneProviders - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.KubeConfigRef != nil { - in, out := &in.KubeConfigRef, &out.KubeConfigRef - *out = new(v1.ObjectReference) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InitOptions. @@ -1397,13 +1432,6 @@ func (in *PhaseStep) DeepCopy() *PhaseStep { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Provider) DeepCopyInto(out *Provider) { *out = *in - if in.Versions != nil { - in, out := &in.Versions, &out.Versions - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Provider. diff --git a/pkg/clusterctl/client/client.go b/pkg/clusterctl/client/client.go deleted file mode 100644 index 29d3edf32..000000000 --- a/pkg/clusterctl/client/client.go +++ /dev/null @@ -1,166 +0,0 @@ -/* - 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 - - https://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. -*/ - -package client - -import ( - "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" - clusterctlclient "sigs.k8s.io/cluster-api/cmd/clusterctl/client" - clusterctlconfig "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/repository" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/yamlprocessor" - clog "sigs.k8s.io/cluster-api/cmd/clusterctl/log" - - airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" - "opendev.org/airship/airshipctl/pkg/clusterctl/implementations" - "opendev.org/airship/airshipctl/pkg/log" -) - -var _ Interface = &Client{} - -const ( - // BootstrapProviderType is a local copy of appropriate type from cluster-api - BootstrapProviderType = v1alpha3.BootstrapProviderType - // CoreProviderType is a local copy of appropriate type from cluster-api - CoreProviderType = v1alpha3.CoreProviderType - // ControlPlaneProviderType is a local copy of appropriate type from cluster-api - ControlPlaneProviderType = v1alpha3.ControlPlaneProviderType - // InfrastructureProviderType is a local copy of appropriate type from cluster-api - InfrastructureProviderType = v1alpha3.InfrastructureProviderType -) - -// Interface is abstraction to Clusterctl -type Interface interface { - Init(kubeconfigPath, kubeconfigContext string) error - Move(fromKubeconfigPath, fromKubeconfigContext, toKubeconfigPath, toKubeconfigContext, namespace string) error - Render(options RenderOptions) ([]byte, error) -} - -// Client Implements interface to Clusterctl -type Client struct { - clusterctlClient clusterctlclient.Client - initOptions clusterctlclient.InitOptions - moveOptions clusterctlclient.MoveOptions - repoFactory RepositoryFactory -} - -// RenderOptions is used to get providers from RepoFactory for Render method -type RenderOptions struct { - ProviderName string - ProviderVersion string - ProviderType string -} - -// GetKubeconfigOptions carries all the options to retrieve kubeconfig from parent cluster -type GetKubeconfigOptions struct { - // Timeout is the maximum length of time to retrieve kubeconfig - Timeout string - // Namespace is the namespace in which secret is placed. - ManagedClusterNamespace string - // ManagedClusterName is the name of the managed cluster. - ManagedClusterName string -} - -// NewClient returns instance of clusterctl client -func NewClient(root string, debug bool, options *airshipv1.Clusterctl) (Interface, error) { - if debug { - debugVerbosity := 5 - clog.SetLogger(clog.NewLogger(clog.WithThreshold(&debugVerbosity))) - } - initOptions := options.InitOptions - var cio clusterctlclient.InitOptions - if initOptions != nil { - cio = clusterctlclient.InitOptions{ - BootstrapProviders: initOptions.BootstrapProviders, - CoreProvider: initOptions.CoreProvider, - InfrastructureProviders: initOptions.InfrastructureProviders, - ControlPlaneProviders: initOptions.ControlPlaneProviders, - } - } - cclient, rf, err := newClusterctlClient(root, options) - if err != nil { - return nil, err - } - return &Client{clusterctlClient: cclient, initOptions: cio, repoFactory: rf}, nil -} - -// Init implements interface to Clusterctl -func (c *Client) Init(kubeconfigPath, kubeconfigContext string) error { - log.Print("Starting cluster-api initiation") - c.initOptions.Kubeconfig = clusterctlclient.Kubeconfig{ - Path: kubeconfigPath, - Context: kubeconfigContext, - } - _, err := c.clusterctlClient.Init(c.initOptions) - return err -} - -// newConfig returns clusterctl config client -func newConfig(options *airshipv1.Clusterctl, root string) (clusterctlconfig.Client, error) { - for _, provider := range options.Providers { - if !provider.IsClusterctlRepository { - provider.URL = root - } - } - reader, err := implementations.NewAirshipReader(options) - if err != nil { - return nil, err - } - return clusterctlconfig.New("", clusterctlconfig.InjectReader(reader)) -} - -func newClusterctlClient(root string, options *airshipv1.Clusterctl) (clusterctlclient.Client, - RepositoryFactory, error) { - cconf, err := newConfig(options, root) - if err != nil { - return nil, RepositoryFactory{}, err - } - - rf := RepositoryFactory{ - Options: options, - ConfigClient: cconf, - } - // option config factory - ocf := clusterctlclient.InjectConfig(cconf) - // option repository factory - orf := clusterctlclient.InjectRepositoryFactory(rf.ClientRepositoryFactory()) - // options cluster client factory - occf := clusterctlclient.InjectClusterClientFactory(rf.ClusterClientFactory()) - client, err := clusterctlclient.New("", ocf, orf, occf) - return client, rf, err -} - -// Render returns requested components as yaml -func (c *Client) Render(renderOptions RenderOptions) ([]byte, error) { - provider, err := c.repoFactory.ConfigClient.Providers().Get(renderOptions.ProviderName, - v1alpha3.ProviderType(renderOptions.ProviderType)) - if err != nil { - return nil, err - } - - crf := c.repoFactory.ClientRepositoryFactory() - repoClient, err := crf(clusterctlclient.RepositoryClientFactoryInput{ - Provider: provider, - Processor: yamlprocessor.NewSimpleProcessor(), - }) - if err != nil { - return nil, err - } - - components, err := repoClient.Components().Get(repository.ComponentsOptions{Version: renderOptions.ProviderVersion}) - if err != nil { - return nil, err - } - return components.Yaml() -} diff --git a/pkg/clusterctl/client/client_test.go b/pkg/clusterctl/client/client_test.go deleted file mode 100644 index c6ddd1936..000000000 --- a/pkg/clusterctl/client/client_test.go +++ /dev/null @@ -1,174 +0,0 @@ -/* - 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 - - https://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. -*/ - -package client - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" - "sigs.k8s.io/yaml" - - airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" -) - -var ( - testConfig = `apiVersion: airshipit.org/v1alpha1 -kind: Clusterctl -metadata: - labels: - airshipit.org/deploy-k8s: "false" - name: clusterctl-v1 -init-options: {} -providers: -- name: "aws" - type: "InfrastructureProvider" - url: "/manifests/capi/infra/aws/v0.3.0" - clusterctl-repository: true -- name: "custom-infra" - type: "InfrastructureProvider" - url: "/manifests/capi/custom-infra/aws/v0.3.0" - clusterctl-repository: true -- name: "custom-airship-infra" - type: "InfrastructureProvider" - versions: - v0.3.1: functions/capi/infrastructure/v0.3.1 - v0.3.2: functions/capi/infrastructure/v0.3.2 -images: - cert-manager/cert-manager-cainjector: - repository: "myorg.io/local-repo" - tag: "v0.1"` -) - -func TestNewConfig(t *testing.T) { - tests := []struct { - name string - conf *airshipv1.Clusterctl - presentProvider string - presentType string - expectedURL string - }{ - { - name: "clusterctl single repo", - presentProvider: "kubeadm", - presentType: "BootstrapProvider", - expectedURL: "/home/providers/kubeadm/v0.3.5/components.yaml", - conf: &airshipv1.Clusterctl{ - - Providers: []*airshipv1.Provider{ - { - Name: "kubeadm", - URL: "/home/providers/kubeadm/v0.3.5/components.yaml", - Type: "BootstrapProvider", - IsClusterctlRepository: true, - }, - }, - }, - }, - { - name: "multiple repos with airship", - presentProvider: "airship-repo", - presentType: "InfrastructureProvider", - expectedURL: testDataDir, - conf: &airshipv1.Clusterctl{ - - Providers: []*airshipv1.Provider{ - { - Name: "airship-repo", - URL: "/home/providers/my-repo/v0.3.5/components.yaml", - Type: "InfrastructureProvider", - IsClusterctlRepository: false, - Versions: map[string]string{ - "v0.3.1": "some-path", - }, - }, - { - Name: "kubeadm", - URL: "/home/providers/kubeadm/v0.3.5/components.yaml", - Type: "BootstrapProvider", - IsClusterctlRepository: true, - }, - }, - }, - }, - } - for _, tt := range tests { - conf := tt.conf - url := tt.expectedURL - provName := tt.presentProvider - provType := tt.presentType - t.Run(tt.name, func(t *testing.T) { - got, err := newConfig(conf, testDataDir) - require.NoError(t, err) - providerClient := got.Providers() - provider, err := providerClient.Get(provName, clusterctlv1.ProviderType(provType)) - require.NoError(t, err) - assert.Equal(t, url, provider.URL()) - }) - } -} - -func TestImageMeta(t *testing.T) { - tests := []struct { - name string - conf *airshipv1.Clusterctl - component string - image string - want string - }{ - { - name: "clusterctl image override ", - component: "cert-manager", - image: "myorg.io/local-repo/cert-manager-cainjector:v0.1", - conf: &airshipv1.Clusterctl{ - ImageMetas: map[string]airshipv1.ImageMeta{ - "cert-manager/cert-manager-cainjector": { - Repository: "myorg.io/local-repo", - Tag: "v0.1", - }, - }, - }, - want: "myorg.io/local-repo/cert-manager-cainjector:v0.1", - }, - } - for _, tt := range tests { - conf := tt.conf - t.Run(tt.name, func(t *testing.T) { - got, err := newConfig(conf, testDataDir) - require.NoError(t, err) - image, err := got.ImageMeta().AlterImage(tt.component, tt.image) - require.NoError(t, err) - assert.Equal(t, image, tt.want) - }) - } -} - -func TestNewClientEmptyOptions(t *testing.T) { - c := &airshipv1.Clusterctl{} - client, err := NewClient("", true, c) - require.NoError(t, err) - require.NotNil(t, client) -} - -func TestNewClient(t *testing.T) { - c := &airshipv1.Clusterctl{} - err := yaml.Unmarshal([]byte(testConfig), c) - require.NoError(t, err) - - client, err := NewClient("", true, c) - require.NoError(t, err) - require.NotNil(t, client) -} diff --git a/pkg/clusterctl/client/errors.go b/pkg/clusterctl/client/errors.go deleted file mode 100644 index ccd6d7431..000000000 --- a/pkg/clusterctl/client/errors.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - 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 - - https://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. -*/ - -package client - -import ( - "fmt" -) - -// ErrProviderNotDefined is returned when wrong AuthType is provided -type ErrProviderNotDefined struct { - ProviderName string -} - -func (e ErrProviderNotDefined) Error() string { - return fmt.Sprintf("provider %s is not defined in Clusterctl document", e.ProviderName) -} - -// ErrProviderRepoNotFound is returned when wrong AuthType is provided -type ErrProviderRepoNotFound struct { - ProviderName string - ProviderType string -} - -func (e ErrProviderRepoNotFound) Error() string { - return fmt.Sprintf("failed to find repository for provider %s of type %s", e.ProviderName, e.ProviderType) -} diff --git a/pkg/clusterctl/client/factory.go b/pkg/clusterctl/client/factory.go deleted file mode 100644 index d2e44a997..000000000 --- a/pkg/clusterctl/client/factory.go +++ /dev/null @@ -1,105 +0,0 @@ -/* - 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 - - https://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. -*/ - -package client - -import ( - "sigs.k8s.io/cluster-api/cmd/clusterctl/client" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/cluster" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/repository" - - airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" - "opendev.org/airship/airshipctl/pkg/clusterctl/implementations" - "opendev.org/airship/airshipctl/pkg/log" -) - -// RepositoryFactory returns an injection factory to work with clusterctl client -type RepositoryFactory struct { - Options *airshipv1.Clusterctl - ConfigClient config.Client -} - -// ClusterClientFactory returns cluster factory function for clusterctl client -func (f RepositoryFactory) ClusterClientFactory() client.ClusterClientFactory { - return func(input client.ClusterClientFactoryInput) (cluster.Client, error) { - o := cluster.InjectRepositoryFactory(f.repoFactoryClusterClient(input)) - return cluster.New(cluster.Kubeconfig{ - Path: input.Kubeconfig.Path, - Context: input.Kubeconfig.Context}, f.ConfigClient, o), nil - } -} - -// ClientRepositoryFactory returns repo factory function for clusterctl client -func (f RepositoryFactory) ClientRepositoryFactory() client.RepositoryClientFactory { - return f.repoFactory -} - -// These two functions are basically the same, but have different with signatures -func (f RepositoryFactory) repoFactoryClusterClient( - input client.ClusterClientFactoryInput) cluster.RepositoryClientFactory { - return func(provider config.Provider, - configClient config.Client, - options ...repository.Option, - ) (repository.Client, error) { - return f.repoFactory(client.RepositoryClientFactoryInput{ - Provider: provider, - Processor: input.Processor, - }) - } -} - -func (f RepositoryFactory) repoFactory(input client.RepositoryClientFactoryInput) (repository.Client, error) { - name := input.Provider.Name() - repoType := input.Provider.Type() - airProv := f.Options.Provider(name, repoType) - if airProv == nil { - return nil, ErrProviderRepoNotFound{ProviderName: name, ProviderType: string(repoType)} - } - // if repository is not clusterctl type, construct an airshipctl implementation of repository interface - if !airProv.IsClusterctlRepository { - // Get repository version map - versions := airProv.Versions - if len(versions) == 0 { - return nil, ErrProviderRepoNotFound{ProviderName: name, ProviderType: string(repoType)} - } - // construct a repository for this provider using root and version map - repo, err := implementations.NewRepository(input.Provider.URL(), versions) - if err != nil { - return nil, err - } - // inject repository into repository client - o := repository.InjectRepository(repo) - // inject yaml processor into repository - oProcessor := repository.InjectYamlProcessor(input.Processor) - log.Printf("Creating airshipctl repository implementation interface for provider %s of type %s\n", - name, - repoType) - - repoClient, err := repository.New(input.Provider, f.ConfigClient, o, oProcessor) - if err != nil { - return nil, err - } - return &implementations.RepositoryClient{ - Client: repoClient, - ProviderType: string(repoType), - ProviderName: name, - VariableSubstitution: airProv.VariableSubstitution}, nil - } - log.Printf("Creating clusterctl repository implementation interface for provider %s of type %s\n", - name, - repoType) - // if repository is clusterctl pass, simply use default clusterctl repository interface - return repository.New(input.Provider, f.ConfigClient) -} diff --git a/pkg/clusterctl/client/factory_test.go b/pkg/clusterctl/client/factory_test.go deleted file mode 100644 index 425de9bd1..000000000 --- a/pkg/clusterctl/client/factory_test.go +++ /dev/null @@ -1,299 +0,0 @@ -/* - 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 - - https://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. -*/ - -package client - -import ( - "sort" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - v1 "k8s.io/api/core/v1" - clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" - clusterctlclient "sigs.k8s.io/cluster-api/cmd/clusterctl/client" - clusterctlconfig "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/repository" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/yamlprocessor" - "sigs.k8s.io/yaml" - - airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" -) - -const ( - testDataDir = "testdata" -) - -var ( - testConfigFactory = `apiVersion: airshipit.org/v1alpha1 -kind: Clusterctl -metadata: - labels: - airshipit.org/deploy-k8s: "false" - name: clusterctl-v1 -init-options: {} -providers: - - name: "aws" - type: "InfrastructureProvider" - url: "/manifests/capi/infra/infrastructure-aws/v0.3.0/components.yaml" - clusterctl-repository: true - - name: "custom-infra" - type: "InfrastructureProvider" - url: "/manifests/capi/infra/infrastructure-custom-infra/v0.3.0/components.yaml" - clusterctl-repository: true - - name: "custom-airship-infra" - type: "InfrastructureProvider" - versions: - v0.3.1: functions/capi/infrastructure/v0.3.1 - v0.3.2: functions/capi/infrastructure/v0.3.2` -) - -func testOptions(t *testing.T, input string) *airshipv1.Clusterctl { - t.Helper() - o := &airshipv1.Clusterctl{} - err := yaml.Unmarshal([]byte(input), o) - require.NoError(t, err) - return o -} - -func testNewConfig(t *testing.T, o *airshipv1.Clusterctl) clusterctlconfig.Client { - t.Helper() - configClient, err := newConfig(o, testDataDir) - require.NoError(t, err) - require.NotNil(t, configClient) - return configClient -} - -// TestFactory checks if airship repository interface is selected for providers that are not -// of airship type, and that this interface methods return correct components -func TestFactory(t *testing.T) { - o := testOptions(t, testConfigFactory) - configClient := testNewConfig(t, o) - factory := RepositoryFactory{ - Options: o, - ConfigClient: configClient, - } - repoFactory := factory.ClientRepositoryFactory() - require.NotNil(t, repoFactory) - pclient := configClient.Providers() - require.NotNil(t, pclient) - tests := []struct { - name string - expectedVersions []string - useVersion string - useName string - useType string - expectErr bool - expectedNamespace string - }{ - { - name: "custom airship v1", - expectedVersions: []string{"v0.3.1", "v0.3.2"}, - useVersion: "v0.3.1", - useName: "custom-airship-infra", - useType: "InfrastructureProvider", - expectErr: false, - expectedNamespace: "version-one", - }, - { - name: "custom airship v2", - expectedVersions: []string{"v0.3.1", "v0.3.2"}, - useVersion: "v0.3.2", - useName: "custom-airship-infra", - useType: "InfrastructureProvider", - expectErr: false, - expectedNamespace: "version-two", - }, - } - for _, tt := range tests { - expectedVersions := tt.expectedVersions - useVersion := tt.useVersion - expectErr := tt.expectErr - useName := tt.useName - useType := tt.useType - expectedNamespace := tt.expectedNamespace - t.Run(tt.name, func(t *testing.T) { - provider, err := pclient.Get(useName, clusterctlv1.ProviderType(useType)) - require.NoError(t, err) - require.NotNil(t, provider) - repo, err := repoFactory(clusterctlclient.RepositoryClientFactoryInput{ - Provider: provider, - Processor: yamlprocessor.NewSimpleProcessor(), - }) - require.NoError(t, err) - require.NotNil(t, repo) - versions, err := repo.GetVersions() - require.NoError(t, err) - sort.Strings(expectedVersions) - sort.Strings(versions) - assert.Equal(t, testDataDir, repo.URL()) - assert.Equal(t, expectedVersions, versions) - components := repo.Components() - require.NotNil(t, components) - // namespaces are left blank, since namespace is provided in the document set - component, err := components.Get(repository.ComponentsOptions{ - Version: useVersion, - }) - require.NoError(t, err) - require.NotNil(t, component) - - b, err := component.Yaml() - if expectErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - actualNamespace := &v1.Namespace{} - err = yaml.Unmarshal(b, actualNamespace) - require.NoError(t, err) - assert.Equal(t, expectedNamespace, actualNamespace.GetName()) - } - }) - } -} - -func TestClientRepositoryFactory(t *testing.T) { - o := testOptions(t, testConfigFactory) - configClient := testNewConfig(t, o) - factory := RepositoryFactory{ - Options: o, - ConfigClient: configClient, - } - clusterclientFactory := factory.ClusterClientFactory() - clusterClient, err := clusterclientFactory(clusterctlclient.ClusterClientFactoryInput{ - Kubeconfig: clusterctlclient.Kubeconfig{ - Path: "testdata/kubeconfig.yaml", - Context: ""}, - Processor: yamlprocessor.NewSimpleProcessor(), - }) - assert.NoError(t, err) - assert.NotNil(t, clusterClient) -} - -func TestRepoFactoryFunction(t *testing.T) { - o := testOptions(t, testConfigFactory) - configClient := testNewConfig(t, o) - - factory := RepositoryFactory{ - Options: o, - ConfigClient: configClient, - } - pclient := configClient.Providers() - require.NotNil(t, pclient) - provider, err := pclient.Get("custom-airship-infra", "InfrastructureProvider") - require.NoError(t, err) - repoClient, err := factory.repoFactory(clusterctlclient.RepositoryClientFactoryInput{ - Provider: provider, - Processor: yamlprocessor.NewSimpleProcessor(), - }) - require.NoError(t, err) - require.NotNil(t, repoClient) - versions, err := repoClient.GetVersions() - expectedVersions := []string{"v0.3.1", "v0.3.2"} - sort.Strings(versions) - sort.Strings(expectedVersions) - require.NoError(t, err) - assert.Equal(t, expectedVersions, versions) -} - -func TestClusterctlRepoFactoryFunction(t *testing.T) { - o := testOptions(t, testConfigFactory) - configClient := testNewConfig(t, o) - factory := RepositoryFactory{ - Options: o, - ConfigClient: configClient, - } - pclient := configClient.Providers() - provider, err := pclient.Get("aws", "InfrastructureProvider") - require.NoError(t, err) - repoClient, err := factory.repoFactory(clusterctlclient.RepositoryClientFactoryInput{ - Provider: provider, - Processor: yamlprocessor.NewSimpleProcessor(), - }) - require.NoError(t, err) - require.NotNil(t, repoClient) -} - -// Test error cases -func TestRepositoryFactoryErrors(t *testing.T) { - // set one default provider clusterctl is properly initialized - defProv := &airshipv1.Provider{ - Name: "aws", - Type: "InfrastructureProvider", - Versions: map[string]string{ - "v0.3.3": testConfig + "/functions/capi/v0.3.3", - }, - } - o := &airshipv1.Clusterctl{ - Providers: []*airshipv1.Provider{defProv}, - } - configClient := testNewConfig(t, o) - require.NotNil(t, configClient) - factory := RepositoryFactory{ - Options: o, - ConfigClient: configClient, - } - rf := factory.ClientRepositoryFactory() - require.NotNil(t, rf) - pclient := configClient.Providers() - require.NotNil(t, pclient) - // save provider so then we can run tests against it, while modifying original airship clustetrctl conf - provider, err := pclient.Get("aws", "InfrastructureProvider") - require.NoError(t, err) - require.NotNil(t, provider) - tests := []struct { - name string - airProvs []*airshipv1.Provider - }{ - { - name: "providers are nil", - airProvs: nil, - }, - { - name: "versions are nil", - airProvs: []*airshipv1.Provider{ - { - Name: "aws", - Type: "InfrastructureProvider", - Versions: nil, - }, - }, - }, - { - name: "versions can't be parsed", - airProvs: []*airshipv1.Provider{ - { - Name: "aws", - Type: "InfrastructureProvider", - Versions: map[string]string{ - "can't parse version": "wrong path", - }, - }, - }, - }, - } - for _, tt := range tests { - airProvs := tt.airProvs - t.Run(tt.name, func(t *testing.T) { - // set airship providers so it does not correspond to clusterctl provider - o.Providers = airProvs - crc, err := factory.repoFactory(clusterctlclient.RepositoryClientFactoryInput{ - Provider: provider, - Processor: yamlprocessor.NewSimpleProcessor(), - }) - // expect error since we have mismatch of airship providers vs clusterctl providers - require.Nil(t, crc) - assert.Error(t, err) - }) - } -} diff --git a/pkg/clusterctl/client/move.go b/pkg/clusterctl/client/move.go deleted file mode 100644 index 40a47539e..000000000 --- a/pkg/clusterctl/client/move.go +++ /dev/null @@ -1,54 +0,0 @@ -/* - 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 - - https://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. -*/ - -package client - -import ( - "github.com/pkg/errors" - - clusterctlclient "sigs.k8s.io/cluster-api/cmd/clusterctl/client" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/cluster" -) - -// Move implements interface to Clusterctl -func (c *Client) Move(fromKubeconfigPath, fromKubeconfigContext, - toKubeconfigPath, toKubeconfigContext, namespace string) error { - var err error - // ephemeral cluster client - pFrom := cluster.New(cluster.Kubeconfig{ - Path: fromKubeconfigPath, - Context: fromKubeconfigContext}, nil).Proxy() - - // If namespace is empty, try to detect it. - if namespace == "" { - var currentNamespace string - currentNamespace, err = pFrom.CurrentNamespace() - if err != nil { - return err - } - namespace = currentNamespace - } - - // clusterctl move - c.moveOptions = clusterctlclient.MoveOptions{ - FromKubeconfig: clusterctlclient.Kubeconfig{Path: fromKubeconfigPath, Context: fromKubeconfigContext}, - ToKubeconfig: clusterctlclient.Kubeconfig{Path: toKubeconfigPath, Context: toKubeconfigContext}, - Namespace: namespace, - } - err = c.clusterctlClient.Move(c.moveOptions) - if err != nil { - return errors.Wrapf(err, "error during clusterctl move") - } - return nil -} diff --git a/pkg/clusterctl/client/testdata/executor_init/kubeconfig.yaml b/pkg/clusterctl/client/testdata/executor_init/kubeconfig.yaml deleted file mode 100644 index fccb7aa59..000000000 --- a/pkg/clusterctl/client/testdata/executor_init/kubeconfig.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: airshipit.org/v1alpha1 -kind: KubeConfig -metadata: - name: sample-name -config: - apiVersion: v1 - kind: Config - clusters: - - cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRFNU1USXlOakE0TWpneU5Gb1hEVEk1TVRJeU16QTRNamd5TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTTFSClM0d3lnajNpU0JBZjlCR0JUS1p5VTFwYmdDaGQ2WTdJektaZWRoakM2K3k1ZEJpWm81ZUx6Z2tEc2gzOC9YQ1MKenFPS2V5cE5RcDN5QVlLdmJKSHg3ODZxSFZZNjg1ZDVYVDNaOHNyVVRzVDR5WmNzZHAzV3lHdDM0eXYzNi9BSQoxK1NlUFErdU5JemN6bzNEdWhXR0ZoQjk3VjZwRitFUTBlVWN5bk05c2hkL3AwWVFzWDR1ZlhxaENENVpzZnZUCnBka3UvTWkyWnVGUldUUUtNeGpqczV3Z2RBWnBsNnN0L2ZkbmZwd1Q5cC9WTjRuaXJnMEsxOURTSFFJTHVrU2MKb013bXNBeDJrZmxITWhPazg5S3FpMEloL2cyczRFYTRvWURZemt0Y2JRZ24wd0lqZ2dmdnVzM3pRbEczN2lwYQo4cVRzS2VmVGdkUjhnZkJDNUZNQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFJek9BL00xWmRGUElzd2VoWjFuemJ0VFNURG4KRHMyVnhSV0VnclFFYzNSYmV3a1NkbTlBS3MwVGR0ZHdEbnBEL2tRYkNyS2xEeFF3RWg3NFZNSFZYYkFadDdsVwpCSm90T21xdXgxYThKYklDRTljR0FHRzFvS0g5R29jWERZY0JzOTA3ckxIdStpVzFnL0xVdG5hN1dSampqZnBLCnFGelFmOGdJUHZIM09BZ3B1RVVncUx5QU8ya0VnelZwTjZwQVJxSnZVRks2TUQ0YzFmMnlxWGxwNXhrN2dFSnIKUzQ4WmF6d0RmWUVmV3Jrdld1YWdvZ1M2SktvbjVEZ0Z1ZHhINXM2Snl6R3lPVnZ0eG1TY2FvOHNxaCs3UXkybgoyLzFVcU5ZK0hlN0x4d04rYkhwYkIxNUtIMTU5ZHNuS3BRbjRORG1jSTZrVnJ3MDVJMUg5ZGRBbGF0bz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - server: https://10.23.25.101:6443 - name: dummycluster_ephemeral - contexts: - - context: - cluster: dummycluster_ephemeral - user: kubernetes-admin - name: dummy_cluster - current-context: dummy_cluster - preferences: {} - users: - - name: kubernetes-admin - user: - client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQwRENDQXJnQ0ZFdFBveEZYSjVrVFNWTXQ0OVlqcHBQL3hCYnlNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1CVXgKRXpBUkJnTlZCQU1UQ210MVltVnlibVYwWlhNd0hoY05NakF3TVRJME1Ua3hOVEV3V2hjTk1qa3hNakF5TVRreApOVEV3V2pBME1Sa3dGd1lEVlFRRERCQnJkV0psY201bGRHVnpMV0ZrYldsdU1SY3dGUVlEVlFRS0RBNXplWE4wClpXMDZiV0Z6ZEdWeWN6Q0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQU1iaFhUUmsKVjZiZXdsUjBhZlpBdTBGYWVsOXRtRThaSFEvaGtaSHhuTjc2bDZUUFltcGJvaDRvRjNGMFFqbzROS1o5NVRuWgo0OWNoV240eFJiZVlPU25EcDBpV0Qzd0pXUlZ5aVFvVUFyYTlNcHVPNkVFU1FpbFVGNXNxc0VXUVdVMjBETStBCkdxK1k0Z2c3eDJ1Q0hTdk1GUmkrNEw5RWlXR2xnRDIvb1hXUm5NWEswNExQajZPb3Vkb2Zid2RmT3J6dTBPVkUKUzR0eGtuS1BCY1BUU3YxMWVaWVhja0JEVjNPbExENEZ3dTB3NTcwcnczNzAraEpYdlZxd3Zjb2RjZjZEL1BXWQowamlnd2ppeUJuZ2dXYW04UVFjd1Nud3o0d05sV3hKOVMyWUJFb1ptdWxVUlFaWVk5ZXRBcEpBdFMzTjlUNlQ2ClovSlJRdEdhZDJmTldTYkxEck5qdU1OTGhBYWRMQnhJUHpBNXZWWk5aalJkdEMwU25pMlFUMTVpSFp4d1RxcjQKakRQQ0pYRXU3KytxcWpQVldUaUZLK3JqcVNhS1pqVWZVaUpHQkJWcm5RZkJENHNtRnNkTjB5cm9tYTZOYzRMNQpKS21RV1NHdmd1aG0zbW5sYjFRaVRZanVyZFJQRFNmdmwrQ0NHbnA1QkkvZ1pwMkF1SHMvNUpKVTJlc1ZvL0xsCkVPdHdSOXdXd3dXcTAvZjhXS3R4bVRrMTUyOUp2dFBGQXQweW1CVjhQbHZlYnVwYmJqeW5pL2xWbTJOYmV6dWUKeCtlMEpNbGtWWnFmYkRSS243SjZZSnJHWW1CUFV0QldoSVkzb1pJVTFEUXI4SUlIbkdmYlZoWlR5ME1IMkFCQQp1dlVQcUtSVk80UGkxRTF4OEE2eWVPeVRDcnB4L0pBazVyR2RBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBSWNFM1BxZHZDTVBIMnJzMXJESk9ESHY3QWk4S01PVXZPRi90RjlqR2EvSFBJbkh3RlVFNEltbldQeDYKVUdBMlE1bjFsRDFGQlU0T0M4eElZc3VvS1VQVHk1T0t6SVNMNEZnL0lEcG54STlrTXlmNStMR043aG8rblJmawpCZkpJblVYb0tERW1neHZzSWFGd1h6bGtSTDJzL1lKYUZRRzE1Uis1YzFyckJmd2dJOFA5Tkd6aEM1cXhnSmovCm04K3hPMGhXUmJIYklrQ21NekRib2pCSWhaL00rb3VYR1doei9TakpodXhZTVBnek5MZkFGcy9PMTVaSjd3YXcKZ3ZoSGc3L2E5UzRvUCtEYytPa3VrMkV1MUZjL0E5WHpWMzc5aWhNWW5ub3RQMldWeFZ3b0ZZQUg0NUdQcDZsUApCQmwyNnkxc2JMbjl6aGZYUUJIMVpFN0EwZVE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS1FJQkFBS0NBZ0VBeHVGZE5HUlhwdDdDVkhScDlrQzdRVnA2WDIyWVR4a2REK0dSa2ZHYzN2cVhwTTlpCmFsdWlIaWdYY1hSQ09qZzBwbjNsT2RuajF5RmFmakZGdDVnNUtjT25TSllQZkFsWkZYS0pDaFFDdHIweW00N28KUVJKQ0tWUVhteXF3UlpCWlRiUU16NEFhcjVqaUNEdkhhNElkSzh3VkdMN2d2MFNKWWFXQVBiK2hkWkdjeGNyVApncytQbzZpNTJoOXZCMTg2dk83UTVVUkxpM0dTY284Rnc5TksvWFY1bGhkeVFFTlhjNlVzUGdYQzdURG52U3ZECmZ2VDZFbGU5V3JDOXloMXgvb1A4OVpqU09LRENPTElHZUNCWnFieEJCekJLZkRQakEyVmJFbjFMWmdFU2htYTYKVlJGQmxoajE2MENra0MxTGMzMVBwUHBuOGxGQzBacDNaODFaSnNzT3MyTzR3MHVFQnAwc0hFZy9NRG05VmsxbQpORjIwTFJLZUxaQlBYbUlkbkhCT3F2aU1NOElsY1M3djc2cXFNOVZaT0lVcjZ1T3BKb3BtTlI5U0lrWUVGV3VkCkI4RVBpeVlXeDAzVEt1aVpybzF6Z3Zra3FaQlpJYStDNkdiZWFlVnZWQ0pOaU82dDFFOE5KKytYNElJYWVua0UKaitCbW5ZQzRlei9ra2xUWjZ4V2o4dVVRNjNCSDNCYkRCYXJUOS94WXEzR1pPVFhuYjBtKzA4VUMzVEtZRlh3KwpXOTV1Nmx0dVBLZUwrVldiWTF0N081N0g1N1FreVdSVm1wOXNORXFmc25wZ21zWmlZRTlTMEZhRWhqZWhraFRVCk5DdndnZ2VjWjl0V0ZsUExRd2ZZQUVDNjlRK29wRlU3ZytMVVRYSHdEcko0N0pNS3VuSDhrQ1Rtc1owQ0F3RUEKQVFLQ0FnQUJ2U1N3ZVpRZW5HSDhsUXY4SURMQzdvU1ZZd0xxNWlCUDdEdjJsN00wYStKNWlXcWwzV2s4ZEVOSQpOYWtDazAwNmkyMCtwVDROdW5mdEZJYzBoTHN6TjBlMkpjRzY1dVlGZnZ2ZHY3RUtZZnNZU3hhU3d4TWJBMlkxCmNCa2NjcGVsUzBhMVpieFYvck16T1RxVUlRNGFQTzJPU3RUeU55b3dWVjhhcXh0QlNPV2pBUlA2VjlBOHNSUDIKNlVGeVFnM2thdjRla3d0S0M5TW85MEVvcGlkSXNnYy9IYk5kQm5tMFJDUnY0bU1DNmVPTXp0NGx0UVNldG0rcwpaRkUwZkM5cjkwRjE4RUVlUjZHTEYxdGhIMzlKTWFFcjYrc3F6TlZXU1VPVGxNN2M5SE55QTJIcnJudnhVUVNOCmF3SkZWSEFOY1hJSjBqcW9icmR6MTdMbGtIRVFGczNLdjRlcDR3REJKMlF0eisxdUFvY1JoV3ZSaWJxWEQ3THgKVmpPdGRyT1h3ZFQxY2ZrKzZRc1RMWUFKR3ptdDdsY1M2QjNnYzJHWmNJWGwyNVlqTUQ1ZVhpa1dEc3hYWmt1UAorb3MzVGhxeGZIS25ITmxtYk9SSVpDMW92Q1NkSTRWZVpzalk0MUs5K0dNaXdXSk1kektpRkp3NlR2blRSUldTCkxod2EzUTlBVmMvTEg0SC9PbU9qWDc0QTNZSWwrRDFVUHd3VzAvMmw4S3BNM0VWZ21XalJMV1ZIRnBNTGJNSlcKZVZKd3dKUmF3bWZLdHZ6bU9KRHlhTXJJblhqTDMvSE1EaWtwU3JhRzFyTnc1SUozOXJZdEFIUUQ1L1VuZlRkSApLNXVjakVucTdPdDMyR1ozcHJvRTU1ZGFBY0hQbktuOGpYZ1ZKTUQyOWh5cEZvL2ZRUUtDQVFFQStBbjRoSDFFCm9GK3FlcWlvYXR3N2cwaVdQUDNCeklxOEZWbWtsRlZBYVF5U28wU2QxWFBybmErR0RFQVd0cHlsVjF5ZkZkR2oKSHc4YXU5NnpUZnRuNWZCRkQxWG1NTkNZeTcrM293V3ArK1NwYUMvMTYzN1dvb3lLRjBjVFNvcWEzZEVuRUtSSwp4TGF2a0lFUTI3OXRBNFVUK0dVK3pTb0NPUFBNNE1JS3poR0FDczZ1anRySzFNcXpwK0JhYldzRlBuN2J1bStVCkRHSFIrNCtab2tBL1Q2N2luYlRxZUwwVzJCNjRMckFURHpZL3Y4NlRGbW1aallEaHRKR1JIWVZUOU9XSXR0RVkKNnZtUDN0a1dOTWt0R2w4bTFiQ0FHQ1JlcGtycUhxWXNMWG5GQ2ZZSFFtOXNpaGgvM3JFVjZ1MUYxZCt0U3JFMgprU1ZVOHhVWDUwbHFNUUtDQVFFQXpVTjZaS0lRNldkT09FR3ZyMExRL1hVczI0bUczN3lGMjhJUDJEcWFBWWVzCnJza2xTdjdlSU9TZWV3MW1CRHVCRkl2bkZvcTVsRlA3cXhWcEIyWjNNSGlDMVNaclZSZjlQTjdCNGFzcmNyMCsKdDB2S0NXWFFIaTVQQXhucXdYb2E2N0Q1bnkwdnlvV0lVUXAyZEZMdkIwQmp0b3MvajJFaHpJZk5WMm1UOW15bgpWQXZOWEdtZnc4SVJCL1diMGkzQ3c0Wityb1l1dTJkRHo2UUwzUFVvN1hLS3ljZzR1UzU1eksvcWZPc09lYm5mCnpsd3ZqbGxNSitmVFFHNzMrQnpINE5IWGs2akZZQzU4eXBrdXd0cmJmYk1pSkZOWThyV1ptL01Nd1VDWlZDQ3kKeUlxQ3FHQVB6b2kyU05zSEtaTlJqN3ZZQ3dQQVd6TzFidjFGcC9hM0xRS0NBUUVBeG0zTGw4cFROVzF6QjgrWApkRzJkV3FpZU1FcmRXRklBcDUvZ1R4NW9lZUdxQ2QxaDJ4cHlldUtwZlhGaitsRVU0Ty9qQU9TRjk5bndqQzFjCkNsMit2Ni9ZdjZ6N2l6L0ZqUEpoNlpRbGFiT0RaeXMvTkZkelEvVGtvRHluRFRJWE5LOFc3blJRc0ZCcDRWT3YKZGUwTlBBeWhiazBvMFo3eXlqY1lSeEpVN0lnSmhCdldmOGcvRGI3ZnZNUjU4eUR6d0F4aW9pS1RNTmlzMFBBUAplMEtrbzQySUU1eGhHNWhDQjBHRUhTMlZBYzFuY0gzRkk5LzFETVAzVEtwTGltOVlQQW5JdG1CTzYrUWNtYTNYCjJ3QzZDV2ZudkhvSDc4aGd3KzRZbjg1V2QwYjhQN3pJRC9qdHZ3aGNlMzMxeDh4cjJ1Nm5ScUxBd1pzNCs0SjcKYmZkSWNRS0NBUUFDL2JlNzNheTNhZnoyenVZN2ZKTEZEcjhQbCtweU9qSU5LTC9JVzlwQXFYUjN1NUNpamlJNApnbnhZdUxKQzM0Y2JBSXJtaGpEOEcxa3dmZ2hneGpwNFoxa290LzJhYU5ZVTIvNGhScmhFWE1PY01pdUloWVpKCjJrem1jNnM3RklkdDVjOU5aWUFyeUZSYk1mYlY3UnQwbEppZllWb1V3Y3FYUzJkUG5jYzlNUW9qTEdUYXN1TlUKRy9EWmw5ZWtjV3hFSXlLWGNuY2QzZnhiK3p6OUJFbUxaRDduZjlacnhHU2IrZmhGeDdzWFJRRWc1YkQvdHdkbwpFWFcvbTU1YmJEZnhhNzFqZG5NaDJxdVEzRGlWT0ZFNGZMTERxcjlDRWlsaDMySFJNeHJJNGcwWTVRUFFaazMwCnFZTldmbktWUllOTHYrWC9DeGZ6ZkVacGpxRkVPRkVsQW9JQkFRQ0t6R2JGdmx6d1BaUmh4czd2VXYxOXlIUXAKQzFmR3gwb0tpRDFSNWZwWVBrT0VRQWVudEFKRHNyYVRsNy9rSDY5V09VbUQ1T3gxbWpyRFB0a1M4WnhXYlJXeApGYjJLK3JxYzRtcGFacGROV09OTkszK3RNZmsrb0FRcWUySU1JV253NUhmbVpjNE1QY0t0bkZQYlJTTkF0aktwCkQ2aG9oL3BXMmdjRFA0cVpNWVZvRW04MVZYZEZDUGhOYitNYnUvU3gyaFB4U0dXYTVGaTczeEtwWWp5M3BISlQKWFoyY2lHN0VNQ3NKZW9HS2FRdmNCY1kvNGlSRGFoV0hWcmlsSVhJQXJQdXdmVUIybzZCZFR0allHeU5sZ2NmeApxWEt4aXBTaEE2VlNienVnR3pkdEdNeEUyekRHVEkxOXFSQy96OUNEREM1ZTJTQUZqbEJUV0QyUHJjcU4KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K \ No newline at end of file diff --git a/pkg/clusterctl/client/testdata/executor_init/kustomization.yaml b/pkg/clusterctl/client/testdata/executor_init/kustomization.yaml deleted file mode 100644 index 64b49bda4..000000000 --- a/pkg/clusterctl/client/testdata/executor_init/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - kubeconfig.yaml \ No newline at end of file diff --git a/pkg/clusterctl/client/testdata/executor_move/kubeconfig.yaml b/pkg/clusterctl/client/testdata/executor_move/kubeconfig.yaml deleted file mode 100644 index fccb7aa59..000000000 --- a/pkg/clusterctl/client/testdata/executor_move/kubeconfig.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: airshipit.org/v1alpha1 -kind: KubeConfig -metadata: - name: sample-name -config: - apiVersion: v1 - kind: Config - clusters: - - cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRFNU1USXlOakE0TWpneU5Gb1hEVEk1TVRJeU16QTRNamd5TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTTFSClM0d3lnajNpU0JBZjlCR0JUS1p5VTFwYmdDaGQ2WTdJektaZWRoakM2K3k1ZEJpWm81ZUx6Z2tEc2gzOC9YQ1MKenFPS2V5cE5RcDN5QVlLdmJKSHg3ODZxSFZZNjg1ZDVYVDNaOHNyVVRzVDR5WmNzZHAzV3lHdDM0eXYzNi9BSQoxK1NlUFErdU5JemN6bzNEdWhXR0ZoQjk3VjZwRitFUTBlVWN5bk05c2hkL3AwWVFzWDR1ZlhxaENENVpzZnZUCnBka3UvTWkyWnVGUldUUUtNeGpqczV3Z2RBWnBsNnN0L2ZkbmZwd1Q5cC9WTjRuaXJnMEsxOURTSFFJTHVrU2MKb013bXNBeDJrZmxITWhPazg5S3FpMEloL2cyczRFYTRvWURZemt0Y2JRZ24wd0lqZ2dmdnVzM3pRbEczN2lwYQo4cVRzS2VmVGdkUjhnZkJDNUZNQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFJek9BL00xWmRGUElzd2VoWjFuemJ0VFNURG4KRHMyVnhSV0VnclFFYzNSYmV3a1NkbTlBS3MwVGR0ZHdEbnBEL2tRYkNyS2xEeFF3RWg3NFZNSFZYYkFadDdsVwpCSm90T21xdXgxYThKYklDRTljR0FHRzFvS0g5R29jWERZY0JzOTA3ckxIdStpVzFnL0xVdG5hN1dSampqZnBLCnFGelFmOGdJUHZIM09BZ3B1RVVncUx5QU8ya0VnelZwTjZwQVJxSnZVRks2TUQ0YzFmMnlxWGxwNXhrN2dFSnIKUzQ4WmF6d0RmWUVmV3Jrdld1YWdvZ1M2SktvbjVEZ0Z1ZHhINXM2Snl6R3lPVnZ0eG1TY2FvOHNxaCs3UXkybgoyLzFVcU5ZK0hlN0x4d04rYkhwYkIxNUtIMTU5ZHNuS3BRbjRORG1jSTZrVnJ3MDVJMUg5ZGRBbGF0bz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - server: https://10.23.25.101:6443 - name: dummycluster_ephemeral - contexts: - - context: - cluster: dummycluster_ephemeral - user: kubernetes-admin - name: dummy_cluster - current-context: dummy_cluster - preferences: {} - users: - - name: kubernetes-admin - user: - client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQwRENDQXJnQ0ZFdFBveEZYSjVrVFNWTXQ0OVlqcHBQL3hCYnlNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1CVXgKRXpBUkJnTlZCQU1UQ210MVltVnlibVYwWlhNd0hoY05NakF3TVRJME1Ua3hOVEV3V2hjTk1qa3hNakF5TVRreApOVEV3V2pBME1Sa3dGd1lEVlFRRERCQnJkV0psY201bGRHVnpMV0ZrYldsdU1SY3dGUVlEVlFRS0RBNXplWE4wClpXMDZiV0Z6ZEdWeWN6Q0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQU1iaFhUUmsKVjZiZXdsUjBhZlpBdTBGYWVsOXRtRThaSFEvaGtaSHhuTjc2bDZUUFltcGJvaDRvRjNGMFFqbzROS1o5NVRuWgo0OWNoV240eFJiZVlPU25EcDBpV0Qzd0pXUlZ5aVFvVUFyYTlNcHVPNkVFU1FpbFVGNXNxc0VXUVdVMjBETStBCkdxK1k0Z2c3eDJ1Q0hTdk1GUmkrNEw5RWlXR2xnRDIvb1hXUm5NWEswNExQajZPb3Vkb2Zid2RmT3J6dTBPVkUKUzR0eGtuS1BCY1BUU3YxMWVaWVhja0JEVjNPbExENEZ3dTB3NTcwcnczNzAraEpYdlZxd3Zjb2RjZjZEL1BXWQowamlnd2ppeUJuZ2dXYW04UVFjd1Nud3o0d05sV3hKOVMyWUJFb1ptdWxVUlFaWVk5ZXRBcEpBdFMzTjlUNlQ2ClovSlJRdEdhZDJmTldTYkxEck5qdU1OTGhBYWRMQnhJUHpBNXZWWk5aalJkdEMwU25pMlFUMTVpSFp4d1RxcjQKakRQQ0pYRXU3KytxcWpQVldUaUZLK3JqcVNhS1pqVWZVaUpHQkJWcm5RZkJENHNtRnNkTjB5cm9tYTZOYzRMNQpKS21RV1NHdmd1aG0zbW5sYjFRaVRZanVyZFJQRFNmdmwrQ0NHbnA1QkkvZ1pwMkF1SHMvNUpKVTJlc1ZvL0xsCkVPdHdSOXdXd3dXcTAvZjhXS3R4bVRrMTUyOUp2dFBGQXQweW1CVjhQbHZlYnVwYmJqeW5pL2xWbTJOYmV6dWUKeCtlMEpNbGtWWnFmYkRSS243SjZZSnJHWW1CUFV0QldoSVkzb1pJVTFEUXI4SUlIbkdmYlZoWlR5ME1IMkFCQQp1dlVQcUtSVk80UGkxRTF4OEE2eWVPeVRDcnB4L0pBazVyR2RBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBSWNFM1BxZHZDTVBIMnJzMXJESk9ESHY3QWk4S01PVXZPRi90RjlqR2EvSFBJbkh3RlVFNEltbldQeDYKVUdBMlE1bjFsRDFGQlU0T0M4eElZc3VvS1VQVHk1T0t6SVNMNEZnL0lEcG54STlrTXlmNStMR043aG8rblJmawpCZkpJblVYb0tERW1neHZzSWFGd1h6bGtSTDJzL1lKYUZRRzE1Uis1YzFyckJmd2dJOFA5Tkd6aEM1cXhnSmovCm04K3hPMGhXUmJIYklrQ21NekRib2pCSWhaL00rb3VYR1doei9TakpodXhZTVBnek5MZkFGcy9PMTVaSjd3YXcKZ3ZoSGc3L2E5UzRvUCtEYytPa3VrMkV1MUZjL0E5WHpWMzc5aWhNWW5ub3RQMldWeFZ3b0ZZQUg0NUdQcDZsUApCQmwyNnkxc2JMbjl6aGZYUUJIMVpFN0EwZVE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS1FJQkFBS0NBZ0VBeHVGZE5HUlhwdDdDVkhScDlrQzdRVnA2WDIyWVR4a2REK0dSa2ZHYzN2cVhwTTlpCmFsdWlIaWdYY1hSQ09qZzBwbjNsT2RuajF5RmFmakZGdDVnNUtjT25TSllQZkFsWkZYS0pDaFFDdHIweW00N28KUVJKQ0tWUVhteXF3UlpCWlRiUU16NEFhcjVqaUNEdkhhNElkSzh3VkdMN2d2MFNKWWFXQVBiK2hkWkdjeGNyVApncytQbzZpNTJoOXZCMTg2dk83UTVVUkxpM0dTY284Rnc5TksvWFY1bGhkeVFFTlhjNlVzUGdYQzdURG52U3ZECmZ2VDZFbGU5V3JDOXloMXgvb1A4OVpqU09LRENPTElHZUNCWnFieEJCekJLZkRQakEyVmJFbjFMWmdFU2htYTYKVlJGQmxoajE2MENra0MxTGMzMVBwUHBuOGxGQzBacDNaODFaSnNzT3MyTzR3MHVFQnAwc0hFZy9NRG05VmsxbQpORjIwTFJLZUxaQlBYbUlkbkhCT3F2aU1NOElsY1M3djc2cXFNOVZaT0lVcjZ1T3BKb3BtTlI5U0lrWUVGV3VkCkI4RVBpeVlXeDAzVEt1aVpybzF6Z3Zra3FaQlpJYStDNkdiZWFlVnZWQ0pOaU82dDFFOE5KKytYNElJYWVua0UKaitCbW5ZQzRlei9ra2xUWjZ4V2o4dVVRNjNCSDNCYkRCYXJUOS94WXEzR1pPVFhuYjBtKzA4VUMzVEtZRlh3KwpXOTV1Nmx0dVBLZUwrVldiWTF0N081N0g1N1FreVdSVm1wOXNORXFmc25wZ21zWmlZRTlTMEZhRWhqZWhraFRVCk5DdndnZ2VjWjl0V0ZsUExRd2ZZQUVDNjlRK29wRlU3ZytMVVRYSHdEcko0N0pNS3VuSDhrQ1Rtc1owQ0F3RUEKQVFLQ0FnQUJ2U1N3ZVpRZW5HSDhsUXY4SURMQzdvU1ZZd0xxNWlCUDdEdjJsN00wYStKNWlXcWwzV2s4ZEVOSQpOYWtDazAwNmkyMCtwVDROdW5mdEZJYzBoTHN6TjBlMkpjRzY1dVlGZnZ2ZHY3RUtZZnNZU3hhU3d4TWJBMlkxCmNCa2NjcGVsUzBhMVpieFYvck16T1RxVUlRNGFQTzJPU3RUeU55b3dWVjhhcXh0QlNPV2pBUlA2VjlBOHNSUDIKNlVGeVFnM2thdjRla3d0S0M5TW85MEVvcGlkSXNnYy9IYk5kQm5tMFJDUnY0bU1DNmVPTXp0NGx0UVNldG0rcwpaRkUwZkM5cjkwRjE4RUVlUjZHTEYxdGhIMzlKTWFFcjYrc3F6TlZXU1VPVGxNN2M5SE55QTJIcnJudnhVUVNOCmF3SkZWSEFOY1hJSjBqcW9icmR6MTdMbGtIRVFGczNLdjRlcDR3REJKMlF0eisxdUFvY1JoV3ZSaWJxWEQ3THgKVmpPdGRyT1h3ZFQxY2ZrKzZRc1RMWUFKR3ptdDdsY1M2QjNnYzJHWmNJWGwyNVlqTUQ1ZVhpa1dEc3hYWmt1UAorb3MzVGhxeGZIS25ITmxtYk9SSVpDMW92Q1NkSTRWZVpzalk0MUs5K0dNaXdXSk1kektpRkp3NlR2blRSUldTCkxod2EzUTlBVmMvTEg0SC9PbU9qWDc0QTNZSWwrRDFVUHd3VzAvMmw4S3BNM0VWZ21XalJMV1ZIRnBNTGJNSlcKZVZKd3dKUmF3bWZLdHZ6bU9KRHlhTXJJblhqTDMvSE1EaWtwU3JhRzFyTnc1SUozOXJZdEFIUUQ1L1VuZlRkSApLNXVjakVucTdPdDMyR1ozcHJvRTU1ZGFBY0hQbktuOGpYZ1ZKTUQyOWh5cEZvL2ZRUUtDQVFFQStBbjRoSDFFCm9GK3FlcWlvYXR3N2cwaVdQUDNCeklxOEZWbWtsRlZBYVF5U28wU2QxWFBybmErR0RFQVd0cHlsVjF5ZkZkR2oKSHc4YXU5NnpUZnRuNWZCRkQxWG1NTkNZeTcrM293V3ArK1NwYUMvMTYzN1dvb3lLRjBjVFNvcWEzZEVuRUtSSwp4TGF2a0lFUTI3OXRBNFVUK0dVK3pTb0NPUFBNNE1JS3poR0FDczZ1anRySzFNcXpwK0JhYldzRlBuN2J1bStVCkRHSFIrNCtab2tBL1Q2N2luYlRxZUwwVzJCNjRMckFURHpZL3Y4NlRGbW1aallEaHRKR1JIWVZUOU9XSXR0RVkKNnZtUDN0a1dOTWt0R2w4bTFiQ0FHQ1JlcGtycUhxWXNMWG5GQ2ZZSFFtOXNpaGgvM3JFVjZ1MUYxZCt0U3JFMgprU1ZVOHhVWDUwbHFNUUtDQVFFQXpVTjZaS0lRNldkT09FR3ZyMExRL1hVczI0bUczN3lGMjhJUDJEcWFBWWVzCnJza2xTdjdlSU9TZWV3MW1CRHVCRkl2bkZvcTVsRlA3cXhWcEIyWjNNSGlDMVNaclZSZjlQTjdCNGFzcmNyMCsKdDB2S0NXWFFIaTVQQXhucXdYb2E2N0Q1bnkwdnlvV0lVUXAyZEZMdkIwQmp0b3MvajJFaHpJZk5WMm1UOW15bgpWQXZOWEdtZnc4SVJCL1diMGkzQ3c0Wityb1l1dTJkRHo2UUwzUFVvN1hLS3ljZzR1UzU1eksvcWZPc09lYm5mCnpsd3ZqbGxNSitmVFFHNzMrQnpINE5IWGs2akZZQzU4eXBrdXd0cmJmYk1pSkZOWThyV1ptL01Nd1VDWlZDQ3kKeUlxQ3FHQVB6b2kyU05zSEtaTlJqN3ZZQ3dQQVd6TzFidjFGcC9hM0xRS0NBUUVBeG0zTGw4cFROVzF6QjgrWApkRzJkV3FpZU1FcmRXRklBcDUvZ1R4NW9lZUdxQ2QxaDJ4cHlldUtwZlhGaitsRVU0Ty9qQU9TRjk5bndqQzFjCkNsMit2Ni9ZdjZ6N2l6L0ZqUEpoNlpRbGFiT0RaeXMvTkZkelEvVGtvRHluRFRJWE5LOFc3blJRc0ZCcDRWT3YKZGUwTlBBeWhiazBvMFo3eXlqY1lSeEpVN0lnSmhCdldmOGcvRGI3ZnZNUjU4eUR6d0F4aW9pS1RNTmlzMFBBUAplMEtrbzQySUU1eGhHNWhDQjBHRUhTMlZBYzFuY0gzRkk5LzFETVAzVEtwTGltOVlQQW5JdG1CTzYrUWNtYTNYCjJ3QzZDV2ZudkhvSDc4aGd3KzRZbjg1V2QwYjhQN3pJRC9qdHZ3aGNlMzMxeDh4cjJ1Nm5ScUxBd1pzNCs0SjcKYmZkSWNRS0NBUUFDL2JlNzNheTNhZnoyenVZN2ZKTEZEcjhQbCtweU9qSU5LTC9JVzlwQXFYUjN1NUNpamlJNApnbnhZdUxKQzM0Y2JBSXJtaGpEOEcxa3dmZ2hneGpwNFoxa290LzJhYU5ZVTIvNGhScmhFWE1PY01pdUloWVpKCjJrem1jNnM3RklkdDVjOU5aWUFyeUZSYk1mYlY3UnQwbEppZllWb1V3Y3FYUzJkUG5jYzlNUW9qTEdUYXN1TlUKRy9EWmw5ZWtjV3hFSXlLWGNuY2QzZnhiK3p6OUJFbUxaRDduZjlacnhHU2IrZmhGeDdzWFJRRWc1YkQvdHdkbwpFWFcvbTU1YmJEZnhhNzFqZG5NaDJxdVEzRGlWT0ZFNGZMTERxcjlDRWlsaDMySFJNeHJJNGcwWTVRUFFaazMwCnFZTldmbktWUllOTHYrWC9DeGZ6ZkVacGpxRkVPRkVsQW9JQkFRQ0t6R2JGdmx6d1BaUmh4czd2VXYxOXlIUXAKQzFmR3gwb0tpRDFSNWZwWVBrT0VRQWVudEFKRHNyYVRsNy9rSDY5V09VbUQ1T3gxbWpyRFB0a1M4WnhXYlJXeApGYjJLK3JxYzRtcGFacGROV09OTkszK3RNZmsrb0FRcWUySU1JV253NUhmbVpjNE1QY0t0bkZQYlJTTkF0aktwCkQ2aG9oL3BXMmdjRFA0cVpNWVZvRW04MVZYZEZDUGhOYitNYnUvU3gyaFB4U0dXYTVGaTczeEtwWWp5M3BISlQKWFoyY2lHN0VNQ3NKZW9HS2FRdmNCY1kvNGlSRGFoV0hWcmlsSVhJQXJQdXdmVUIybzZCZFR0allHeU5sZ2NmeApxWEt4aXBTaEE2VlNienVnR3pkdEdNeEUyekRHVEkxOXFSQy96OUNEREM1ZTJTQUZqbEJUV0QyUHJjcU4KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K \ No newline at end of file diff --git a/pkg/clusterctl/client/testdata/executor_move/kustomization.yaml b/pkg/clusterctl/client/testdata/executor_move/kustomization.yaml deleted file mode 100644 index 64b49bda4..000000000 --- a/pkg/clusterctl/client/testdata/executor_move/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - kubeconfig.yaml \ No newline at end of file diff --git a/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.1/kustomization.yaml b/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.1/kustomization.yaml deleted file mode 100644 index 3ee92e092..000000000 --- a/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.1/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - version.yaml \ No newline at end of file diff --git a/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.1/version.yaml b/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.1/version.yaml deleted file mode 100644 index 8ed26986a..000000000 --- a/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.1/version.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: airshipit.org/v1alpha1 -kind: Testversion -metadata: - name: version-1 -spec: - version: v0.3.1 ---- -apiVersion: v1 -kind: Namespace -metadata: - labels: - control-plane: controller-manager - name: version-one diff --git a/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.2/kustomization.yaml b/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.2/kustomization.yaml deleted file mode 100644 index 3ee92e092..000000000 --- a/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.2/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - version.yaml \ No newline at end of file diff --git a/pkg/clusterctl/client/testdata/metadata.yaml b/pkg/clusterctl/client/testdata/metadata.yaml deleted file mode 100644 index d88db8f8c..000000000 --- a/pkg/clusterctl/client/testdata/metadata.yaml +++ /dev/null @@ -1,2 +0,0 @@ -phase: - path: executor_move \ No newline at end of file diff --git a/pkg/clusterctl/implementations/components_client.go b/pkg/clusterctl/implementations/components_client.go deleted file mode 100644 index 87bcb4641..000000000 --- a/pkg/clusterctl/implementations/components_client.go +++ /dev/null @@ -1,41 +0,0 @@ -/* - 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 - - https://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. -*/ - -package implementations - -import ( - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/repository" - - "opendev.org/airship/airshipctl/pkg/log" -) - -var _ repository.ComponentsClient = &ComponentsClient{} - -// ComponentsClient override Get() method to return same components, -// but in our implementation we skip variable substitution. -type ComponentsClient struct { - client repository.ComponentsClient - providerType string - providerName string - variableSubstitution bool -} - -// Get returns the components from a repository but without variable substitution -func (cc *ComponentsClient) Get(options repository.ComponentsOptions) (repository.Components, error) { - // Invert variable substitution, so that by default clusterctl will not substitute variables - options.SkipVariables = !cc.variableSubstitution - log.Printf("Getting airshipctl provider components, skipping variable substitution: %t.\n"+ - "Provider type: %s, name: %s\n", options.SkipVariables, cc.providerType, cc.providerName) - return cc.client.Get(options) -} diff --git a/pkg/clusterctl/implementations/errors.go b/pkg/clusterctl/implementations/errors.go deleted file mode 100644 index f82a6532b..000000000 --- a/pkg/clusterctl/implementations/errors.go +++ /dev/null @@ -1,55 +0,0 @@ -/* - 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 - - https://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. -*/ - -package implementations - -import ( - "fmt" -) - -// ErrVersionNotDefined is returned when requested version is not present in repository -type ErrVersionNotDefined struct { - Version string -} - -func (e ErrVersionNotDefined) Error() string { - return fmt.Sprintf(`version %s is not defined in the repository`, e.Version) -} - -// ErrNoVersionsAvailable is returned when version map is empty or not defined -type ErrNoVersionsAvailable struct { - Versions map[string]string -} - -func (e ErrNoVersionsAvailable) Error() string { - return fmt.Sprintf(`version map is empty or not defined, %v`, e.Versions) -} - -// ErrValueForVariableNotSet is returned when version map is empty or not defined -type ErrValueForVariableNotSet struct { - Variable string -} - -func (e ErrValueForVariableNotSet) Error() string { - return fmt.Sprintf("value for variable %q is not set", e.Variable) -} - -// ErrAppendNotAllowed is returned when version map is empty or not defined -type ErrAppendNotAllowed struct { - Variables map[string]string -} - -func (e ErrAppendNotAllowed) Error() string { - return fmt.Sprintf(`variables %v, are not allowed to be appended from clusterctl.AdditoinalVariables`, e.Variables) -} diff --git a/pkg/clusterctl/implementations/reader.go b/pkg/clusterctl/implementations/reader.go deleted file mode 100644 index 324587da8..000000000 --- a/pkg/clusterctl/implementations/reader.go +++ /dev/null @@ -1,155 +0,0 @@ -/* - 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 - - https://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. -*/ - -package implementations - -import ( - "os" - "regexp" - - clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" - "sigs.k8s.io/yaml" - - airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" - "opendev.org/airship/airshipctl/pkg/log" -) - -var _ config.Reader = &AirshipReader{} - -const ( - // TODO this must come as as ProviderConfigKey from clusterctl/client/config pkg - // see https://github.com/kubernetes-sigs/cluster-api/blob/master/cmd/clusterctl/client/config/imagemeta_client.go#L27 - imagesConfigKey = "images" -) - -// AirshipReader provides a reader implementation backed by a map -type AirshipReader struct { - variables map[string]string - varsFromEnv bool -} - -// configProvider is a mirror of config.Provider, re-implemented here in order to -// avoid circular dependencies between pkg/client/config and pkg/internal/test -type configProvider struct { - Name string `json:"name,omitempty"` - URL string `json:"url,omitempty"` - Type clusterctlv1.ProviderType `json:"type,omitempty"` -} - -type imageMeta struct { - Repository string `json:"repository,omitempty"` - Tag string `json:"tag,omitempty"` -} - -// Init implementation of clusterctl reader interface -// This is dummy method that is must be present to implement Reader interface -func (f *AirshipReader) Init(config string) error { - return nil -} - -// Get implementation of clusterctl reader interface -func (f *AirshipReader) Get(key string) (string, error) { - // if value is set in variables - return it, variables from variables map take precedence over - // env variables - if val, ok := f.variables[key]; ok { - return val, nil - } - // if we are allowed to check environment variables and key is allowed to be taken from env - // look it up and return - if f.varsFromEnv && allowFromEnv(key) { - val, ok := os.LookupEnv(key) - if ok { - return val, nil - } - } - // if neither env nor variables slice has the var, return error - return "", ErrValueForVariableNotSet{Variable: key} -} - -// Set implementation of clusterctl reader interface -func (f *AirshipReader) Set(key, value string) { - // TODO handle empty keys - f.variables[key] = value -} - -// UnmarshalKey implementation of clusterctl reader interface -func (f *AirshipReader) UnmarshalKey(key string, rawval interface{}) error { - data, err := f.Get(key) - if err != nil { - return err - } - return yaml.Unmarshal([]byte(data), rawval) -} - -func allowFromEnv(key string) bool { - variableRegEx := regexp.MustCompile(`^([A-Z0-9_$]+)$`) - log.Debugf("Verifying that variable %s is allowed to be taken from environment", key) - return variableRegEx.MatchString(key) -} - -func allowAppend(key, _ string) bool { - // TODO Investigate if more validation should be done here - forbiddenVars := map[string]string{ - config.ProvidersConfigKey: "", - imagesConfigKey: "", - } - _, forbid := forbiddenVars[key] - log.Debugf("Verifying that variable %s is allowed to be appended", key) - return !forbid -} - -// NewAirshipReader returns airship implementation of clusterctl reader interface -func NewAirshipReader(options *airshipv1.Clusterctl) (*AirshipReader, error) { - variables := map[string]string{} - providers := []configProvider{} - images := map[string]imageMeta{} - for _, prov := range options.Providers { - appendProvider := configProvider{ - Name: prov.Name, - Type: clusterctlv1.ProviderType(prov.Type), - URL: prov.URL, - } - providers = append(providers, appendProvider) - } - providersYaml, err := yaml.Marshal(providers) - if err != nil { - return nil, err - } - for key, val := range options.AdditionalComponentVariables { - // if variable is not allowed, it will be ignored - if allowAppend(key, val) { - variables[key] = val - } - } - - for key, val := range options.ImageMetas { - imageVal := imageMeta{ - Repository: val.Repository, - Tag: val.Tag, - } - images[key] = imageVal - } - imagesYaml, err := yaml.Marshal(images) - if err != nil { - return nil, err - } - // Add providers to config - variables[config.ProvidersConfigKey] = string(providersYaml) - variables[imagesConfigKey] = string(imagesYaml) - return &AirshipReader{ - variables: variables, - varsFromEnv: options.EnvVars, - }, nil -} diff --git a/pkg/clusterctl/implementations/reader_test.go b/pkg/clusterctl/implementations/reader_test.go deleted file mode 100644 index df3064dcc..000000000 --- a/pkg/clusterctl/implementations/reader_test.go +++ /dev/null @@ -1,319 +0,0 @@ -/* - 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 - - https://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. -*/ - -package implementations - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" - - airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" -) - -func makeValidOptions() *airshipv1.Clusterctl { - return &airshipv1.Clusterctl{ - Providers: []*airshipv1.Provider{ - { - Name: "metal3", - Type: "InfrastructureProvider", - Versions: map[string]string{ - "v0.3.1": "manifests/function/capm3/v0.3.1", - }, - }, - { - Name: "kubeadm", - Type: "BootstrapProvider", - Versions: map[string]string{ - "v0.3.3": "manifests/function/cabpk/v0.3.3", - }, - }, - { - Name: "cluster-api", - Type: "InfrastructureProvider", - Versions: map[string]string{ - "v0.3.3": "manifests/function/capi/v0.3.3", - }, - }, - { - Name: "kubeadm", - Type: "ControlPlaneProvider", - Versions: map[string]string{ - "v0.3.3": "manifests/function/cacpk/v0.3.3", - }, - }, - }, - ImageMetas: map[string]airshipv1.ImageMeta{ - "all": { - Repository: "myorg.io/all-repo", - }, - }, - } -} - -func TestNewReader(t *testing.T) { - tests := []struct { - name string - options *airshipv1.Clusterctl - }{ - { - // make sure we get no panic here - name: "pass empty options", - options: &airshipv1.Clusterctl{}, - }, - { - name: "pass airshipctl valid config", - options: makeValidOptions(), - }, - } - for _, tt := range tests { - options := tt.options - t.Run(tt.name, func(t *testing.T) { - reader, err := NewAirshipReader(options) - require.NoError(t, err) - assert.NotNil(t, reader) - }) - } -} - -func TestGet(t *testing.T) { - tests := []struct { - name string - options *airshipv1.Clusterctl - key string - expectedErr error - expectedResult string - }{ - { - // make sure we get no panic here - name: "pass empty options", - options: &airshipv1.Clusterctl{}, - key: "FOO", - expectedErr: ErrValueForVariableNotSet{Variable: "FOO"}, - }, - { - name: "pass airshipctl valid config", - options: makeValidOptions(), - key: "providers", - expectedErr: nil, - expectedResult: `- name: metal3 - type: InfrastructureProvider -- name: kubeadm - type: BootstrapProvider -- name: cluster-api - type: InfrastructureProvider -- name: kubeadm - type: ControlPlaneProvider -`, - }, - { - name: "image repo override for all clusterctl components", - options: makeValidOptions(), - key: "images", - expectedErr: nil, - expectedResult: `all: - repository: myorg.io/all-repo -`, - }, - { - name: "image override for cert-manager components", - options: &airshipv1.Clusterctl{ - ImageMetas: map[string]airshipv1.ImageMeta{ - "cert-manager": { - Repository: "myorg.io/certmanager-repo", - Tag: "v0.1", - }, - }, - }, - key: "images", - expectedErr: nil, - expectedResult: `cert-manager: - repository: myorg.io/certmanager-repo - tag: v0.1 -`, - }, - { - name: "image override for cainjector of cert-manager", - options: &airshipv1.Clusterctl{ - ImageMetas: map[string]airshipv1.ImageMeta{ - "cert-manager/cert-manager-cainjector": { - Repository: "myorg.io/certmanagercainjector-repo", - Tag: "v0.1", - }, - }, - }, - key: "images", - expectedErr: nil, - expectedResult: `cert-manager/cert-manager-cainjector: - repository: myorg.io/certmanagercainjector-repo - tag: v0.1 -`, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - reader, err := NewAirshipReader(tt.options) - require.NoError(t, err) - require.NotNil(t, reader) - value, err := reader.Get(tt.key) - assert.Equal(t, tt.expectedErr, err) - assert.Equal(t, tt.expectedResult, value) - }) - } -} - -func TestSetGet(t *testing.T) { - tests := []struct { - name string - setKey string - setGetValue string - expectedErr error - }{ - { - // should return empty string - name: "set simple key", - setKey: "FOO", - expectedErr: nil, - setGetValue: "", - }, - { - name: "set providers", - setKey: "providers", - expectedErr: nil, - setGetValue: `- name: metal3 - type: InfrastructureProvider -- name: kubeadm - type: BootstrapProvider -- name: cluster-api - type: InfrastructureProvider -- name: kubeadm - type: ControlPlaneProvider -`, - }, - { - // set empty - name: "empty key", - setKey: "", - setGetValue: "some key", - expectedErr: nil, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - reader, err := NewAirshipReader(&airshipv1.Clusterctl{}) - require.NoError(t, err) - require.NotNil(t, reader) - reader.Set(tt.setKey, tt.setGetValue) - result, err := reader.Get(tt.setKey) - require.Equal(t, tt.expectedErr, err) - assert.Equal(t, tt.setGetValue, result) - }) - } -} - -// Test verifies that options provider returns -func TestUnmarshalProviders(t *testing.T) { - options := &airshipv1.Clusterctl{ - Providers: []*airshipv1.Provider{ - { - Name: config.Metal3ProviderName, - Type: string(clusterctlv1.InfrastructureProviderType), - }, - { - Name: config.KubeadmBootstrapProviderName, - Type: string(clusterctlv1.BootstrapProviderType), - }, - { - Name: config.ClusterAPIProviderName, - Type: string(clusterctlv1.CoreProviderType), - }, - { - Name: config.KubeadmControlPlaneProviderName, - Type: string(clusterctlv1.ControlPlaneProviderType), - }, - }, - } - providers := []configProvider{} - reader, err := NewAirshipReader(options) - require.NoError(t, err) - require.NotNil(t, reader) - // check if we can unmarshal provider key into correct struct - err = reader.UnmarshalKey(config.ProvidersConfigKey, &providers) - require.NoError(t, err) - assert.Len(t, providers, 4) - for _, actualProvider := range providers { - assert.NotNil(t, options.Provider(actualProvider.Name, actualProvider.Type)) - } -} - -func TestUnmarshal(t *testing.T) { - tests := []struct { - name string - expectErr bool - variables map[string]string - getKey string - unmarshal interface{} - }{ - { - name: "unmarshal into nil", - getKey: "Foo", - expectErr: true, - }, - { - name: "value doesn't exist", - getKey: "Foo", - variables: map[string]string{}, - unmarshal: []configProvider{}, - expectErr: true, - }, - { - name: "value doesn't exist", - getKey: "foo", - expectErr: false, - variables: map[string]string{ - "foo": "foo: bar", - }, - unmarshal: &struct { - Foo string `json:"foo,omitempty"` - }{}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - reader, err := NewAirshipReader(&airshipv1.Clusterctl{}) - require.NoError(t, err) - require.NotNil(t, reader) - reader.variables = tt.variables - if tt.expectErr { - assert.Error(t, reader.UnmarshalKey(tt.getKey, tt.unmarshal)) - } else { - assert.NoError(t, reader.UnmarshalKey(tt.getKey, tt.unmarshal)) - } - }) - } -} - -// This test is simply for test coverage of the Reader interface -func TestInit(t *testing.T) { - reader, err := NewAirshipReader(&airshipv1.Clusterctl{}) - require.NoError(t, err) - require.NotNil(t, reader) - assert.NoError(t, reader.Init("anything")) -} diff --git a/pkg/clusterctl/implementations/repository.go b/pkg/clusterctl/implementations/repository.go deleted file mode 100644 index cf2bb68e1..000000000 --- a/pkg/clusterctl/implementations/repository.go +++ /dev/null @@ -1,139 +0,0 @@ -/* - 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 - - https://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. -*/ - -package implementations - -import ( - "bytes" - "path/filepath" - - "k8s.io/apimachinery/pkg/util/version" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/repository" - - "opendev.org/airship/airshipctl/pkg/document" - "opendev.org/airship/airshipctl/pkg/log" -) - -const ( - metaDataFilePath = "metadata.yaml" - dummyComponentPath = "components.yaml" -) - -// Repository implements Repository from clusterctl project -type Repository struct { - root string - versions map[string]string - defaultVersion string -} - -var _ repository.Repository = &Repository{} - -// ComponentsPath always returns same value, since it is not relevant without real filesystem -func (r *Repository) ComponentsPath() string { - return dummyComponentPath -} - -// GetVersions retrieve all versions from the repository -func (r *Repository) GetVersions() ([]string, error) { - versions := make([]string, 0, len(r.versions)) - for availableVersion := range r.versions { - _, err := version.ParseSemantic(availableVersion) - if err != nil { - // discard releases with tags that are not a valid semantic versions (the user can point explicitly to such releases) - continue - } - versions = append(versions, availableVersion) - } - return versions, nil -} - -// DefaultVersion highest version available -func (r *Repository) DefaultVersion() string { - return r.defaultVersion -} - -// RootPath not relevant without real filesystem -func (r *Repository) RootPath() string { - return r.root -} - -// GetFile returns all kubernetes resources that belong to cluster-api -func (r *Repository) GetFile(version string, filePath string) ([]byte, error) { - if version == "latest" { - // default should be latest - version = r.defaultVersion - } - - path, ok := r.versions[version] - if !ok { - return nil, ErrVersionNotDefined{Version: version} - } - kustomizePath := filepath.Join(r.root, path) - log.Debugf("Building cluster-api provider component documents from kustomize path at %s", kustomizePath) - bundle, err := document.NewBundleByPath(kustomizePath) - if err != nil { - return nil, err - } - // TODO when clusterctl will have a defined set of expected files in repository - // revisit this implementation - // metadata.yaml should return a bytes containing clusterctlv1.Metadata or error - if filePath == metaDataFilePath { - doc, errMeta := bundle.SelectOne(document.NewClusterctlMetadataSelector()) - if errMeta != nil { - return nil, errMeta - } - return doc.AsYAML() - } - filteredBundle, err := bundle.SelectBundle(document.NewDeployToK8sSelector()) - if err != nil { - return nil, err - } - - buffer := bytes.NewBuffer([]byte{}) - err = filteredBundle.Write(buffer) - if err != nil { - return nil, err - } - return buffer.Bytes(), nil -} - -// NewRepository builds instance of repository -func NewRepository(root string, versions map[string]string) (repository.Repository, error) { - var latestVersion *version.Version - var latestStringVersion string - // calculate latest version and delete versions that do not obey version syntax - for ver := range versions { - availableSemVersion, err := version.ParseSemantic(ver) - if err != nil { - // ignore and delete version if we can't parse it. - fmtMsg := "Invalid version %s in repository versions map %q, ignoring it. " + - "Version must obey the the Semantic Versioning specification (http://semver.org/)" - log.Debugf(fmtMsg, ver, versions) - // delete the version so actual version list is clean - delete(versions, ver) - continue - } - if latestVersion == nil || latestVersion.LessThan(availableSemVersion) { - latestVersion = availableSemVersion - latestStringVersion = ver - } - } - if latestStringVersion == "" { - return nil, ErrNoVersionsAvailable{Versions: versions} - } - return &Repository{ - root: root, - versions: versions, - defaultVersion: latestStringVersion}, nil -} diff --git a/pkg/clusterctl/implementations/repository_client.go b/pkg/clusterctl/implementations/repository_client.go deleted file mode 100644 index 06474dc73..000000000 --- a/pkg/clusterctl/implementations/repository_client.go +++ /dev/null @@ -1,45 +0,0 @@ -/* - 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 - - https://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. -*/ - -package implementations - -import ( - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/repository" - - "opendev.org/airship/airshipctl/pkg/log" -) - -var _ config.Provider = &RepositoryClient{} - -// RepositoryClient override Components() method to return same components client, -// but in our implementation we skip variable substitution. -type RepositoryClient struct { - repository.Client - VariableSubstitution bool - ProviderType string - ProviderName string -} - -// Components provide access to YAML file for creating provider components. -func (rc *RepositoryClient) Components() repository.ComponentsClient { - log.Debugf("Setting up airshipctl provider Components client\n"+ - "Provider type: %s, name: %s\n", rc.ProviderType, rc.ProviderName) - return &ComponentsClient{ - client: rc.Client.Components(), - providerName: rc.ProviderName, - providerType: rc.ProviderType, - variableSubstitution: rc.VariableSubstitution, - } -} diff --git a/pkg/clusterctl/implementations/repository_client_test.go b/pkg/clusterctl/implementations/repository_client_test.go deleted file mode 100644 index d51e66d5a..000000000 --- a/pkg/clusterctl/implementations/repository_client_test.go +++ /dev/null @@ -1,214 +0,0 @@ -/* - 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 - - https://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. -*/ - -package implementations - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" - clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" - clusterctlconfig "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" - "sigs.k8s.io/cluster-api/cmd/clusterctl/client/repository" - - airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" -) - -func TestRepositoryClient(t *testing.T) { - airRepoClient := testRepoClient(testRepoOpts{ - kustRoot: "functions/4", - envVars: false, - additionalVars: map[string]string{}, - }, t) - // get the components of the repository with empty options, all defaults should work - // SkipVariables is to true, to make sure that it is ignored in this implementation, and instead - // taken from airship clusterctl provider option, which disables var substitution by default - c, err := airRepoClient.Components().Get(repository.ComponentsOptions{SkipVariables: true}) - require.NoError(t, err) - // No errors must be returned since there is are no variables that need to be substituted - assert.NotNil(t, c) - // Make sure that target namespace is the same as defined by repository implementation bundle - assert.Equal(t, "newnamespace", c.TargetNamespace()) - // Make sure that variables for substitution are actually found - require.Len(t, c.Variables(), 1) - // make sure that variable name is correct - assert.Equal(t, "PROVISIONING_IP", c.Variables()[0]) -} - -func TestMissingVariableRepoClient(t *testing.T) { - airRepoClient := testRepoClient(testRepoOpts{ - kustRoot: "functions/5", - envVars: true, - additionalVars: map[string]string{}, - varSubstitution: true, - }, t) - envVars := map[string]string{ - "AZURE_SUBSCRIPTION_ID_B64": "c29tZS1iYXNlNjQtSUQtdGV4dAo=", - "AZURE_TENANT_ID_B64": "c29tZS1iYXNlNjQtVEVOQU5ULUlELXRleHQK", - "AZURE_CLIENT_ID_B64": "c29tZS1iYXNlNjQtQ0xJRU5ULUlELXRleHQK", - } - for key, val := range envVars { - os.Setenv(key, val) - defer os.Unsetenv(key) - } - c, err := airRepoClient.Components().Get(repository.ComponentsOptions{}) - require.Error(t, err) - assert.Contains(t, err.Error(), `value for variables [AZURE_CLIENT_SECRET_B64] is not set`) - assert.Nil(t, c) -} - -func TestEnvVariableSubstitutionRepoClient(t *testing.T) { - airRepoClient := testRepoClient(testRepoOpts{ - kustRoot: "functions/5", - envVars: true, - additionalVars: map[string]string{}, - varSubstitution: true, - }, t) - envVars := map[string]string{ - "AZURE_SUBSCRIPTION_ID_B64": "c29tZS1iYXNlNjQtSUQtdGV4dAo=", - "AZURE_TENANT_ID_B64": "c29tZS1iYXNlNjQtVEVOQU5ULUlELXRleHQK", - "AZURE_CLIENT_ID_B64": "c29tZS1iYXNlNjQtQ0xJRU5ULUlELXRleHQK", - "AZURE_CLIENT_SECRET_B64": "c29tZS1iYXNlNjQtQ0xJRU5ULVNFQ1JFVC10ZXh0Cg==", - } - for key, val := range envVars { - os.Setenv(key, val) - defer os.Unsetenv(key) - } - c, err := airRepoClient.Components().Get(repository.ComponentsOptions{}) - require.NoError(t, err) - assert.NotNil(t, c) - assert.Len(t, c.Variables(), len(dataKeyMapping())) - // find secret containing env variables - for _, obj := range c.InstanceObjs() { - if obj.GetKind() == "Secret" { - cm := &v1.ConfigMap{} - err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), cm) - require.NoError(t, err) - for key, expectedVal := range envVars { - dataKey, exists := dataKeyMapping()[key] - require.True(t, exists) - actualVal, exists := cm.Data[dataKey] - require.True(t, exists) - assert.Equal(t, expectedVal, actualVal) - } - } - } -} - -func TestAdditionalVariableSubstitutionRepoClient(t *testing.T) { - vars := map[string]string{ - "AZURE_SUBSCRIPTION_ID_B64": "c29tZS1iYXNlNjQtSUQtdGV4dAo=", - "AZURE_TENANT_ID_B64": "c29tZS1iYXNlNjQtVEVOQU5ULUlELXRleHQK", - "AZURE_CLIENT_ID_B64": "c29tZS1iYXNlNjQtQ0xJRU5ULUlELXRleHQK", - "AZURE_CLIENT_SECRET_B64": "c29tZS1iYXNlNjQtc2VjcmV0Cg==", - } - - airRepoClient := testRepoClient(testRepoOpts{ - kustRoot: "functions/5", - envVars: false, - additionalVars: vars, - varSubstitution: true, - }, t) - - c, err := airRepoClient.Components().Get(repository.ComponentsOptions{}) - require.NoError(t, err) - assert.NotNil(t, c) - assert.Len(t, c.Variables(), len(dataKeyMapping())) - - for _, obj := range c.InstanceObjs() { - if obj.GetKind() == "Secret" { - cm := &v1.ConfigMap{} - err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), cm) - require.NoError(t, err) - for key, expectedVal := range vars { - dataKey, exists := dataKeyMapping()[key] - require.True(t, exists) - actualVal, exists := cm.Data[dataKey] - require.True(t, exists) - assert.Equal(t, expectedVal, actualVal) - } - } - } -} - -type testRepoOpts struct { - kustRoot string - envVars bool - additionalVars map[string]string - varSubstitution bool -} - -func testRepoClient(opts testRepoOpts, t *testing.T) repository.Client { - t.Helper() - providerName := "metal3" - providerType := "InfrastructureProvider" - // this version contains a variable that is suppose to be substituted by clusterctl - // and we will test if the variable is found and not substituted - versions := map[string]string{ - "v0.2.3": opts.kustRoot, - } - cctl := &airshipv1.Clusterctl{ - AdditionalComponentVariables: opts.additionalVars, - EnvVars: opts.envVars, - Providers: []*airshipv1.Provider{ - { - Name: providerName, - Type: providerType, - URL: "/dummy/path/v0.3.2/components.yaml", - Versions: versions, - }, - }, - } - // create instance of airship reader interface implementation for clusterctl and inject it - reader, err := NewAirshipReader(cctl) - require.NoError(t, err) - require.NotNil(t, reader) - optionReader := clusterctlconfig.InjectReader(reader) - require.NotNil(t, optionReader) - configClient, err := clusterctlconfig.New("", optionReader) - require.NoError(t, err) - require.NotNil(t, configClient) - // get the provider from configuration client, in which we injected our reader - provider, err := configClient.Providers().Get(providerName, clusterctlv1.ProviderType(providerType)) - require.NoError(t, err) - require.NotNil(t, provider) - // Create instance of airship repository interface implementation for clusterctl - repo, err := NewRepository("testdata", versions) - require.NoError(t, err) - require.NotNil(t, repo) - // Inject the repository in repository client - optionsRepo := repository.InjectRepository(repo) - repoClient, err := repository.New(provider, configClient, optionsRepo) - require.NoError(t, err) - require.NotNil(t, repoClient) - return &RepositoryClient{ - ProviderName: providerName, - ProviderType: providerType, - Client: repoClient, - VariableSubstitution: opts.varSubstitution, - } -} - -func dataKeyMapping() map[string]string { - return map[string]string{ - "AZURE_SUBSCRIPTION_ID_B64": "subscription-id", - "AZURE_TENANT_ID_B64": "tenant-id", - "AZURE_CLIENT_ID_B64": "client-id", - "AZURE_CLIENT_SECRET_B64": "client-secret", - } -} diff --git a/pkg/clusterctl/implementations/repository_test.go b/pkg/clusterctl/implementations/repository_test.go deleted file mode 100644 index f474b060f..000000000 --- a/pkg/clusterctl/implementations/repository_test.go +++ /dev/null @@ -1,302 +0,0 @@ -/* - 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 - - https://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. -*/ - -package implementations_test - -import ( - "sort" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - versionclient "k8s.io/apimachinery/pkg/util/version" - clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" - "sigs.k8s.io/yaml" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "opendev.org/airship/airshipctl/pkg/clusterctl/implementations" -) - -type Version struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec VersionSpec `json:"spec"` -} - -type VersionSpec struct { - Version string `json:"version"` -} - -func TestNewRepository(t *testing.T) { - tests := []struct { - name string - root string - versions map[string]string - defaultVersion string - Error error - }{ - { - name: "simple repository success", - root: "testdata", - versions: map[string]string{ - "v0.0.1": "functions/capi", - }, - Error: nil, - defaultVersion: "v0.0.1", - }, - { - name: "invalid version", - root: "testdata", - versions: map[string]string{ - "malformed-version": "functions/capi", - }, - Error: implementations.ErrNoVersionsAvailable{Versions: map[string]string{}}, - }, - { - name: "multiple repository versions", - root: "testdata", - versions: map[string]string{ - "v0.0.1": "functions/1", - "v0.2.3": "functions/2", - "v7.0.2": "functions/3", - "v0.3.2": "functions/4", - "v4.0.2": "functions/5", - "v1.0.2": "functions/6", - }, - Error: nil, - defaultVersion: "v7.0.2", - }, - { - name: "Empty version", - root: "testdata", - versions: map[string]string{}, - Error: implementations.ErrNoVersionsAvailable{Versions: map[string]string{}}, - }, - } - - for _, tt := range tests { - repo, err := implementations.NewRepository(tt.root, tt.versions) - expectedErr := tt.Error - defaultVersion := tt.defaultVersion - t.Run(tt.name, func(t *testing.T) { - if expectedErr != nil { - assert.Equal(t, expectedErr, err) - assert.Nil(t, repo) - } else { - assert.NoError(t, err) - assert.NotNil(t, repo) - assert.Equal(t, defaultVersion, repo.DefaultVersion()) - } - }) - } -} - -func TestGetFile(t *testing.T) { - tests := []struct { - name string - root string - versions map[string]string - expectErr bool - resultVersion string - versionToUse string - fileToUse string - resultContract string - }{ - { - name: "single version", - root: "testdata", - versions: map[string]string{ - "v0.0.1": "functions/1", - }, - expectErr: false, - resultVersion: "v0.0.1", - versionToUse: "v0.0.1", - }, - { - name: "latest version", - root: "testdata", - versions: map[string]string{ - "v0.0.1": "functions/1", - "v0.0.2": "functions/2", - "v0.0.3": "functions/3", - }, - expectErr: false, - resultVersion: "v0.0.3", - versionToUse: "latest", - }, - { - name: "failed to bundle", - root: "testdata", - versions: map[string]string{ - "v1.3.2": "does-not-exist", - }, - versionToUse: "v1.3.2", - expectErr: true, - }, - { - name: "multiple repository versions", - root: "testdata", - versions: map[string]string{ - "v0.0.1": "functions/1", - "v0.2.3": "functions/2", - "v7.0.2": "functions/3", - }, - expectErr: false, - resultVersion: "v0.0.2", - versionToUse: "v0.2.3", - }, - { - name: "version doesn't exist", - root: "testdata", - versions: map[string]string{ - "v1.3.2": "does-not-exist", - }, - versionToUse: "v1.3.3", - expectErr: true, - }, - { - name: "test valid metadata", - root: "testdata", - versions: map[string]string{ - "v0.2.3": "functions/2", - }, - expectErr: false, - versionToUse: "v0.2.3", - fileToUse: "metadata.yaml", - resultContract: "v1alpha2", - }, - { - name: "test valid metadata", - root: "testdata", - versions: map[string]string{ - "v0.2.0": "functions/1", - }, - expectErr: true, - versionToUse: "v0.2.3", - fileToUse: "metadata.yaml", - resultContract: "v1alpha2", - }, - } - for _, tt := range tests { - root := tt.root - versions := tt.versions - resultVersion := tt.resultVersion - versionToUse := tt.versionToUse - expectErr := tt.expectErr - fileToUse := tt.fileToUse - resultContract := tt.resultContract - t.Run(tt.name, func(t *testing.T) { - repo, err := implementations.NewRepository(root, versions) - require.NoError(t, err) - assert.NotNil(t, repo) - b, err := repo.GetFile(versionToUse, fileToUse) - if expectErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - if fileToUse == "metadata.yaml" { - gotMetadata := metadata(t, b) - parsedVersion, err := versionclient.ParseSemantic(versionToUse) - require.NoError(t, err) - assert.Equal(t, resultContract, gotMetadata.GetReleaseSeriesForVersion(parsedVersion).Contract) - } else { - gotVersion := version(t, b) - assert.Equal(t, resultVersion, gotVersion.Spec.Version) - } - } - }) - } -} - -func version(t *testing.T, versionBytes []byte) *Version { - t.Helper() - ver := &Version{} - - err := yaml.Unmarshal(versionBytes, ver) - require.NoError(t, err) - return ver -} - -func metadata(t *testing.T, metadataBytes []byte) *clusterctlv1.Metadata { - t.Helper() - m := &clusterctlv1.Metadata{} - err := yaml.Unmarshal(metadataBytes, m) - require.NoError(t, err) - return m -} - -func TestComponentsPath(t *testing.T) { - versions := map[string]string{ - "v0.0.1": "functions/1", - } - repo, err := implementations.NewRepository("testdata", versions) - require.NoError(t, err) - assert.NotEmpty(t, repo.ComponentsPath()) -} - -func TestRootPath(t *testing.T) { - versions := map[string]string{ - "v0.0.1": "functions/1", - } - repo, err := implementations.NewRepository("testdata", versions) - require.NoError(t, err) - assert.Equal(t, "testdata", repo.RootPath()) -} - -func TestGetVersions(t *testing.T) { - tests := []struct { - name string - root string - versions map[string]string - expectedVersions []string - }{ - { - name: "single version", - root: "testdata", - versions: map[string]string{ - "v0.0.1": "functions/1", - }, - expectedVersions: []string{"v0.0.1"}, - }, - { - name: "multiple repository versions", - root: "testdata", - versions: map[string]string{ - "v0.0.1": "functions/1", - "v0.2.3": "functions/2", - "v7.0.2": "functions/3", - "malformed-version": "doesn't matter", - }, - expectedVersions: []string{"v0.0.1", "v0.2.3", "v7.0.2"}, - }, - } - - for _, tt := range tests { - root := tt.root - versions := tt.versions - expectedVersions := tt.expectedVersions - t.Run(tt.name, func(t *testing.T) { - repo, err := implementations.NewRepository(root, versions) - require.NoError(t, err) - actualVersions, err := repo.GetVersions() - assert.NoError(t, err) - // this will make sure that slices are sorted in a same way - sort.Strings(expectedVersions) - sort.Strings(actualVersions) - assert.Equal(t, expectedVersions, actualVersions) - }) - } -} diff --git a/pkg/clusterctl/implementations/testdata/functions/1/kustomization.yaml b/pkg/clusterctl/implementations/testdata/functions/1/kustomization.yaml deleted file mode 100644 index 3ee92e092..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/1/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - version.yaml \ No newline at end of file diff --git a/pkg/clusterctl/implementations/testdata/functions/1/version.yaml b/pkg/clusterctl/implementations/testdata/functions/1/version.yaml deleted file mode 100644 index dc76bf228..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/1/version.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: airshipit.org/v1alpha1 -kind: Testversion -metadata: - name: version-1 -spec: - version: v0.0.1 diff --git a/pkg/clusterctl/implementations/testdata/functions/2/kustomization.yaml b/pkg/clusterctl/implementations/testdata/functions/2/kustomization.yaml deleted file mode 100644 index 3ee92e092..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/2/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - version.yaml \ No newline at end of file diff --git a/pkg/clusterctl/implementations/testdata/functions/3/kustomization.yaml b/pkg/clusterctl/implementations/testdata/functions/3/kustomization.yaml deleted file mode 100644 index 3ee92e092..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/3/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - version.yaml \ No newline at end of file diff --git a/pkg/clusterctl/implementations/testdata/functions/3/version.yaml b/pkg/clusterctl/implementations/testdata/functions/3/version.yaml deleted file mode 100644 index f42d675a6..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/3/version.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: airshipit.org/v1alpha1 -kind: Testversion -metadata: - name: version-3 -spec: - version: v0.0.3 diff --git a/pkg/clusterctl/implementations/testdata/functions/4/dnsmasq.conf b/pkg/clusterctl/implementations/testdata/functions/4/dnsmasq.conf deleted file mode 100644 index 455931b41..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/4/dnsmasq.conf +++ /dev/null @@ -1 +0,0 @@ -dhcp-boot=tag:ipxe,http://${PROVISIONING_IP}:80/dualboot.ipxe diff --git a/pkg/clusterctl/implementations/testdata/functions/4/kustomization.yaml b/pkg/clusterctl/implementations/testdata/functions/4/kustomization.yaml deleted file mode 100644 index 983f1851a..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/4/kustomization.yaml +++ /dev/null @@ -1,12 +0,0 @@ -resources: - - resources.yaml - -generatorOptions: - disableNameSuffixHash: true - -## this contains a variable that matches a regexp for clusterctl variable subsitution -## check the regexp here https://github.com/kubernetes-sigs/cluster-api/blob/v0.3.5/cmd/clusterctl/client/repository/components.go#L55 -configMapGenerator: -- name: ironic-config-files - files: - - dnsmasq.conf diff --git a/pkg/clusterctl/implementations/testdata/functions/4/resources.yaml b/pkg/clusterctl/implementations/testdata/functions/4/resources.yaml deleted file mode 100644 index 360417576..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/4/resources.yaml +++ /dev/null @@ -1,17 +0,0 @@ -## contains a namespace that should be idenitifed by components interface, ---- -apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 -kind: Metadata -metadata: - name: repository-metadata -releaseSeries: -- major: 0 - minor: 3 - contract: v1alpha3 -- major: 0 - minor: 2 - contract: v1alpha2 ---- -kind: Namespace -metadata: - name: newnamespace diff --git a/pkg/clusterctl/implementations/testdata/functions/5/azure-resources.yaml b/pkg/clusterctl/implementations/testdata/functions/5/azure-resources.yaml deleted file mode 100644 index 9e6934326..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/5/azure-resources.yaml +++ /dev/null @@ -1,29 +0,0 @@ -## contains a namespace that should be idenitifed by components interface, ---- -apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 -kind: Metadata -metadata: - name: repository-metadata -releaseSeries: -- major: 0 - minor: 3 - contract: v1alpha3 -- major: 0 - minor: 2 - contract: v1alpha2 ---- -kind: Namespace -metadata: - name: newnamespace ---- -apiVersion: v1 -kind: Secret -metadata: - name: manager-bootstrap-credentials - namespace: system -type: Opaque -data: - subscription-id: ${AZURE_SUBSCRIPTION_ID_B64} - tenant-id: ${AZURE_TENANT_ID_B64} - client-id: ${AZURE_CLIENT_ID_B64} - client-secret: ${AZURE_CLIENT_SECRET_B64} \ No newline at end of file diff --git a/pkg/clusterctl/implementations/testdata/functions/5/kustomization.yaml b/pkg/clusterctl/implementations/testdata/functions/5/kustomization.yaml deleted file mode 100644 index 35440e624..000000000 --- a/pkg/clusterctl/implementations/testdata/functions/5/kustomization.yaml +++ /dev/null @@ -1,3 +0,0 @@ -# Contains variables that should be substituted -resources: - - azure-resources.yaml diff --git a/pkg/document/constants.go b/pkg/document/constants.go index 81014c9f4..edfff6d38 100644 --- a/pkg/document/constants.go +++ b/pkg/document/constants.go @@ -48,6 +48,15 @@ const ( // CRDKind is a kind for custom resource definition documents CRDKind = "CustomResourceDefinition" + + // ClusterctlContainerGroup defines Group for clustertctl container + ClusterctlContainerGroup = "airshipit.org" + // ClusterctlContainerVersion defines Version for clustertctl container + ClusterctlContainerVersion = "v1alpha1" + // ClusterctlContainerKind defines Kind for clustertctl container + ClusterctlContainerKind = "GenericContainer" + // ClusterctlContainerName defines Name for clustertctl container + ClusterctlContainerName = "clusterctl" ) // KustomizationFile is used for kustomization file diff --git a/pkg/document/selectors.go b/pkg/document/selectors.go index ba7814711..c9e1b62ef 100644 --- a/pkg/document/selectors.go +++ b/pkg/document/selectors.go @@ -202,3 +202,11 @@ func NewValidatorExecutorSelector() Selector { func NewCRDSelector() Selector { return NewSelector().ByKind(CRDKind) } + +// NewClusterctlContainerExecutorSelector returns selector to get executor documents for clusterctl container +func NewClusterctlContainerExecutorSelector() Selector { + return NewSelector().ByGvk(ClusterctlContainerGroup, + ClusterctlContainerVersion, + ClusterctlContainerKind). + ByName(ClusterctlContainerName) +} diff --git a/pkg/k8s/kubeconfig/builder.go b/pkg/k8s/kubeconfig/builder.go index d47e6e46c..f5a7f2cbc 100644 --- a/pkg/k8s/kubeconfig/builder.go +++ b/pkg/k8s/kubeconfig/builder.go @@ -23,7 +23,6 @@ import ( "opendev.org/airship/airshipctl/pkg/api/v1alpha1" "opendev.org/airship/airshipctl/pkg/cluster/clustermap" - "opendev.org/airship/airshipctl/pkg/clusterctl/client" "opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/fs" "opendev.org/airship/airshipctl/pkg/k8s/utils" @@ -237,7 +236,7 @@ func (b *Builder) fromClusterAPI(clusterName string, ref v1alpha1.KubeconfigSour log.Debugf("Getting child kubeconfig from parent, parent context '%s', parent kubeconfig '%s'", parentContext, f) - return FromSecret(b.client, &client.GetKubeconfigOptions{ + return FromSecret(b.client, &v1alpha1.GetKubeconfigOptions{ Timeout: ref.Timeout, ManagedClusterNamespace: ref.Namespace, ManagedClusterName: ref.Name, diff --git a/pkg/k8s/kubeconfig/kubeconfig.go b/pkg/k8s/kubeconfig/kubeconfig.go index a2e5df1b1..cda64cc7b 100644 --- a/pkg/k8s/kubeconfig/kubeconfig.go +++ b/pkg/k8s/kubeconfig/kubeconfig.go @@ -28,7 +28,6 @@ import ( "sigs.k8s.io/yaml" "opendev.org/airship/airshipctl/pkg/api/v1alpha1" - "opendev.org/airship/airshipctl/pkg/clusterctl/client" "opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/fs" "opendev.org/airship/airshipctl/pkg/log" @@ -113,7 +112,7 @@ func FromAPIalphaV1(apiObj *v1alpha1.KubeConfig) KubeSourceFunc { } // FromSecret returns KubeSource type, uses client interface to kubernetes cluster -func FromSecret(c corev1.CoreV1Interface, o *client.GetKubeconfigOptions) KubeSourceFunc { +func FromSecret(c corev1.CoreV1Interface, o *v1alpha1.GetKubeconfigOptions) KubeSourceFunc { return func() ([]byte, error) { if o.ManagedClusterName == "" { return nil, ErrClusterNameEmpty{} diff --git a/pkg/k8s/kubeconfig/kubeconfig_test.go b/pkg/k8s/kubeconfig/kubeconfig_test.go index c183007dc..1bfba5958 100644 --- a/pkg/k8s/kubeconfig/kubeconfig_test.go +++ b/pkg/k8s/kubeconfig/kubeconfig_test.go @@ -35,7 +35,6 @@ import ( kustfs "sigs.k8s.io/kustomize/api/filesys" "opendev.org/airship/airshipctl/pkg/api/v1alpha1" - "opendev.org/airship/airshipctl/pkg/clusterctl/client" "opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/fs" "opendev.org/airship/airshipctl/pkg/k8s/kubeconfig" @@ -220,7 +219,7 @@ func (s *SecretMockInterface) Patch(_ string, _ types.PatchType, _ []byte, _ ... func TestFromSecret(t *testing.T) { tests := []struct { name string - options *client.GetKubeconfigOptions + options *v1alpha1.GetKubeconfigOptions getSecret *apiv1.Secret getErr error expectedData []byte @@ -228,30 +227,30 @@ func TestFromSecret(t *testing.T) { }{ { name: "empty cluster name", - options: &client.GetKubeconfigOptions{}, + options: &v1alpha1.GetKubeconfigOptions{}, expectedErr: kubeconfig.ErrClusterNameEmpty{}, }, { name: "multiple retries and error", - options: &client.GetKubeconfigOptions{ManagedClusterName: "cluster", Timeout: "1s"}, + options: &v1alpha1.GetKubeconfigOptions{ManagedClusterName: "cluster", Timeout: "1s"}, getErr: errors.New("error"), expectedErr: wait.ErrWaitTimeout, }, { name: "empty secret object", - options: &client.GetKubeconfigOptions{ManagedClusterName: "cluster"}, + options: &v1alpha1.GetKubeconfigOptions{ManagedClusterName: "cluster"}, getSecret: &apiv1.Secret{}, expectedErr: kubeconfig.ErrMalformedKubeconfig{ClusterName: "cluster"}, }, { name: "empty data value", - options: &client.GetKubeconfigOptions{ManagedClusterName: "cluster"}, + options: &v1alpha1.GetKubeconfigOptions{ManagedClusterName: "cluster"}, getSecret: &apiv1.Secret{Data: map[string][]byte{"value": {}}}, expectedErr: kubeconfig.ErrMalformedKubeconfig{ClusterName: "cluster"}, }, { name: "successfully get kubeconfig", - options: &client.GetKubeconfigOptions{ManagedClusterName: "cluster"}, + options: &v1alpha1.GetKubeconfigOptions{ManagedClusterName: "cluster"}, getSecret: &apiv1.Secret{Data: map[string][]byte{"value": []byte(testValidKubeconfig)}}, expectedData: []byte(testValidKubeconfig), }, diff --git a/pkg/phase/executors/clusterctl.go b/pkg/phase/executors/clusterctl.go old mode 100755 new mode 100644 index 1a8e0464b..ca41e8343 --- a/pkg/phase/executors/clusterctl.go +++ b/pkg/phase/executors/clusterctl.go @@ -18,11 +18,16 @@ import ( "bytes" "fmt" "io" + "net/url" + "os" + "path/filepath" "strings" + "sigs.k8s.io/kustomize/kyaml/yaml" + airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" "opendev.org/airship/airshipctl/pkg/cluster/clustermap" - "opendev.org/airship/airshipctl/pkg/clusterctl/client" + "opendev.org/airship/airshipctl/pkg/container" "opendev.org/airship/airshipctl/pkg/document" airerrors "opendev.org/airship/airshipctl/pkg/errors" "opendev.org/airship/airshipctl/pkg/events" @@ -33,62 +38,236 @@ import ( "opendev.org/airship/airshipctl/pkg/phase/ifc" ) +const clusterAPIOverrides = "/workdir/.cluster-api/overrides" + var _ ifc.Executor = &ClusterctlExecutor{} // ClusterctlExecutor phase executor type ClusterctlExecutor struct { clusterName string + targetPath string - client.Interface clusterMap clustermap.ClusterMap options *airshipv1.Clusterctl kubecfg kubeconfig.Interface + execObj *airshipv1.GenericContainer + clientFunc container.ClientV1Alpha1FactoryFunc + cctlOpts *airshipv1.ClusterctlOptions } -// NewClusterctlExecutor creates instance of 'clusterctl init' phase executor +var typeMap = map[string]string{ + airshipv1.BootstrapProviderType: "bootstrap", + airshipv1.ControlPlaneProviderType: "control-plane", + airshipv1.InfrastructureProviderType: "infrastructure", + airshipv1.CoreProviderType: "core", +} + +// NewClusterctlExecutor creates instance of 'clusterctl' phase executor func NewClusterctlExecutor(cfg ifc.ExecutorConfig) (ifc.Executor, error) { options := airshipv1.DefaultClusterctl() if err := cfg.ExecutorDocument.ToAPIObject(options, airshipv1.Scheme); err != nil { return nil, err } - client, err := client.NewClient(cfg.TargetPath, log.DebugEnabled(), options) + cctlOpts := &airshipv1.ClusterctlOptions{ + Components: map[string][]byte{}, + } + if err := initRepoData(options, cctlOpts, cfg.TargetPath); err != nil { + return nil, err + } + + doc, err := cfg.PhaseConfigBundle.SelectOne(document.NewClusterctlContainerExecutorSelector()) if err != nil { return nil, err } + + apiObj := airshipv1.DefaultGenericContainer() + err = doc.ToAPIObject(apiObj, airshipv1.Scheme) + if err != nil { + return nil, err + } + + clientFunc := container.NewClientV1Alpha1 + if cfg.ContainerFunc != nil { + clientFunc = cfg.ContainerFunc + } + return &ClusterctlExecutor{ clusterName: cfg.ClusterName, - Interface: client, options: options, + cctlOpts: cctlOpts, kubecfg: cfg.KubeConfig, clusterMap: cfg.ClusterMap, + targetPath: cfg.TargetPath, + execObj: apiObj, + clientFunc: clientFunc, }, nil } +func initRepoData(c *airshipv1.Clusterctl, o *airshipv1.ClusterctlOptions, targetPath string) error { + for _, prv := range c.Providers { + rURL, err := url.Parse(prv.URL) + if err != nil { + return err + } + if rURL.Scheme != "" || filepath.IsAbs(prv.URL) { + continue + } + + componentDir := filepath.Join(clusterAPIOverrides, + fmt.Sprintf("%s-%s", typeMap[prv.Type], prv.Name), filepath.Base(prv.URL)) + if prv.Type == airshipv1.CoreProviderType { + componentDir = filepath.Join(clusterAPIOverrides, prv.Name, filepath.Base(prv.URL)) + } + + kustomizePath := filepath.Join(targetPath, prv.URL) + log.Debugf("Building cluster-api provider component documents from kustomize path at '%s'", kustomizePath) + bundle, err := document.NewBundleByPath(kustomizePath) + if err != nil { + return err + } + doc, err := bundle.SelectOne(document.NewClusterctlMetadataSelector()) + if err != nil { + return err + } + metadata, err := doc.AsYAML() + if err != nil { + return err + } + + o.Components[filepath.Join(componentDir, "metadata.yaml")] = metadata + + filteredBundle, err := bundle.SelectBundle(document.NewDeployToK8sSelector()) + if err != nil { + return err + } + + buffer := &bytes.Buffer{} + if err = filteredBundle.Write(buffer); err != nil { + return err + } + prv.URL = filepath.Join(componentDir, fmt.Sprintf("%s-components.yaml", typeMap[prv.Type])) + o.Components[prv.URL] = buffer.Bytes() + } + return nil +} + // Run clusterctl init as a phase runner func (c *ClusterctlExecutor) Run(evtCh chan events.Event, opts ifc.RunOptions) { defer close(evtCh) + + if log.DebugEnabled() { + c.cctlOpts.CmdOptions = append(c.cctlOpts.CmdOptions, "-v5") + } + + cctlConfig := map[string]interface{}{ + "providers": c.options.Providers, + "images": c.options.ImageMetas, + } + for k, v := range c.options.AdditionalComponentVariables { + cctlConfig[k] = v + } + + var err error + c.cctlOpts.Config, err = yaml.Marshal(cctlConfig) + if err != nil { + handleError(evtCh, err) + } + switch c.options.Action { - case airshipv1.Move: - c.move(opts, evtCh) case airshipv1.Init: - c.init(opts, evtCh) + c.init(evtCh) + case airshipv1.Move: + c.move(opts.DryRun, evtCh) default: handleError(evtCh, errors.ErrUnknownExecutorAction{Action: string(c.options.Action), ExecutorName: "clusterctl"}) } } -func (c *ClusterctlExecutor) move(opts ifc.RunOptions, evtCh chan events.Event) { - evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ - Operation: events.ClusterctlMoveStart, - Message: "starting clusterctl move executor", - }) - ns := c.options.MoveOptions.Namespace +func (c *ClusterctlExecutor) run() error { + opts, err := yaml.Marshal(c.cctlOpts) + if err != nil { + return err + } + c.execObj.Config = string(opts) + return c.clientFunc("", &bytes.Buffer{}, os.Stdout, c.execObj, c.targetPath).Run() +} + +func (c *ClusterctlExecutor) getKubeconfig() (string, string, func(), error) { kubeConfigFile, cleanup, err := c.kubecfg.GetFile() + if err != nil { + return "", "", nil, err + } + + context, err := c.clusterMap.ClusterKubeconfigContext(c.clusterName) + if err != nil { + cleanup() + return "", "", nil, err + } + + c.execObj.Spec.StorageMounts = append(c.execObj.Spec.StorageMounts, airshipv1.StorageMount{ + MountType: "bind", + Src: kubeConfigFile, + DstPath: kubeConfigFile, + ReadWriteMode: false, + }) + return kubeConfigFile, context, cleanup, nil +} + +func (c *ClusterctlExecutor) init(evtCh chan events.Event) { + evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ + Operation: events.ClusterctlInitStart, + Message: "starting clusterctl init executor", + }) + + kubecfg, context, cleanup, err := c.getKubeconfig() if err != nil { handleError(evtCh, err) return } defer cleanup() + + c.cctlOpts.CmdOptions = append(c.cctlOpts.CmdOptions, + "init", + "--kubeconfig", kubecfg, + "--kubeconfig-context", context, + ) + + initMap := map[string]string{ + typeMap[airshipv1.BootstrapProviderType]: c.options.InitOptions.BootstrapProviders, + typeMap[airshipv1.ControlPlaneProviderType]: c.options.InitOptions.ControlPlaneProviders, + typeMap[airshipv1.InfrastructureProviderType]: c.options.InitOptions.InfrastructureProviders, + typeMap[airshipv1.CoreProviderType]: c.options.InitOptions.CoreProvider, + } + for k, v := range initMap { + if v != "" { + c.cctlOpts.CmdOptions = append(c.cctlOpts.CmdOptions, fmt.Sprintf("--%s=%s", k, v)) + } + } + + if err = c.run(); err != nil { + handleError(evtCh, err) + return + } + + eventMsg := "clusterctl init completed successfully" + evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ + Operation: events.ClusterctlInitEnd, + Message: eventMsg, + }) +} + +func (c *ClusterctlExecutor) move(dryRun bool, evtCh chan events.Event) { + evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ + Operation: events.ClusterctlMoveStart, + Message: "starting clusterctl move executor", + }) + kubecfg, context, cleanup, err := c.getKubeconfig() + if err != nil { + handleError(evtCh, err) + return + } + defer cleanup() + fromCluster, err := c.clusterMap.ParentCluster(c.clusterName) if err != nil { handleError(evtCh, err) @@ -99,78 +278,36 @@ func (c *ClusterctlExecutor) move(opts ifc.RunOptions, evtCh chan events.Event) handleError(evtCh, err) return } - toContext, err := c.clusterMap.ClusterKubeconfigContext(c.clusterName) - if err != nil { + + c.cctlOpts.CmdOptions = append( + c.cctlOpts.CmdOptions, + "move", + "--kubeconfig", kubecfg, + "--kubeconfig-context", fromContext, + "--to-kubeconfig", kubecfg, + "--to-kubeconfig-context", context, + "--namespace", c.options.MoveOptions.Namespace, + ) + + if dryRun { + c.cctlOpts.CmdOptions = append( + c.cctlOpts.CmdOptions, + "--dry-run", + ) + } + + if err = c.run(); err != nil { handleError(evtCh, err) return } - log.Print("command 'clusterctl move' is going to be executed") - // TODO (kkalynovskyi) add more details to dry-run, for now if dry run is set we skip move command - if !opts.DryRun { - err = c.Move(kubeConfigFile, fromContext, kubeConfigFile, toContext, ns) - if err != nil { - handleError(evtCh, err) - return - } - } - + eventMsg := "clusterctl move completed successfully" evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ Operation: events.ClusterctlMoveEnd, - Message: "clusterctl move completed successfully", - }) -} - -func (c *ClusterctlExecutor) init(opts ifc.RunOptions, evtCh chan events.Event) { - evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ - Operation: events.ClusterctlInitStart, - Message: "starting clusterctl init executor", - }) - kubeConfigFile, cleanup, err := c.kubecfg.GetFile() - if err != nil { - handleError(evtCh, err) - return - } - - defer cleanup() - - if opts.DryRun { - // TODO (dukov) add more details to dry-run - log.Print("command 'clusterctl init' is going to be executed") - evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ - Operation: events.ClusterctlInitEnd, - Message: "clusterctl init dry-run completed successfully", - }) - return - } - - context, err := c.clusterMap.ClusterKubeconfigContext(c.clusterName) - if err != nil { - handleError(evtCh, err) - return - } - - eventMsg := "clusterctl init completed successfully" - - // Use cluster name as context in kubeconfig file - err = c.Init(kubeConfigFile, context) - if err != nil && isAlreadyExistsError(err) { - // log the already existed/initialized error as warning and continue - eventMsg = fmt.Sprintf("WARNING: clusterctl is already initialized, received an error : %s", err.Error()) - } else if err != nil { - handleError(evtCh, err) - return - } - evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ - Operation: events.ClusterctlInitEnd, Message: eventMsg, }) } -func isAlreadyExistsError(err error) bool { - return strings.Contains(err.Error(), "there is already an instance") -} - // Validate executor configuration and documents func (c *ClusterctlExecutor) Validate() error { switch c.options.Action { @@ -190,33 +327,10 @@ func (c *ClusterctlExecutor) Validate() error { // Render executor documents func (c *ClusterctlExecutor) Render(w io.Writer, ro ifc.RenderOptions) error { - dataAll := bytes.NewBuffer([]byte{}) - typeMap := map[string][]string{ - string(client.BootstrapProviderType): c.options.InitOptions.BootstrapProviders, - string(client.ControlPlaneProviderType): c.options.InitOptions.ControlPlaneProviders, - string(client.InfrastructureProviderType): c.options.InitOptions.InfrastructureProviders, - string(client.CoreProviderType): (map[bool][]string{true: {c.options.InitOptions.CoreProvider}, - false: {}})[c.options.InitOptions.CoreProvider != ""], - } - for prvType, prvList := range typeMap { - for _, prv := range prvList { - res := strings.Split(prv, ":") - if len(res) != 2 { - return errors.ErrUnableParseProvider{ - Provider: prv, - ProviderType: prvType, - } - } - data, err := c.Interface.Render(client.RenderOptions{ - ProviderName: res[0], - ProviderVersion: res[1], - ProviderType: prvType, - }) - if err != nil { - return err - } - dataAll.Write(data) - dataAll.Write([]byte("\n---\n")) + dataAll := &bytes.Buffer{} + for path, data := range c.cctlOpts.Components { + if strings.Contains(path, "components.yaml") { + dataAll.Write(append(data, []byte("\n---\n")...)) } } diff --git a/pkg/phase/executors/clusterctl_test.go b/pkg/phase/executors/clusterctl_test.go old mode 100755 new mode 100644 index 9146c8c37..8a038e29e --- a/pkg/phase/executors/clusterctl_test.go +++ b/pkg/phase/executors/clusterctl_test.go @@ -18,6 +18,7 @@ import ( "bytes" goerrors "errors" "fmt" + "io" "testing" "time" @@ -26,14 +27,13 @@ import ( "opendev.org/airship/airshipctl/pkg/api/v1alpha1" "opendev.org/airship/airshipctl/pkg/cluster/clustermap" + "opendev.org/airship/airshipctl/pkg/container" "opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/events" - "opendev.org/airship/airshipctl/pkg/fs" "opendev.org/airship/airshipctl/pkg/k8s/kubeconfig" "opendev.org/airship/airshipctl/pkg/phase/executors" "opendev.org/airship/airshipctl/pkg/phase/executors/errors" "opendev.org/airship/airshipctl/pkg/phase/ifc" - testfs "opendev.org/airship/airshipctl/testutil/fs" ) var ( @@ -52,8 +52,7 @@ init-options: providers: - name: "cluster-api" type: "CoreProvider" - versions: - v0.3.2: functions/capi/infrastructure/v0.3.2` + url: functions/capi/v0.3.2` executorConfigTmplGood = ` apiVersion: airshipit.org/v1alpha1 @@ -73,72 +72,200 @@ move-options: providers: - name: "cluster-api" type: "CoreProvider" - versions: - v0.3.3: manifests/function/capi/v0.3.3` + url: functions/capi/v0.3.2` renderedDocs = `--- apiVersion: v1 kind: Namespace metadata: labels: - cluster.x-k8s.io/provider: cluster-api - clusterctl.cluster.x-k8s.io: "" control-plane: controller-manager name: version-two ... +` + krmExecDoc = `--- +apiVersion: airshipit.org/v1alpha1 +kind: GenericContainer +metadata: + name: clusterctl + labels: + airshipit.org/deploy-k8s: "false" +spec: + type: krm + image: localhost/clusterctl:latest + hostNetwork: true ` ) func TestNewClusterctlExecutor(t *testing.T) { - sampleCfgDoc := executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "init")) testCases := []struct { - name string - expectedErr error + name string + targetPath string + phaseCfgBundle document.Bundle + execDoc document.Document + errContains string }{ { - name: "New Clusterctl Executor", + name: "invalid executor document", + execDoc: executorDoc(t, ` +apiVersion: test.org/v1alpha1 +kind: testkind +metadata: + name: testname +`), + errContains: "no kind \"testkind\" is registered for version \"test.org/v1alpha1\"", + }, + { + name: "broken kustomize entrypoint", + targetPath: "/not/exist", + execDoc: executorDoc(t, ` +apiVersion: airshipit.org/v1alpha1 +kind: Clusterctl +metadata: + name: clusterctl +providers: + - name: "cluster-api" + type: "CoreProvider" + url: functions/capi/v0.3.2" +`), + errContains: "no such file or directory", + }, + { + name: "no metadata available", + targetPath: "./testdata", + execDoc: executorDoc(t, ` +apiVersion: airshipit.org/v1alpha1 +kind: Clusterctl +metadata: + name: clusterctl +providers: + - name: "cluster-api" + type: "CoreProvider" + url: functions/capi/v0.3.2/no-metadata +`), + errContains: "document filtered by selector " + + "[Group=\"clusterctl.cluster.x-k8s.io\", Version=\"v1alpha3\", Kind=\"Metadata\"] found no documents", + }, + { + name: "no container executor available", + targetPath: "./testdata", + phaseCfgBundle: executorBundle(t, ""), + execDoc: executorDoc(t, ` +apiVersion: airshipit.org/v1alpha1 +kind: Clusterctl +metadata: + name: clusterctl +providers: + - name: "cluster-api" + type: "CoreProvider" + url: functions/capi/v0.3.2 +`), + errContains: "document filtered by selector [Group=\"airshipit.org\", " + + "Version=\"v1alpha1\", Kind=\"GenericContainer\", Name=\"clusterctl\"] found no documents", + }, + { + name: "successfully create executor", + targetPath: "./testdata", + phaseCfgBundle: executorBundle(t, krmExecDoc), + execDoc: executorDoc(t, ` +apiVersion: airshipit.org/v1alpha1 +kind: Clusterctl +metadata: + name: clusterctl +providers: + - name: "cluster-api" + type: "CoreProvider" + url: functions/capi/v0.3.2 +`), }, } for _, test := range testCases { tt := test t.Run(tt.name, func(t *testing.T) { - _, actualErr := executors.NewClusterctlExecutor(ifc.ExecutorConfig{ - ExecutorDocument: sampleCfgDoc, + executor, actualErr := executors.NewClusterctlExecutor(ifc.ExecutorConfig{ + ExecutorDocument: tt.execDoc, + TargetPath: tt.targetPath, + PhaseConfigBundle: tt.phaseCfgBundle, }) - assert.Equal(t, tt.expectedErr, actualErr) + if tt.errContains != "" { + require.Nil(t, executor) + require.NotNil(t, actualErr) + require.Contains(t, actualErr.Error(), tt.errContains) + } else { + require.NoError(t, actualErr) + require.NotNil(t, executor) + } }) } } +var _ clustermap.ClusterMap = &ClusterMapMockInterface{} + +type ClusterMapMockInterface struct { + MockClusterKubeconfigContext func(string) (string, error) + MockParentCluster func(string) (string, error) +} + +func (c ClusterMapMockInterface) ValidateClusterMap() error { + panic("implement me") +} + +func (c ClusterMapMockInterface) ParentCluster(s string) (string, error) { + return c.MockParentCluster(s) +} + +func (c ClusterMapMockInterface) AllClusters() []string { + panic("implement me") +} + +func (c ClusterMapMockInterface) ClusterKubeconfigContext(s string) (string, error) { + return c.MockClusterKubeconfigContext(s) +} + +func (c ClusterMapMockInterface) Sources(_ string) ([]v1alpha1.KubeconfigSource, error) { + panic("implement me") +} + +func (c ClusterMapMockInterface) Write(_ io.Writer, _ clustermap.WriteOptions) error { + panic("implement me") +} + +var _ container.ClientV1Alpha1 = &MockClientFuncInterface{} + +type MockClientFuncInterface struct { + MockRun func() error +} + +func (c MockClientFuncInterface) Run() error { + return c.MockRun() +} + func TestClusterctlExecutorRun(t *testing.T) { errTmpFile := goerrors.New("TmpFile error") - + errCtx := goerrors.New("context error") + errParent := goerrors.New("parent cluster error") testCases := []struct { name string cfgDoc document.Document - fs fs.FileSystem - bundlePath string + kubecfg kubeconfig.Interface expectedEvt []events.Event clusterMap clustermap.ClusterMap + clientFunc container.ClientV1Alpha1FactoryFunc }{ { - name: "Error unknown action", - cfgDoc: executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "someAction")), - bundlePath: "testdata/executor_init", + name: "Error unknown action", + cfgDoc: executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "someAction")), expectedEvt: []events.Event{ wrapError(errors.ErrUnknownExecutorAction{Action: "someAction", ExecutorName: "clusterctl"}), }, clusterMap: clustermap.NewClusterMap(v1alpha1.DefaultClusterMap()), }, { - name: "Error temporary file", + name: "Failed get kubeconfig file - init", cfgDoc: executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "init")), - fs: testfs.MockFileSystem{ - MockTempFile: func(string, string) (fs.File, error) { - return nil, errTmpFile - }, - }, - bundlePath: "testdata/executor_init", + kubecfg: fakeKubeConfig{getFile: func() (string, kubeconfig.Cleanup, error) { + return "", nil, errTmpFile + }}, expectedEvt: []events.Event{ events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ Operation: events.ClusterctlInitStart, @@ -147,21 +274,86 @@ func TestClusterctlExecutorRun(t *testing.T) { }, clusterMap: clustermap.NewClusterMap(v1alpha1.DefaultClusterMap()), }, + { + name: "Failed get kubeconfig file - move", + cfgDoc: executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "move")), + kubecfg: fakeKubeConfig{getFile: func() (string, kubeconfig.Cleanup, error) { + return "", nil, errTmpFile + }}, + expectedEvt: []events.Event{ + events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ + Operation: events.ClusterctlMoveStart, + }), + wrapError(errTmpFile), + }, + clusterMap: clustermap.NewClusterMap(v1alpha1.DefaultClusterMap()), + }, + { + name: "Failed get kubeconfig context - init", + cfgDoc: executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "init")), + kubecfg: fakeKubeConfig{getFile: func() (string, kubeconfig.Cleanup, error) { + return "", func() {}, nil + }}, + expectedEvt: []events.Event{ + events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ + Operation: events.ClusterctlInitStart, + }), + wrapError(errCtx), + }, + clusterMap: ClusterMapMockInterface{MockClusterKubeconfigContext: func(s string) (string, error) { + return "", errCtx + }}, + }, + { + name: "Failed get kubeconfig context - move", + cfgDoc: executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "move")), + kubecfg: fakeKubeConfig{getFile: func() (string, kubeconfig.Cleanup, error) { + return "", func() {}, nil + }}, + expectedEvt: []events.Event{ + events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ + Operation: events.ClusterctlMoveStart, + }), + wrapError(errCtx), + }, + clusterMap: ClusterMapMockInterface{MockClusterKubeconfigContext: func(s string) (string, error) { + return "", errCtx + }}, + }, + { + name: "Failed get parent cluster", + cfgDoc: executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "move")), + kubecfg: fakeKubeConfig{getFile: func() (string, kubeconfig.Cleanup, error) { + return "", func() {}, nil + }}, + expectedEvt: []events.Event{ + events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ + Operation: events.ClusterctlMoveStart, + }), + wrapError(errParent), + }, + clusterMap: ClusterMapMockInterface{MockClusterKubeconfigContext: func(s string) (string, error) { + return "ctx", nil + }, + MockParentCluster: func(s string) (string, error) { + return "", errParent + }}, + }, { name: "Regular Run init", cfgDoc: executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "init")), - fs: testfs.MockFileSystem{ - MockTempFile: func(string, string) (fs.File, error) { - return testfs.TestFile{ - MockName: func() string { return "filename" }, - MockWrite: func([]byte) (int, error) { return 0, nil }, - MockClose: func() error { return nil }, - }, nil - }, - MockRemoveAll: func() error { return nil }, + kubecfg: fakeKubeConfig{getFile: func() (string, kubeconfig.Cleanup, error) { + return "", func() {}, nil + }}, + clusterMap: ClusterMapMockInterface{MockClusterKubeconfigContext: func(s string) (string, error) { + return "cluster", nil + }}, + clientFunc: func(_ string, _ io.Reader, _ io.Writer, + _ *v1alpha1.GenericContainer, _ string) container.ClientV1Alpha1 { + return MockClientFuncInterface{MockRun: func() error { + return nil + }} }, - bundlePath: "testdata/executor_init", - clusterMap: clustermap.NewClusterMap(v1alpha1.DefaultClusterMap()), expectedEvt: []events.Event{ events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ Operation: events.ClusterctlInitStart, @@ -171,27 +363,52 @@ func TestClusterctlExecutorRun(t *testing.T) { }), }, }, - // TODO add move tests here + { + name: "Regular Run move", + cfgDoc: executorDoc(t, fmt.Sprintf(executorConfigTmplGood, "move")), + kubecfg: fakeKubeConfig{getFile: func() (string, kubeconfig.Cleanup, error) { + return "", func() {}, nil + }}, + clusterMap: ClusterMapMockInterface{MockClusterKubeconfigContext: func(s string) (string, error) { + return "cluster", nil + }, + MockParentCluster: func(s string) (string, error) { + return "parentCluster", nil + }}, + clientFunc: func(_ string, _ io.Reader, _ io.Writer, + _ *v1alpha1.GenericContainer, _ string) container.ClientV1Alpha1 { + return MockClientFuncInterface{MockRun: func() error { + return nil + }} + }, + expectedEvt: []events.Event{ + events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ + Operation: events.ClusterctlMoveStart, + }), + events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{ + Operation: events.ClusterctlMoveEnd, + }), + }, + }, } for _, test := range testCases { tt := test t.Run(tt.name, func(t *testing.T) { - kubeCfg := kubeconfig.NewKubeConfig( - kubeconfig.FromByte([]byte("someKubeConfig")), - kubeconfig.InjectFileSystem(tt.fs), - ) executor, err := executors.NewClusterctlExecutor( ifc.ExecutorConfig{ - ExecutorDocument: tt.cfgDoc, - KubeConfig: kubeCfg, - ClusterMap: tt.clusterMap, + TargetPath: "testdata", + PhaseConfigBundle: executorBundle(t, krmExecDoc), + ExecutorDocument: tt.cfgDoc, + KubeConfig: tt.kubecfg, + ClusterMap: tt.clusterMap, + ContainerFunc: tt.clientFunc, }) require.NoError(t, err) ch := make(chan events.Event) go executor.Run(ch, ifc.RunOptions{DryRun: true}) var actualEvt []events.Event for evt := range ch { - // Skip timmestamp for comparison + // Skip timestamp for comparison evt.Timestamp = time.Time{} if evt.Type == events.ClusterctlType { // Set message to empty string, so it's not compared @@ -200,7 +417,7 @@ func TestClusterctlExecutorRun(t *testing.T) { actualEvt = append(actualEvt, evt) } for i := range tt.expectedEvt { - // Skip timmestamp for comparison + // Skip timestamp for comparison tt.expectedEvt[i].Timestamp = time.Time{} } assert.Equal(t, tt.expectedEvt, actualEvt) @@ -237,10 +454,12 @@ func TestClusterctlExecutorValidate(t *testing.T) { for _, test := range testCases { tt := test t.Run(tt.name, func(t *testing.T) { - sampleCfgDoc := executorDoc(t, fmt.Sprintf(test.executorConfigTmpl, test.actionType, test.actionType)) + sampleCfgDoc := executorDoc(t, fmt.Sprintf(test.executorConfigTmpl, test.actionType)) executor, err := executors.NewClusterctlExecutor( ifc.ExecutorConfig{ - ExecutorDocument: sampleCfgDoc, + TargetPath: "testdata", + ExecutorDocument: sampleCfgDoc, + PhaseConfigBundle: executorBundle(t, krmExecDoc), }) require.NoError(t, err) err = executor.Validate() @@ -258,8 +477,9 @@ func TestClusterctlExecutorRender(t *testing.T) { sampleCfgDoc := executorDoc(t, fmt.Sprintf(executorConfigTmpl, "init")) executor, err := executors.NewClusterctlExecutor( ifc.ExecutorConfig{ - TargetPath: "../../clusterctl/client/testdata", - ExecutorDocument: sampleCfgDoc, + TargetPath: "testdata", + ExecutorDocument: sampleCfgDoc, + PhaseConfigBundle: executorBundle(t, krmExecDoc), }) require.NoError(t, err) actualOut := &bytes.Buffer{} diff --git a/pkg/phase/executors/common.go b/pkg/phase/executors/common.go old mode 100755 new mode 100644 diff --git a/pkg/phase/executors/common_test.go b/pkg/phase/executors/common_test.go old mode 100755 new mode 100644 index 076286815..876672a14 --- a/pkg/phase/executors/common_test.go +++ b/pkg/phase/executors/common_test.go @@ -96,6 +96,14 @@ func executorDoc(t *testing.T, s string) document.Document { return doc } +// executorBundle converts string to bundle object +func executorBundle(t *testing.T, s string) document.Bundle { + b, err := document.NewBundleFromBytes([]byte(s)) + require.NoError(t, err) + require.NotNil(t, b) + return b +} + // TODO replace this test bundle factory with one that uses bundle mock func testBundleFactory() document.BundleFactoryFunc { return func() (document.Bundle, error) { diff --git a/pkg/phase/executors/errors/errors.go b/pkg/phase/executors/errors/errors.go old mode 100755 new mode 100644 diff --git a/pkg/phase/executors/testdata/functions/capi/v0.3.2/kustomization.yaml b/pkg/phase/executors/testdata/functions/capi/v0.3.2/kustomization.yaml new file mode 100644 index 000000000..f37e47ee0 --- /dev/null +++ b/pkg/phase/executors/testdata/functions/capi/v0.3.2/kustomization.yaml @@ -0,0 +1,3 @@ +resources: + - version.yaml + - metadata.yaml diff --git a/pkg/phase/executors/testdata/functions/capi/v0.3.2/metadata.yaml b/pkg/phase/executors/testdata/functions/capi/v0.3.2/metadata.yaml new file mode 100644 index 000000000..8afbc1921 --- /dev/null +++ b/pkg/phase/executors/testdata/functions/capi/v0.3.2/metadata.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 +kind: Metadata +metadata: + name: repository-metadata + labels: + airshipit.org/deploy-k8s: "false" +releaseSeries: +- major: 0 + minor: 3 + contract: v1alpha3 diff --git a/pkg/clusterctl/client/testdata/executor_init_empty/kustomization.yaml b/pkg/phase/executors/testdata/functions/capi/v0.3.2/no-metadata/kustomization.yaml similarity index 100% rename from pkg/clusterctl/client/testdata/executor_init_empty/kustomization.yaml rename to pkg/phase/executors/testdata/functions/capi/v0.3.2/no-metadata/kustomization.yaml diff --git a/pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.2/version.yaml b/pkg/phase/executors/testdata/functions/capi/v0.3.2/version.yaml similarity index 100% rename from pkg/clusterctl/client/testdata/functions/capi/infrastructure/v0.3.2/version.yaml rename to pkg/phase/executors/testdata/functions/capi/v0.3.2/version.yaml diff --git a/pkg/phase/ifc/executor.go b/pkg/phase/ifc/executor.go index 0288d9edb..b8ce92b20 100644 --- a/pkg/phase/ifc/executor.go +++ b/pkg/phase/ifc/executor.go @@ -19,6 +19,7 @@ import ( "time" "opendev.org/airship/airshipctl/pkg/cluster/clustermap" + "opendev.org/airship/airshipctl/pkg/container" "opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/events" inventoryifc "opendev.org/airship/airshipctl/pkg/inventory/ifc" @@ -70,4 +71,5 @@ type ExecutorConfig struct { BundleFactory document.BundleFactoryFunc PhaseConfigBundle document.Bundle Inventory inventoryifc.Inventory + ContainerFunc container.ClientV1Alpha1FactoryFunc } diff --git a/testutil/clusterctl/client.go b/testutil/clusterctl/client.go deleted file mode 100644 index 6c47b768c..000000000 --- a/testutil/clusterctl/client.go +++ /dev/null @@ -1,68 +0,0 @@ -/* - 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 - - https://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. -*/ - -package clusterctl - -import ( - "fmt" - - "github.com/stretchr/testify/mock" - - "opendev.org/airship/airshipctl/pkg/clusterctl/client" -) - -var _ client.Interface = &MockInterface{} - -// MockInterface provides mock interface for clusterctl -type MockInterface struct { - mock.Mock -} - -// Init to be implemented -func (m *MockInterface) Init(kubeconfigPath, kubeconfigContext string) error { - return nil -} - -// Move to be implemented -func (m *MockInterface) Move(fkp, fkc, tkp, tkc, namespace string) error { - return nil -} - -// Render to be implemented -func (m *MockInterface) Render(client.RenderOptions) ([]byte, error) { - return nil, nil -} - -// GetKubeconfig allows to control exepected input to the function and check expected output -// example usage: -// c := &clusterctl.MockInterface{ -// Mock: mock.Mock{}, -// } -// c.On("GetKubeconfig").Once().Return(&client.GetKubeconfigOptions{ -// ParentKubeconfigPath: filepath.Join("testdata", kubeconfig.KubeconfigPrefix), -// ParentKubeconfigContext: "dummy_cluster", -// ManagedClusterNamespace: clustermap.DefaultClusterAPIObjNamespace, -// ManagedClusterName: childCluster, -// }, "kubeconfig data", nil) -// first argument in return function is what you expect as input -// second argument is resulting expected string -// third is resulting error -func (m *MockInterface) GetKubeconfig(options *client.GetKubeconfigOptions) (string, error) { - args := m.Called(options) - expectedResult, ok := args.Get(0).(string) - if !ok { - return "", fmt.Errorf("wrong input") - } - return expectedResult, args.Error(1) -}