diff --git a/Makefile b/Makefile index 38143a886..99ae86c07 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ install-deps: mod-download go get -v github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc go get -v github.com/solo-io/protoc-gen-ext go get -v github.com/golang/mock/mockgen - go get -v golang.org/x/tools/cmd/goimports + go get -v golang.org/x/tools/cmd/goimports@v0.0.0-20200427205912-352a5409fae0 go mod tidy # Generated Code - Required to update Codgen Templates diff --git a/changelog/v0.1.0/cluster-config.yaml b/changelog/v0.1.0/cluster-config.yaml new file mode 100644 index 000000000..fc5eac8fc --- /dev/null +++ b/changelog/v0.1.0/cluster-config.yaml @@ -0,0 +1,6 @@ +changelog: +- type: NEW_FEATURE + description: | + Add functions to build temporary ClientConfig from different cloud provider cluster resources + issueLink: https://github.com/solo-io/skv2/issues/25 + resolvesIssue: false \ No newline at end of file diff --git a/go.mod b/go.mod index 012d5bb5a..bb871b491 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,10 @@ module github.com/solo-io/skv2 go 1.13 require ( + cloud.google.com/go v0.40.0 github.com/BurntSushi/toml v0.3.1 github.com/Masterminds/sprig/v3 v3.0.0 + github.com/aws/aws-sdk-go v1.30.15 github.com/envoyproxy/protoc-gen-validate v0.1.0 github.com/gertd/go-pluralize v0.1.1 github.com/go-logr/logr v0.1.0 @@ -20,7 +22,7 @@ require ( github.com/onsi/ginkgo v1.12.0 github.com/onsi/gomega v1.8.1 github.com/pborman/uuid v1.2.0 - github.com/pkg/errors v0.8.1 + github.com/pkg/errors v0.9.1 github.com/rogpeppe/go-internal v1.5.2 github.com/rotisserie/eris v0.1.1 github.com/sirupsen/logrus v1.4.2 @@ -30,13 +32,17 @@ require ( github.com/solo-io/solo-kit v0.12.2 go.uber.org/zap v1.13.0 golang.org/x/crypto v0.0.0-20200117160349-530e935923ad // indirect + golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/sys v0.0.0-20200117145432-59e60aa80a0c // indirect - golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b + golang.org/x/tools v0.0.0-20200427205912-352a5409fae0 + google.golang.org/api v0.6.0 + google.golang.org/genproto v0.0.0-20191028173616-919d9bdd9fe6 k8s.io/api v0.17.2 k8s.io/apiextensions-apiserver v0.17.2 k8s.io/apimachinery v0.17.2 k8s.io/client-go v8.0.0+incompatible k8s.io/code-generator v0.17.2 + sigs.k8s.io/aws-iam-authenticator v0.5.0 sigs.k8s.io/controller-runtime v0.5.1 sigs.k8s.io/yaml v1.1.0 ) diff --git a/go.sum b/go.sum index 7d9562ade..42bbc508b 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,7 @@ github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXn github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/Netflix/go-expect v0.0.0-20180928190340-9d1f4485533b/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= @@ -72,6 +73,9 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:l github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/avast/retry-go v2.2.0+incompatible h1:m+w7mVLWa/oKqX2xYqiEKQQkeGH8DDEXB/XnjS54Wyw= github.com/avast/retry-go v2.2.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= +github.com/aws/aws-sdk-go v1.26.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.30.15 h1:Sd8QDVzzE8Sl+xNccmdj0HwMrFowv6uVUx9tGsCE1ZE= +github.com/aws/aws-sdk-go v1.30.15/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -88,6 +92,8 @@ github.com/bugsnag/bugsnag-go v1.5.0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqR github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= +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.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= @@ -99,6 +105,7 @@ github.com/containerd/containerd v1.3.0-beta.2.0.20190823190603-4a2f61c4f2b4/go. github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= 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= github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= @@ -109,6 +116,7 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -121,6 +129,7 @@ github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1 github.com/deislabs/oras v0.7.0/go.mod h1:sqMKPG3tMyIX9xwXUBRLhZ24o+uT4y6jgBD2RzUTKDM= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= 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/docker/cli v0.0.0-20190506213505-d88565df0c2d/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= @@ -144,6 +153,7 @@ github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3y github.com/envoyproxy/go-control-plane v0.9.1/go.mod h1:G1fbsNGAFpC1aaERrShZQVdUV2ZuZuv6FCl2v9JNSxQ= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -229,6 +239,7 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -244,9 +255,12 @@ github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIavi github.com/gobuffalo/packr/v2 v2.5.1 h1:TFOeY2VoGamPjQLiNDT3mn//ytzk236VMO2j7iHxJR4= github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gofrs/flock v0.7.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc= github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.3.1/go.mod h1:d+q1s/xVJxZGKWwC/6UfPIF33J+G1Tq4GYv9Y+Tg/EU= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 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/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -292,6 +306,7 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u 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 v0.0.0-20170612174753-24818f796faf/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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -300,6 +315,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= @@ -316,9 +332,11 @@ github.com/gosuri/uitable v0.0.1/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= @@ -386,10 +404,14 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 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/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= +github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 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 v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -482,6 +504,7 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m 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/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -495,6 +518,7 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -522,6 +546,8 @@ github.com/pierrec/lz4 v2.3.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -529,24 +555,32 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI= github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= 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/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= 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-20190129233650-316cf8ccfec5/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pseudomuto/protoc-gen-doc v1.0.0 h1:g4ld0LeJ2OO2FXhm1o7Arrv+W75sdEClxuvVUSN2RAE= github.com/pseudomuto/protoc-gen-doc v1.0.0/go.mod h1:fwtQAY9erXp3mC92O8OTECnDlJT2r0Ff4KSEKbGEmy0= github.com/radovskyb/watcher v1.0.2/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= @@ -587,6 +621,7 @@ github.com/solo-io/protoc-gen-ext v0.0.7 h1:s9uFGtAoSsXL7vukWKPgofkxzHUeje7m6+0C github.com/solo-io/protoc-gen-ext v0.0.7/go.mod h1:zZIFs9Ch3EU3uQgL2ZwCHlUGAtwiz4Cbw6tBcmaNsEk= github.com/solo-io/solo-kit v0.12.2 h1:9TFo60400EDrsaovNEg09AA0bjFesUWU0dGnh7XsNyU= github.com/solo-io/solo-kit v0.12.2/go.mod h1:oNDT3CNTgdjNh5tgkr4Wj8tj+h0VtJjfT/ZaZ8e1/js= +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= @@ -602,6 +637,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn 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/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= 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= @@ -613,9 +649,13 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 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/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= @@ -633,12 +673,15 @@ github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940/go.mod h1:aX github.com/yvasiyarov/gorelic v0.0.6/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.hein.dev/go-version v0.1.0/go.mod h1:WOEm7DWMroRe5GdUgHMvx+Pji5WWIpMuXmK/3foylXs= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50= go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -668,6 +711,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -705,14 +749,17 @@ 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-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -720,6 +767,7 @@ golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -758,6 +806,8 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812172437-4e8604ab3aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -793,6 +843,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-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-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -801,13 +852,14 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190812233024-afc3694995b6/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b h1:zSzQJAznWxAh9fZxiPy2FZo+ZZEYoYFYYDYdOrU7AaM= -golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200427205912-352a5409fae0 h1:LAA2Rthl6LNXSdEcUgEFvfWwDMZdcROEevLJ0YJIGw4= +golang.org/x/tools v0.0.0-20200427205912-352a5409fae0/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -821,6 +873,7 @@ gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6d gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.6.0 h1:2tJEkRfnZL5g1GeBUlITh/rqT5HG3sFcoVCUUxmgJ2g= google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= 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= @@ -842,9 +895,11 @@ google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= gopkg.in/AlecAivazis/survey.v1 v1.8.2/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -887,6 +942,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +k8s.io/api v0.0.0-20190425012535-181e1f9c52c1/go.mod h1:AhUc3Ph6fhRc0SCpt0Hwv0E+Q8QiEAASkXKwfmT2JwU= k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48= k8s.io/api v0.0.0-20191016110408-35e52d86657a/go.mod h1:/L5qH+AD540e7Cetbui1tuJeXdmNhO8jM6VkXeDdDhQ= k8s.io/api v0.0.0-20191121015604-11707872ac1c/go.mod h1:R/s4gKT0V/cWEnbQa9taNRJNbWUK57/Dx6cPj6MD3A0= @@ -899,6 +955,9 @@ k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65 h1:kThoiqgMsSw k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65/go.mod h1:5BINdGqggRXXKnDgpwoJ7PyQH8f+Ypp02fvVNcIFy9s= k8s.io/apiextensions-apiserver v0.17.2 h1:cP579D2hSZNuO/rZj9XFRzwJNYb41DbNANJb6Kolpss= k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs= +k8s.io/apimachinery v0.0.0-20190424212440-527a9d33701e/go.mod h1:5CBnzrKYGHzv9ZsSKmQ8wHt4XI4/TUBPDwYM9FlZMyw= +k8s.io/apimachinery v0.0.0-20190425132440-17f84483f500/go.mod h1:5CBnzrKYGHzv9ZsSKmQ8wHt4XI4/TUBPDwYM9FlZMyw= +k8s.io/apimachinery v0.0.0-20190612125636-6a5db36e93ad/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4= k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ= k8s.io/apimachinery v0.0.0-20191121015412-41065c7a8c2a/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= @@ -912,22 +971,27 @@ k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo= k8s.io/cli-runtime v0.0.0-20191016114015-74ad18325ed5/go.mod h1:sDl6WKSQkDM6zS1u9F49a0VooQ3ycYFBFLqd2jf2Xfo= k8s.io/client-go v0.17.1 h1:LbbuZ5tI7OYx4et5DfRFcJuoojvpYO0c7vps2rgJsHY= k8s.io/client-go v0.17.1/go.mod h1:HZtHJSC/VuSHcETN9QA5QDZky1tXiYrkF/7t7vRpO1A= +k8s.io/code-generator v0.0.0-20190419212335-ff26e7842f9d/go.mod h1:rVrFWfTVftGH7bb972nWC6N4QkJ4LU7FOXu8GH2UkJo= k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE= k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 h1:NMYlxaF7rYQJk2E2IyrUhaX81zX24+dmoZdkPw0gJqI= k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894/go.mod h1:mJUgkl06XV4kstAnLHAIzJPVCOzVR+ZcfPIv4fUsFCY= k8s.io/code-generator v0.17.2 h1:pTwl3rLB1fUyxmvEzmVPMM0tBSdUehd7z+bDzpj4lPE= k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= +k8s.io/component-base v0.0.0-20190612130303-4062e14deebe/go.mod h1:MmIDXnint3qMN0cqXHKrSiJ2XQKo3J1BPIz7in7NvO0= k8s.io/component-base v0.0.0-20190918160511-547f6c5d7090/go.mod h1:933PBGtQFJky3TEwYx4aEPZ4IxqhWh3R6DCmzqIn1hA= k8s.io/component-base v0.0.0-20191016111319-039242c015a9/go.mod h1:SuWowIgd/dtU/m/iv8OD9eOxp3QZBBhTIiWMsBQvKjI= k8s.io/component-base v0.17.2/go.mod h1:zMPW3g5aH7cHJpKYQ/ZsGMcgbsA/VyhEugF3QT1awLs= +k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190822140433-26a664648505 h1:ZY6yclUKVbZ+SdWnkfY+Je5vrMpKOxmGeKRbsXVmqYM= k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf h1:EYm5AW/UUDbnmnI+gK0TJDVK9qPLhM+sRHYanNKw0EQ= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20190918143330-0270cf2f1c1d/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= @@ -935,6 +999,8 @@ k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLy k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51/go.mod h1:gL826ZTIfD4vXTGlmzgTbliCAT9NGiqpCqK2aNYv5MQ= k8s.io/metrics v0.0.0-20191016113814-3b1a734dba6e/go.mod h1:ve7/vMWeY5lEBkZf6Bt5TTbGS3b8wAxwGbdXAsufjRs= +k8s.io/sample-controller v0.0.0-20190425173525-f9c23632fb31/go.mod h1:GHuOX/EqRZMKxNeVbZW7O0e9A6QsqDjruyOD0k49uVc= +k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= k8s.io/utils v0.0.0-20190801114015-581e00157fb1 h1:+ySTxfHnfzZb9ys375PXNlLhkJPLKgHajBU0N62BDvE= k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20191010214722-8d271d903fe4/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= @@ -949,6 +1015,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/letsencrypt v0.0.1/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/aws-iam-authenticator v0.5.0 h1:Lq6dfqNR0W0pU33QmhS9SwCFNnjB5yMG8+hnVekB7UE= +sigs.k8s.io/aws-iam-authenticator v0.5.0/go.mod h1:hGGN2wp01A1NU/88s8Wjfa3nY5bZYdeZn1aAAb8j1SI= sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg= sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns= sigs.k8s.io/controller-runtime v0.5.1 h1:TNidCfVoU/cs2i+9xoTcL/l7yhl0bDhYXU0NCG6wmiE= diff --git a/pkg/multicluster/discovery/aws.go b/pkg/multicluster/discovery/aws.go new file mode 100644 index 000000000..8e449db2e --- /dev/null +++ b/pkg/multicluster/discovery/aws.go @@ -0,0 +1,48 @@ +package discovery + +import ( + "context" + "encoding/base64" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/eks" + "github.com/solo-io/skv2/pkg/multicluster/discovery/cloud" + "github.com/solo-io/skv2/pkg/multicluster/kubeconfig" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +func NewEksConfigBuilder(eksClient cloud.EksClient) EksConfigBuilder { + return &awsClusterConfigBuilder{ + eksClient: eksClient, + } +} + +type awsClusterConfigBuilder struct { + eksClient cloud.EksClient +} + +func (a *awsClusterConfigBuilder) ConfigForCluster(ctx context.Context, cluster *eks.Cluster) (clientcmd.ClientConfig, error) { + tok, err := a.eksClient.Token(ctx, aws.StringValue(cluster.Name)) + if err != nil { + return nil, err + } + ca, err := base64.StdEncoding.DecodeString(aws.StringValue(cluster.CertificateAuthority.Data)) + if err != nil { + return nil, err + } + + cfg := kubeconfig.BuildRemoteCfg( + &clientcmdapi.Cluster{ + Server: aws.StringValue(cluster.Endpoint), + CertificateAuthorityData: ca, + }, + &clientcmdapi.Context{ + Cluster: aws.StringValue(cluster.Name), + }, + aws.StringValue(cluster.Name), + tok.Token, + ) + + return clientcmd.NewDefaultClientConfig(cfg, &clientcmd.ConfigOverrides{}), nil +} diff --git a/pkg/multicluster/discovery/aws_test.go b/pkg/multicluster/discovery/aws_test.go new file mode 100644 index 000000000..0756a2a25 --- /dev/null +++ b/pkg/multicluster/discovery/aws_test.go @@ -0,0 +1,90 @@ +package discovery_test + +import ( + "context" + "encoding/base64" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/eks" + "github.com/golang/mock/gomock" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/rotisserie/eris" + "github.com/solo-io/go-utils/testutils" + "github.com/solo-io/skv2/pkg/multicluster/discovery" + mock_cloud "github.com/solo-io/skv2/pkg/multicluster/discovery/cloud/mocks" + "github.com/solo-io/skv2/pkg/multicluster/kubeconfig" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + "sigs.k8s.io/aws-iam-authenticator/pkg/token" +) + +var _ = Describe("Aws", func() { + var ( + ctx context.Context + ctrl *gomock.Controller + + eksClient *mock_cloud.MockEksClient + + testErr = eris.New("hello") + ) + + BeforeEach(func() { + ctrl, ctx = gomock.WithContext(context.TODO(), GinkgoT()) + + eksClient = mock_cloud.NewMockEksClient(ctrl) + }) + + It("will fail if token cannot be found", func() { + configBuilder := discovery.NewEksConfigBuilder(eksClient) + + cluster := &eks.Cluster{ + Name: aws.String("cluster-name"), + } + eksClient.EXPECT(). + Token(ctx, aws.StringValue(cluster.Name)). + Return(token.Token{}, testErr) + + _, err := configBuilder.ConfigForCluster(ctx, cluster) + Expect(err).To(HaveOccurred()) + Expect(err).To(testutils.HaveInErrorChain(testErr)) + }) + + It("will Create ClientConfig if token can be found", func() { + configBuilder := discovery.NewEksConfigBuilder(eksClient) + caData := []byte("fake-ca-data") + tok := token.Token{Token: "new-token-who-dis"} + cluster := &eks.Cluster{ + Name: aws.String("cluster-name"), + CertificateAuthority: &eks.Certificate{ + Data: aws.String(base64.StdEncoding.EncodeToString(caData)), + }, + Endpoint: aws.String("fake-endpoint"), + } + eksClient.EXPECT(). + Token(ctx, aws.StringValue(cluster.Name)). + Return(tok, nil) + + cfg, err := configBuilder.ConfigForCluster(ctx, cluster) + Expect(err).NotTo(HaveOccurred()) + + ca, err := base64.StdEncoding.DecodeString(aws.StringValue(cluster.CertificateAuthority.Data)) + Expect(err).NotTo(HaveOccurred()) + newCfg := kubeconfig.BuildRemoteCfg( + &clientcmdapi.Cluster{ + Server: aws.StringValue(cluster.Endpoint), + CertificateAuthorityData: ca, + }, + &clientcmdapi.Context{ + Cluster: aws.StringValue(cluster.Name), + }, + aws.StringValue(cluster.Name), + tok.Token, + ) + + rawCfg, err := cfg.RawConfig() + Expect(err).NotTo(HaveOccurred()) + Expect(rawCfg).To(Equal(newCfg)) + + }) + +}) diff --git a/pkg/multicluster/discovery/cloud/aws.go b/pkg/multicluster/discovery/cloud/aws.go new file mode 100644 index 000000000..814243673 --- /dev/null +++ b/pkg/multicluster/discovery/cloud/aws.go @@ -0,0 +1,65 @@ +package cloud + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/eks" + "sigs.k8s.io/aws-iam-authenticator/pkg/token" +) + +func NewEksClient(region string, creds *credentials.Credentials) (EksClient, error) { + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(region), + Credentials: creds, + }) + if err != nil { + return nil, err + } + return &awsClient{ + sess: sess, + }, nil +} + +type awsClient struct { + sess *session.Session +} + +func (a *awsClient) Session() *session.Session { + return a.sess +} + +func (a *awsClient) DescribeCluster(ctx context.Context, name string) (*eks.Cluster, error) { + eksSvc := eks.New(a.sess) + input := &eks.DescribeClusterInput{ + Name: aws.String(name), + } + resp, err := eksSvc.DescribeClusterWithContext(ctx, input) + if err != nil { + return nil, err + } + return resp.Cluster, nil +} + +func (a *awsClient) ListClusters(ctx context.Context, input *eks.ListClustersInput) (*eks.ListClustersOutput, error) { + eksSvc := eks.New(a.sess) + return eksSvc.ListClustersWithContext(ctx, input) +} + +func (a *awsClient) Token(ctx context.Context, name string) (token.Token, error) { + gen, err := token.NewGenerator(true, false) + if err != nil { + return token.Token{}, err + } + opts := &token.GetTokenOptions{ + ClusterID: name, + Session: a.sess, + } + tok, err := gen.GetWithOptions(opts) + if err != nil { + return token.Token{}, err + } + return tok, nil +} diff --git a/pkg/multicluster/discovery/cloud/gke.go b/pkg/multicluster/discovery/cloud/gke.go new file mode 100644 index 000000000..23ea2712b --- /dev/null +++ b/pkg/multicluster/discovery/cloud/gke.go @@ -0,0 +1,46 @@ +package cloud + +import ( + "context" + "fmt" + + container "cloud.google.com/go/container/apiv1" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + "google.golang.org/api/option" + containerpb "google.golang.org/genproto/googleapis/container/v1" +) + +func NewGkeClient(ctx context.Context, projectId string) (GkeClient, error) { + creds, err := google.FindDefaultCredentials(ctx, container.DefaultAuthScopes()...) + if err != nil { + return nil, err + } + return &gkeClient{ + creds: creds, + projectId: projectId, + }, nil +} + +type gkeClient struct { + projectId string + creds *google.Credentials +} + +func (g *gkeClient) Token(ctx context.Context) (*oauth2.Token, error) { + return g.creds.TokenSource.Token() +} + +func (g *gkeClient) ListClusters(ctx context.Context) ([]*containerpb.Cluster, error) { + client, err := container.NewClusterManagerClient(ctx, option.WithCredentials(g.creds)) + if err != nil { + return nil, err + } + resp, err := client.ListClusters(ctx, &containerpb.ListClustersRequest{ + Parent: fmt.Sprintf("projects/%s/locations/-", g.projectId), + }) + if err != nil { + return nil, err + } + return resp.GetClusters(), nil +} diff --git a/pkg/multicluster/discovery/cloud/interfaces.go b/pkg/multicluster/discovery/cloud/interfaces.go new file mode 100644 index 000000000..687136432 --- /dev/null +++ b/pkg/multicluster/discovery/cloud/interfaces.go @@ -0,0 +1,23 @@ +package cloud + +import ( + "context" + + "github.com/aws/aws-sdk-go/service/eks" + "golang.org/x/oauth2" + containerpb "google.golang.org/genproto/googleapis/container/v1" + "sigs.k8s.io/aws-iam-authenticator/pkg/token" +) + +//go:generate mockgen -source ./interfaces.go -destination ./mocks/mock_interfaces.go + +type EksClient interface { + DescribeCluster(ctx context.Context, name string) (*eks.Cluster, error) + ListClusters(ctx context.Context, input *eks.ListClustersInput) (*eks.ListClustersOutput, error) + Token(ctx context.Context, name string) (token.Token, error) +} + +type GkeClient interface { + Token(ctx context.Context) (*oauth2.Token, error) + ListClusters(ctx context.Context) ([]*containerpb.Cluster, error) +} diff --git a/pkg/multicluster/discovery/cloud/mocks/mock_interfaces.go b/pkg/multicluster/discovery/cloud/mocks/mock_interfaces.go new file mode 100644 index 000000000..7572ed561 --- /dev/null +++ b/pkg/multicluster/discovery/cloud/mocks/mock_interfaces.go @@ -0,0 +1,137 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./interfaces.go + +// Package mock_cloud is a generated GoMock package. +package mock_cloud + +import ( + context "context" + reflect "reflect" + + eks "github.com/aws/aws-sdk-go/service/eks" + gomock "github.com/golang/mock/gomock" + oauth2 "golang.org/x/oauth2" + container "google.golang.org/genproto/googleapis/container/v1" + token "sigs.k8s.io/aws-iam-authenticator/pkg/token" +) + +// MockEksClient is a mock of EksClient interface. +type MockEksClient struct { + ctrl *gomock.Controller + recorder *MockEksClientMockRecorder +} + +// MockEksClientMockRecorder is the mock recorder for MockEksClient. +type MockEksClientMockRecorder struct { + mock *MockEksClient +} + +// NewMockEksClient creates a new mock instance. +func NewMockEksClient(ctrl *gomock.Controller) *MockEksClient { + mock := &MockEksClient{ctrl: ctrl} + mock.recorder = &MockEksClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockEksClient) EXPECT() *MockEksClientMockRecorder { + return m.recorder +} + +// DescribeCluster mocks base method. +func (m *MockEksClient) DescribeCluster(ctx context.Context, name string) (*eks.Cluster, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DescribeCluster", ctx, name) + ret0, _ := ret[0].(*eks.Cluster) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DescribeCluster indicates an expected call of DescribeCluster. +func (mr *MockEksClientMockRecorder) DescribeCluster(ctx, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DescribeCluster", reflect.TypeOf((*MockEksClient)(nil).DescribeCluster), ctx, name) +} + +// ListClusters mocks base method. +func (m *MockEksClient) ListClusters(ctx context.Context, input *eks.ListClustersInput) (*eks.ListClustersOutput, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListClusters", ctx, input) + ret0, _ := ret[0].(*eks.ListClustersOutput) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListClusters indicates an expected call of ListClusters. +func (mr *MockEksClientMockRecorder) ListClusters(ctx, input interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListClusters", reflect.TypeOf((*MockEksClient)(nil).ListClusters), ctx, input) +} + +// Token mocks base method. +func (m *MockEksClient) Token(ctx context.Context, name string) (token.Token, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Token", ctx, name) + ret0, _ := ret[0].(token.Token) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Token indicates an expected call of Token. +func (mr *MockEksClientMockRecorder) Token(ctx, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Token", reflect.TypeOf((*MockEksClient)(nil).Token), ctx, name) +} + +// MockGkeClient is a mock of GkeClient interface. +type MockGkeClient struct { + ctrl *gomock.Controller + recorder *MockGkeClientMockRecorder +} + +// MockGkeClientMockRecorder is the mock recorder for MockGkeClient. +type MockGkeClientMockRecorder struct { + mock *MockGkeClient +} + +// NewMockGkeClient creates a new mock instance. +func NewMockGkeClient(ctrl *gomock.Controller) *MockGkeClient { + mock := &MockGkeClient{ctrl: ctrl} + mock.recorder = &MockGkeClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockGkeClient) EXPECT() *MockGkeClientMockRecorder { + return m.recorder +} + +// Token mocks base method. +func (m *MockGkeClient) Token(ctx context.Context) (*oauth2.Token, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Token", ctx) + ret0, _ := ret[0].(*oauth2.Token) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Token indicates an expected call of Token. +func (mr *MockGkeClientMockRecorder) Token(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Token", reflect.TypeOf((*MockGkeClient)(nil).Token), ctx) +} + +// ListClusters mocks base method. +func (m *MockGkeClient) ListClusters(ctx context.Context) ([]*container.Cluster, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListClusters", ctx) + ret0, _ := ret[0].([]*container.Cluster) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListClusters indicates an expected call of ListClusters. +func (mr *MockGkeClientMockRecorder) ListClusters(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListClusters", reflect.TypeOf((*MockGkeClient)(nil).ListClusters), ctx) +} diff --git a/pkg/multicluster/discovery/discovery_suite_test.go b/pkg/multicluster/discovery/discovery_suite_test.go new file mode 100644 index 000000000..759196c2b --- /dev/null +++ b/pkg/multicluster/discovery/discovery_suite_test.go @@ -0,0 +1,13 @@ +package discovery_test + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestDiscovery(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Discovery Suite") +} diff --git a/pkg/multicluster/discovery/gke.go b/pkg/multicluster/discovery/gke.go new file mode 100644 index 000000000..87b835845 --- /dev/null +++ b/pkg/multicluster/discovery/gke.go @@ -0,0 +1,45 @@ +package discovery + +import ( + "context" + "encoding/base64" + + "github.com/solo-io/skv2/pkg/multicluster/discovery/cloud" + "github.com/solo-io/skv2/pkg/multicluster/kubeconfig" + containerpb "google.golang.org/genproto/googleapis/container/v1" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +func NewGkeConfigBuilder(gkeClient cloud.GkeClient) GkeConfigBuilder { + return &gkeConfigBuilder{gkeClient: gkeClient} +} + +type gkeConfigBuilder struct { + gkeClient cloud.GkeClient +} + +func (g *gkeConfigBuilder) ConfigForCluster(ctx context.Context, cluster *containerpb.Cluster) (clientcmd.ClientConfig, error) { + token, err := g.gkeClient.Token(ctx) + if err != nil { + return nil, err + } + ca, err := base64.StdEncoding.DecodeString(cluster.GetMasterAuth().GetClusterCaCertificate()) + if err != nil { + return nil, err + } + + cfg := kubeconfig.BuildRemoteCfg( + &clientcmdapi.Cluster{ + Server: cluster.GetEndpoint(), + CertificateAuthorityData: ca, + }, + &clientcmdapi.Context{ + Cluster: cluster.GetName(), + }, + cluster.GetName(), + token.AccessToken, + ) + + return clientcmd.NewDefaultClientConfig(cfg, &clientcmd.ConfigOverrides{}), nil +} diff --git a/pkg/multicluster/discovery/gke_test.go b/pkg/multicluster/discovery/gke_test.go new file mode 100644 index 000000000..782105522 --- /dev/null +++ b/pkg/multicluster/discovery/gke_test.go @@ -0,0 +1,89 @@ +package discovery_test + +import ( + "context" + "encoding/base64" + + "github.com/golang/mock/gomock" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/rotisserie/eris" + "github.com/solo-io/go-utils/testutils" + "github.com/solo-io/skv2/pkg/multicluster/discovery" + mock_cloud "github.com/solo-io/skv2/pkg/multicluster/discovery/cloud/mocks" + "github.com/solo-io/skv2/pkg/multicluster/kubeconfig" + "golang.org/x/oauth2" + containerpb "google.golang.org/genproto/googleapis/container/v1" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +var _ = Describe("Gke", func() { + var ( + ctx context.Context + ctrl *gomock.Controller + + gkeClient *mock_cloud.MockGkeClient + + testErr = eris.New("hello") + ) + + BeforeEach(func() { + ctrl, ctx = gomock.WithContext(context.TODO(), GinkgoT()) + + gkeClient = mock_cloud.NewMockGkeClient(ctrl) + }) + + It("will fail if token cannot be found", func() { + configBuilder := discovery.NewGkeConfigBuilder(gkeClient) + + cluster := &containerpb.Cluster{} + gkeClient.EXPECT(). + Token(ctx). + Return(nil, testErr) + + _, err := configBuilder.ConfigForCluster(ctx, cluster) + Expect(err).To(HaveOccurred()) + Expect(err).To(testutils.HaveInErrorChain(testErr)) + }) + + It("will Create ClientConfig if token can be found", func() { + configBuilder := discovery.NewGkeConfigBuilder(gkeClient) + caData := []byte("fake-ca-data") + token := &oauth2.Token{ + AccessToken: "new-token-who-dis", + } + cluster := &containerpb.Cluster{ + Endpoint: "fake-endpoint", + Name: "fake-name", + MasterAuth: &containerpb.MasterAuth{ + ClusterCaCertificate: base64.StdEncoding.EncodeToString(caData), + }, + } + gkeClient.EXPECT(). + Token(ctx). + Return(token, nil) + + cfg, err := configBuilder.ConfigForCluster(ctx, cluster) + Expect(err).NotTo(HaveOccurred()) + + ca, err := base64.StdEncoding.DecodeString(cluster.GetMasterAuth().GetClusterCaCertificate()) + Expect(err).NotTo(HaveOccurred()) + newCfg := kubeconfig.BuildRemoteCfg( + &clientcmdapi.Cluster{ + Server: cluster.Endpoint, + CertificateAuthorityData: ca, + }, + &clientcmdapi.Context{ + Cluster: cluster.Name, + }, + cluster.Name, + token.AccessToken, + ) + + rawCfg, err := cfg.RawConfig() + Expect(err).NotTo(HaveOccurred()) + Expect(rawCfg).To(Equal(newCfg)) + + }) + +}) diff --git a/pkg/multicluster/discovery/interfaces.go b/pkg/multicluster/discovery/interfaces.go new file mode 100644 index 000000000..0a9266c9b --- /dev/null +++ b/pkg/multicluster/discovery/interfaces.go @@ -0,0 +1,19 @@ +package discovery + +import ( + "context" + + "github.com/aws/aws-sdk-go/service/eks" + containerpb "google.golang.org/genproto/googleapis/container/v1" + "k8s.io/client-go/tools/clientcmd" +) + +//go:generate mockgen -source ./interfaces.go -destination ./mocks/mock_interfaces.go + +type GkeConfigBuilder interface { + ConfigForCluster(ctx context.Context, cluster *containerpb.Cluster) (clientcmd.ClientConfig, error) +} + +type EksConfigBuilder interface { + ConfigForCluster(ctx context.Context, cluster *eks.Cluster) (clientcmd.ClientConfig, error) +} diff --git a/pkg/multicluster/discovery/mocks/mock_interfaces.go b/pkg/multicluster/discovery/mocks/mock_interfaces.go new file mode 100644 index 000000000..25380db37 --- /dev/null +++ b/pkg/multicluster/discovery/mocks/mock_interfaces.go @@ -0,0 +1,91 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./interfaces.go + +// Package mock_discovery is a generated GoMock package. +package mock_discovery + +import ( + context "context" + reflect "reflect" + + eks "github.com/aws/aws-sdk-go/service/eks" + gomock "github.com/golang/mock/gomock" + container "google.golang.org/genproto/googleapis/container/v1" + clientcmd "k8s.io/client-go/tools/clientcmd" +) + +// MockGkeConfigBuilder is a mock of GkeConfigBuilder interface. +type MockGkeConfigBuilder struct { + ctrl *gomock.Controller + recorder *MockGkeConfigBuilderMockRecorder +} + +// MockGkeConfigBuilderMockRecorder is the mock recorder for MockGkeConfigBuilder. +type MockGkeConfigBuilderMockRecorder struct { + mock *MockGkeConfigBuilder +} + +// NewMockGkeConfigBuilder creates a new mock instance. +func NewMockGkeConfigBuilder(ctrl *gomock.Controller) *MockGkeConfigBuilder { + mock := &MockGkeConfigBuilder{ctrl: ctrl} + mock.recorder = &MockGkeConfigBuilderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockGkeConfigBuilder) EXPECT() *MockGkeConfigBuilderMockRecorder { + return m.recorder +} + +// ConfigForCluster mocks base method. +func (m *MockGkeConfigBuilder) ConfigForCluster(ctx context.Context, cluster *container.Cluster) (clientcmd.ClientConfig, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConfigForCluster", ctx, cluster) + ret0, _ := ret[0].(clientcmd.ClientConfig) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ConfigForCluster indicates an expected call of ConfigForCluster. +func (mr *MockGkeConfigBuilderMockRecorder) ConfigForCluster(ctx, cluster interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigForCluster", reflect.TypeOf((*MockGkeConfigBuilder)(nil).ConfigForCluster), ctx, cluster) +} + +// MockEksConfigBuilder is a mock of EksConfigBuilder interface. +type MockEksConfigBuilder struct { + ctrl *gomock.Controller + recorder *MockEksConfigBuilderMockRecorder +} + +// MockEksConfigBuilderMockRecorder is the mock recorder for MockEksConfigBuilder. +type MockEksConfigBuilderMockRecorder struct { + mock *MockEksConfigBuilder +} + +// NewMockEksConfigBuilder creates a new mock instance. +func NewMockEksConfigBuilder(ctrl *gomock.Controller) *MockEksConfigBuilder { + mock := &MockEksConfigBuilder{ctrl: ctrl} + mock.recorder = &MockEksConfigBuilderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockEksConfigBuilder) EXPECT() *MockEksConfigBuilderMockRecorder { + return m.recorder +} + +// ConfigForCluster mocks base method. +func (m *MockEksConfigBuilder) ConfigForCluster(ctx context.Context, cluster *eks.Cluster) (clientcmd.ClientConfig, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConfigForCluster", ctx, cluster) + ret0, _ := ret[0].(clientcmd.ClientConfig) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ConfigForCluster indicates an expected call of ConfigForCluster. +func (mr *MockEksConfigBuilderMockRecorder) ConfigForCluster(ctx, cluster interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigForCluster", reflect.TypeOf((*MockEksConfigBuilder)(nil).ConfigForCluster), ctx, cluster) +} diff --git a/pkg/multicluster/kubeconfig/interfaces.go b/pkg/multicluster/kubeconfig/interfaces.go new file mode 100644 index 000000000..726c21b73 --- /dev/null +++ b/pkg/multicluster/kubeconfig/interfaces.go @@ -0,0 +1,16 @@ +package kubeconfig + +import ( + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +//go:generate mockgen -destination ./mocks/mock_interfaces.go -source ./interfaces.go + +type KubeLoader interface { + GetRestConfigForContext(path string, context string) (*rest.Config, error) + GetRawConfigForContext(path, context string) (clientcmdapi.Config, error) + GetClientConfigForContext(path, context string) (clientcmd.ClientConfig, error) + GetRestConfigFromBytes(config []byte) (*rest.Config, error) +} diff --git a/pkg/multicluster/kubeconfig/loader.go b/pkg/multicluster/kubeconfig/loader.go new file mode 100644 index 000000000..59a6aec30 --- /dev/null +++ b/pkg/multicluster/kubeconfig/loader.go @@ -0,0 +1,102 @@ +package kubeconfig + +import ( + "os" + "time" + + "github.com/solo-io/go-utils/kubeutils" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/clientcmd/api" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +// given a path to a kube config file, convert it into either creds for hitting the API server of the cluster it points to, +// or return the contexts/clusters it is aware of + +// only the pieces from a kube config that we need to operate on +// mainly just used to simplify from the complexity of the actual object +type KubeContext struct { + CurrentContext string + Contexts map[string]*api.Context + Clusters map[string]*api.Cluster +} + +// default KubeLoader +func DefaultKubeLoaderProvider(timeout *time.Duration) KubeLoader { + return &kubeLoader{ + timeout: timeout.String(), + } +} + +type kubeLoader struct { + timeout string +} + +func (k *kubeLoader) GetClientConfigForContext(path, context string) (clientcmd.ClientConfig, error) { + return k.getConfigWithContext("", path, context) +} + +func (k *kubeLoader) GetRestConfigForContext(path string, context string) (*rest.Config, error) { + cfg, err := k.getConfigWithContext("", path, context) + if err != nil { + return nil, err + } + + return cfg.ClientConfig() +} + +func (k *kubeLoader) GetRestConfigFromBytes(config []byte) (*rest.Config, error) { + return clientcmd.RESTConfigFromKubeConfig(config) +} + +func (k *kubeLoader) getConfigWithContext(masterURL, kubeconfigPath, context string) (clientcmd.ClientConfig, error) { + verifiedKubeConfigPath := clientcmd.RecommendedHomeFile + if kubeconfigPath != "" { + verifiedKubeConfigPath = kubeconfigPath + } + + if err := assertKubeConfigExists(verifiedKubeConfigPath); err != nil { + return nil, err + } + + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + loadingRules.ExplicitPath = verifiedKubeConfigPath + configOverrides := &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterURL}} + + if context != "" { + configOverrides.CurrentContext = context + } + return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides), nil +} + +// expects `path` to be nonempty +func assertKubeConfigExists(path string) error { + if _, err := os.Stat(path); err != nil { + return err + } + + return nil +} + +func (k *kubeLoader) GetRawConfigForContext(path, context string) (clientcmdapi.Config, error) { + cfg, err := k.getConfigWithContext("", path, context) + if err != nil { + return clientcmdapi.Config{}, err + } + + return cfg.RawConfig() +} + +func (k *kubeLoader) ParseContext(path string) (*KubeContext, error) { + cfg, err := kubeutils.GetKubeConfig("", path) + if err != nil { + return nil, err + } + + return &KubeContext{ + CurrentContext: cfg.CurrentContext, + Contexts: cfg.Contexts, + Clusters: cfg.Clusters, + }, nil +} diff --git a/pkg/multicluster/kubeconfig/mocks/mock_interfaces.go b/pkg/multicluster/kubeconfig/mocks/mock_interfaces.go new file mode 100644 index 000000000..3c489399c --- /dev/null +++ b/pkg/multicluster/kubeconfig/mocks/mock_interfaces.go @@ -0,0 +1,97 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./interfaces.go + +// Package mock_kubeconfig is a generated GoMock package. +package mock_kubeconfig + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + rest "k8s.io/client-go/rest" + clientcmd "k8s.io/client-go/tools/clientcmd" + api "k8s.io/client-go/tools/clientcmd/api" +) + +// MockKubeLoader is a mock of KubeLoader interface. +type MockKubeLoader struct { + ctrl *gomock.Controller + recorder *MockKubeLoaderMockRecorder +} + +// MockKubeLoaderMockRecorder is the mock recorder for MockKubeLoader. +type MockKubeLoaderMockRecorder struct { + mock *MockKubeLoader +} + +// NewMockKubeLoader creates a new mock instance. +func NewMockKubeLoader(ctrl *gomock.Controller) *MockKubeLoader { + mock := &MockKubeLoader{ctrl: ctrl} + mock.recorder = &MockKubeLoaderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockKubeLoader) EXPECT() *MockKubeLoaderMockRecorder { + return m.recorder +} + +// GetRestConfigForContext mocks base method. +func (m *MockKubeLoader) GetRestConfigForContext(path, context string) (*rest.Config, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRestConfigForContext", path, context) + ret0, _ := ret[0].(*rest.Config) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRestConfigForContext indicates an expected call of GetRestConfigForContext. +func (mr *MockKubeLoaderMockRecorder) GetRestConfigForContext(path, context interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRestConfigForContext", reflect.TypeOf((*MockKubeLoader)(nil).GetRestConfigForContext), path, context) +} + +// GetRawConfigForContext mocks base method. +func (m *MockKubeLoader) GetRawConfigForContext(path, context string) (api.Config, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRawConfigForContext", path, context) + ret0, _ := ret[0].(api.Config) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRawConfigForContext indicates an expected call of GetRawConfigForContext. +func (mr *MockKubeLoaderMockRecorder) GetRawConfigForContext(path, context interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRawConfigForContext", reflect.TypeOf((*MockKubeLoader)(nil).GetRawConfigForContext), path, context) +} + +// GetClientConfigForContext mocks base method. +func (m *MockKubeLoader) GetClientConfigForContext(path, context string) (clientcmd.ClientConfig, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetClientConfigForContext", path, context) + ret0, _ := ret[0].(clientcmd.ClientConfig) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetClientConfigForContext indicates an expected call of GetClientConfigForContext. +func (mr *MockKubeLoaderMockRecorder) GetClientConfigForContext(path, context interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClientConfigForContext", reflect.TypeOf((*MockKubeLoader)(nil).GetClientConfigForContext), path, context) +} + +// GetRestConfigFromBytes mocks base method. +func (m *MockKubeLoader) GetRestConfigFromBytes(config []byte) (*rest.Config, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRestConfigFromBytes", config) + ret0, _ := ret[0].(*rest.Config) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRestConfigFromBytes indicates an expected call of GetRestConfigFromBytes. +func (mr *MockKubeLoaderMockRecorder) GetRestConfigFromBytes(config interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRestConfigFromBytes", reflect.TypeOf((*MockKubeLoader)(nil).GetRestConfigFromBytes), config) +} diff --git a/pkg/multicluster/kubeconfig/remote.go b/pkg/multicluster/kubeconfig/remote.go new file mode 100644 index 000000000..e3090292e --- /dev/null +++ b/pkg/multicluster/kubeconfig/remote.go @@ -0,0 +1,35 @@ +package kubeconfig + +import ( + "k8s.io/client-go/tools/clientcmd/api" +) + +func BuildRemoteCfg( + remoteCluster *api.Cluster, + remoteCtx *api.Context, + clusterName, token string, +) api.Config { + return api.Config{ + Kind: "Secret", + APIVersion: "kubernetes_core", + Preferences: api.Preferences{}, + Clusters: map[string]*api.Cluster{ + clusterName: remoteCluster, + }, + AuthInfos: map[string]*api.AuthInfo{ + clusterName: { + Token: token, + }, + }, + Contexts: map[string]*api.Context{ + clusterName: { + LocationOfOrigin: remoteCtx.LocationOfOrigin, + Cluster: clusterName, + AuthInfo: clusterName, + Namespace: remoteCtx.Namespace, + Extensions: remoteCtx.Extensions, + }, + }, + CurrentContext: clusterName, + } +}