Merge "Move clustetctl to KRM"
This commit is contained in:
commit
0ff049115d
12
Makefile
12
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) \
|
||||
|
3
go.mod
3
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
|
||||
|
122
go.sum
122
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=
|
||||
|
44
krm-functions/clusterctl/Dockerfile
Normal file
44
krm-functions/clusterctl/Dockerfile
Normal file
@ -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"]
|
78
krm-functions/clusterctl/Makefile
Normal file
78
krm-functions/clusterctl/Makefile
Normal file
@ -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
|
22
krm-functions/clusterctl/README.md
Normal file
22
krm-functions/clusterctl/README.md
Normal file
@ -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 <phase_name>
|
||||
|
||||
if appropriate phase has Clusterctl executor defined.
|
6
krm-functions/clusterctl/certs/README.md
Normal file
6
krm-functions/clusterctl/certs/README.md
Normal file
@ -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.
|
5
krm-functions/clusterctl/image/go.mod
Normal file
5
krm-functions/clusterctl/image/go.mod
Normal file
@ -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
|
225
krm-functions/clusterctl/image/go.sum
Normal file
225
krm-functions/clusterctl/image/go.sum
Normal file
@ -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=
|
97
krm-functions/clusterctl/image/main.go
Normal file
97
krm-functions/clusterctl/image/main.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
46
krm-functions/clusterctl/local-resource/example-use.yaml
Executable file
46
krm-functions/clusterctl/local-resource/example-use.yaml
Executable file
@ -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
|
@ -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
|
||||
|
2
manifests/function/cabpk/v0.3.7/data/kustomization.yaml
Normal file
2
manifests/function/cabpk/v0.3.7/data/kustomization.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
resources:
|
||||
- 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
|
@ -5,6 +5,7 @@ commonLabels:
|
||||
|
||||
bases:
|
||||
- crd
|
||||
- data
|
||||
- default
|
||||
- webhook
|
||||
|
||||
|
2
manifests/function/cacpk/v0.3.7/data/kustomization.yaml
Normal file
2
manifests/function/cacpk/v0.3.7/data/kustomization.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
resources:
|
||||
- metadata.yaml
|
11
manifests/function/cacpk/v0.3.7/data/metadata.yaml
Normal file
11
manifests/function/cacpk/v0.3.7/data/metadata.yaml
Normal file
@ -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
|
@ -5,6 +5,7 @@ commonLabels:
|
||||
|
||||
bases:
|
||||
- crd
|
||||
- data
|
||||
- default
|
||||
- webhook
|
||||
|
||||
|
2
manifests/function/capi/v0.3.7/data/kustomization.yaml
Normal file
2
manifests/function/capi/v0.3.7/data/kustomization.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
resources:
|
||||
- metadata.yaml
|
11
manifests/function/capi/v0.3.7/data/metadata.yaml
Normal file
11
manifests/function/capi/v0.3.7/data/metadata.yaml
Normal file
@ -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
|
@ -5,6 +5,7 @@ commonLabels:
|
||||
|
||||
bases:
|
||||
- crd
|
||||
- data
|
||||
- webhook
|
||||
- default
|
||||
|
||||
|
@ -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
|
||||
|
@ -529,3 +529,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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
@ -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()
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
@ -1,2 +0,0 @@
|
||||
resources:
|
||||
- kubeconfig.yaml
|
@ -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
|
@ -1,2 +0,0 @@
|
||||
resources:
|
||||
- kubeconfig.yaml
|
@ -1,2 +0,0 @@
|
||||
resources:
|
||||
- version.yaml
|
@ -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
|
@ -1,2 +0,0 @@
|
||||
resources:
|
||||
- version.yaml
|
2
pkg/clusterctl/client/testdata/metadata.yaml
vendored
2
pkg/clusterctl/client/testdata/metadata.yaml
vendored
@ -1,2 +0,0 @@
|
||||
phase:
|
||||
path: executor_move
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
@ -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"))
|
||||
}
|
@ -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
|
||||
}
|
@ -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,
|
||||
}
|
||||
}
|
@ -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",
|
||||
}
|
||||
}
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
resources:
|
||||
- version.yaml
|
@ -1,7 +0,0 @@
|
||||
---
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
kind: Testversion
|
||||
metadata:
|
||||
name: version-1
|
||||
spec:
|
||||
version: v0.0.1
|
@ -1,2 +0,0 @@
|
||||
resources:
|
||||
- version.yaml
|
@ -1,2 +0,0 @@
|
||||
resources:
|
||||
- version.yaml
|
@ -1,7 +0,0 @@
|
||||
---
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
kind: Testversion
|
||||
metadata:
|
||||
name: version-3
|
||||
spec:
|
||||
version: v0.0.3
|
@ -1 +0,0 @@
|
||||
dhcp-boot=tag:ipxe,http://${PROVISIONING_IP}:80/dualboot.ipxe
|
@ -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
|
@ -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
|
@ -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}
|
@ -1,3 +0,0 @@
|
||||
# Contains variables that should be substituted
|
||||
resources:
|
||||
- azure-resources.yaml
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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{}
|
||||
|
@ -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),
|
||||
},
|
||||
|
320
pkg/phase/executors/clusterctl.go
Executable file → Normal file
320
pkg/phase/executors/clusterctl.go
Executable file → Normal file
@ -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")...))
|
||||
}
|
||||
}
|
||||
|
||||
|
326
pkg/phase/executors/clusterctl_test.go
Executable file → Normal file
326
pkg/phase/executors/clusterctl_test.go
Executable file → Normal file
@ -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{}
|
||||
|
0
pkg/phase/executors/common.go
Executable file → Normal file
0
pkg/phase/executors/common.go
Executable file → Normal file
8
pkg/phase/executors/common_test.go
Executable file → Normal file
8
pkg/phase/executors/common_test.go
Executable file → Normal file
@ -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) {
|
||||
|
0
pkg/phase/executors/errors/errors.go
Executable file → Normal file
0
pkg/phase/executors/errors/errors.go
Executable file → Normal file
3
pkg/phase/executors/testdata/functions/capi/v0.3.2/kustomization.yaml
vendored
Normal file
3
pkg/phase/executors/testdata/functions/capi/v0.3.2/kustomization.yaml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
resources:
|
||||
- version.yaml
|
||||
- metadata.yaml
|
11
pkg/phase/executors/testdata/functions/capi/v0.3.2/metadata.yaml
vendored
Normal file
11
pkg/phase/executors/testdata/functions/capi/v0.3.2/metadata.yaml
vendored
Normal file
@ -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
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user