From 95beaeeeb670745204b01bc2337d6e65fa3b7a8a Mon Sep 17 00:00:00 2001 From: Kubernetes Prow Robot Date: Wed, 4 Mar 2020 16:14:38 -0800 Subject: [PATCH] Cherry-pick #225 #254 #267 to v1.0-branch (#268) * Add IAM Role and Policy for Service Account support (#225) * Add IAM Role and Policy for Service Account support * Use more elegant way to handle AssumeRoleWithWebIdentityPolicyDocument * Create kubeflow namespace before we create service account * Add more service account under IAM Role kf-admin control * Rebase go mod changes * Improve kfctl for AWS (#254) * Optimize size of policy document * Clean up cert-manager namespace in `Delete` * Clean up web identity roles and provider after * Create separate eks and k8sClient files * Use kfdef to replace fields in cluster_features.yaml * Refactor codes and address a few TODOs * Resolve cert-manager webhook issue and unblock namespace deletion * Add kfDef deleteApplication, addOverlay, removeOverlay support * Add kustomize settings for managed sql * Fix syntax issues to build kfctl * Add OWNERS file under awsplugin * Fix test - remove unless test files * Create OIDC secret and pass to alb-ingress-controller (#267) 1. Remove cognito and add oidc overlay to istio-ingress applications 2. Create a secret using clientId and clientSecret and pass to alb Signed-off-by: Jiaxin Shan --- go.mod | 29 +- go.sum | 303 ++++++- pkg/kfapp/aws/OWNERS | 2 + pkg/kfapp/aws/aws.go | 765 ++++++++++-------- pkg/kfapp/aws/eks.go | 143 ++++ pkg/kfapp/aws/eks_test.go | 20 + pkg/kfapp/aws/identity.go | 336 ++++++++ pkg/kfapp/aws/k8sClient.go | 95 +++ pkg/kfconfig/awsplugin/OWNERS | 2 + pkg/kfconfig/awsplugin/types.go | 115 ++- .../awsplugin/zz_generated.deepcopy.go | 62 ++ pkg/kfconfig/types.go | 83 ++ pkg/kfconfig/types_test.go | 393 +++++++++ pkg/utils/awsutil.go | 38 +- 14 files changed, 1984 insertions(+), 402 deletions(-) create mode 100644 pkg/kfapp/aws/OWNERS create mode 100644 pkg/kfapp/aws/eks.go create mode 100644 pkg/kfapp/aws/eks_test.go create mode 100644 pkg/kfapp/aws/identity.go create mode 100644 pkg/kfapp/aws/k8sClient.go create mode 100644 pkg/kfconfig/awsplugin/OWNERS diff --git a/go.mod b/go.mod index 0aa7b474..2e8ed0b0 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,12 @@ module github.com/kubeflow/kfctl/v3 require ( - cloud.google.com/go v0.38.0 + cloud.google.com/go v0.47.0 + github.com/Azure/go-autorest v13.3.3+incompatible // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/Sirupsen/logrus v0.0.0-00010101000000-000000000000 // indirect - github.com/aws/aws-sdk-go v1.17.7 + github.com/aws/aws-sdk-go v1.27.1 github.com/cenkalti/backoff v2.2.1+incompatible github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect github.com/deckarep/golang-set v1.7.1 @@ -17,34 +18,40 @@ require ( github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/go-logr/logr v0.1.0 github.com/go-openapi/jsonpointer v0.19.2 // indirect - github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48 - github.com/google/go-cmp v0.3.0 + github.com/gogo/protobuf v1.3.1 + github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e + github.com/google/go-cmp v0.3.1 github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/go-getter v1.0.2 - github.com/imdario/mergo v0.3.7 + github.com/hashicorp/go-version v1.2.0 + github.com/imdario/mergo v0.3.8 github.com/kubernetes-sigs/application v0.8.0 github.com/onrik/logrus v0.2.1 github.com/operator-framework/operator-sdk v0.13.0 github.com/otiai10/copy v1.0.2 github.com/pkg/errors v0.8.1 - github.com/prometheus/common v0.6.0 + github.com/prometheus/common v0.7.0 github.com/sirupsen/logrus v1.4.2 github.com/spf13/cobra v0.0.5 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.4.0 + github.com/stretchr/testify v1.4.0 + github.com/tektoncd/pipeline v0.10.1 + github.com/tidwall/gjson v1.4.0 + github.com/tidwall/pretty v1.0.1 // indirect go.uber.org/zap v1.12.0 // indirect golang.org/dl v0.0.0-20191220003028-84da647cadd0 // indirect golang.org/x/crypto v0.0.0 - golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc + golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 google.golang.org/api v0.10.0 - google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 + google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect - gopkg.in/yaml.v2 v2.2.4 - k8s.io/api v0.0.0 + gopkg.in/yaml.v2 v2.2.5 + k8s.io/api v0.17.0 k8s.io/apiextensions-apiserver v0.0.0 - k8s.io/apimachinery v0.0.0 + k8s.io/apimachinery v0.17.1 k8s.io/cli-runtime v0.0.0 k8s.io/client-go v12.0.0+incompatible k8s.io/kubernetes v1.16.2 diff --git a/go.sum b/go.sum index 73732a67..77f0a00b 100644 --- a/go.sum +++ b/go.sum @@ -5,16 +5,66 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.47.0 h1:1JUtpcY9E7+eTospEwWS2QXP3DEn7poB3E2j0jN74mM= +cloud.google.com/go v0.47.0/go.mod h1:5p3Ky/7f3N10VBkhuR5LFtddroTiMyjZV/Kj5qOQFxU= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/logging v1.0.0/go.mod h1:V1cc3ogwobYzQq5f2R7DS/GvRIrI4FKj01Gs5glwAls= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= +contrib.go.opencensus.io/exporter/prometheus v0.1.0 h1:SByaIoWwNgMdPSgl5sMqM2KDE5H/ukPWBRo314xiDvg= +contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A= +contrib.go.opencensus.io/exporter/stackdriver v0.12.8 h1:iXI5hr7pUwMx0IwMphpKz5Q3If/G5JiWFVZ5MPPxP9E= +contrib.go.opencensus.io/exporter/stackdriver v0.12.8/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v21.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v28.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v11.1.2+incompatible h1:viZ3tV5l4gE2Sw0xrasFHytCGtzYCrT+um/rrSQ1BfA= github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v13.3.3+incompatible h1:oYzB8/Ldlo1Bq7By79KO/1nxWuoLnEoGQiToUM2rBZo= +github.com/Azure/go-autorest v13.3.3+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.3 h1:OZEIaBbMdUE/Js+BQKlpO81XlISgipr6yDJ+PSwsgi4= +github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= +github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.8.1 h1:pZdL8o72rK+avFWl+p9nE8RWi1JInZrWJYlnpfXJwHk= +github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/to v0.1.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= +github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= +github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= +github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= +github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= +github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 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/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/GoogleCloudPlatform/cloud-builders/gcs-fetcher v0.0.0-20191203181535-308b93ad1f39/go.mod h1:yfGmCjKuUzk9WzubMlW2zwjhCraIc/J+M40cufdemRM= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20181220005116-f8e995905100/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= @@ -24,9 +74,9 @@ github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy86 github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.0.1 h1:iLrQrdwjDd52kHDA5op2UBJFjmOb9g+7scBan4RN8F0= github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -39,28 +89,36 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Rican7/retry v0.1.0/go.mod h1:FgOROf8P5bebcC1DS0PdOQiqGUridaZvikzUmkFW6gg= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/ant31/crd-validation v0.0.0-20180702145049-30f8a35d0ac2/go.mod h1:X0noFIik9YqfhGYBLEHg8LJKEwy7QIitLQuFMpKLcPk= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= +github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7/go.mod h1:LWMyo4iOLWXHGdBki7NIht1kHru/0wM179h+d3g8ATM= github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= -github.com/aws/aws-sdk-go v1.16.26 h1:GWkl3rkRO/JGRTWoLLIqwf7AWC4/W/1hMOUZqmX0js4= github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.17.7 h1:/4+rDPe0W95KBmNGYCG+NUvdL8ssPYBMxL+aSCg6nIA= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.1 h1:MXnqY6SlWySaZAqNnXThOvjRFdiiOuKtC6i7baFdNdU= +github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/bazelbuild/bazel-gazelle v0.0.0-20181012220611-c728ce9f663e/go.mod h1:uHBSeeATKpVazAACZBDPL/Nk/UhQDDsJWDlqYJo8/Us= github.com/bazelbuild/buildtools v0.0.0-20180226164855-80c7f0d45d7e/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -75,6 +133,9 @@ github.com/brancz/gojsontoyaml v0.0.0-20190425155809-e8bd32d46b3d/go.mod h1:IyUJ github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c/go.mod h1:Xe6ZsFhtM8HrDku0pxJ3/Lr51rwykrzgFwpmTzleatY= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= @@ -83,6 +144,7 @@ github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1/go.mod h1:/iP1 github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/client9/misspell v0.0.0-20170928000206-9ce5d979ffda/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudevents/sdk-go v0.0.0-20190509003705-56931988abe3/go.mod h1:j1nZWMLGg3om8SswStBoY6/SHvcLM19MuZqwDtMtmzs= github.com/cloudflare/cfssl v0.0.0-20180726162950-56268a613adf/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= @@ -93,12 +155,12 @@ github.com/container-storage-interface/spec v1.1.0/go.mod h1:6URME8mwIBbpVyZV93C github.com/containerd/console v0.0.0-20170925154832-84eeaae905fa/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/containerd v1.0.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containernetworking/cni v0.6.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= 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.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v0.0.0-20180117170138-065b426bd416/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= @@ -115,6 +177,7 @@ github.com/coreos/prometheus-operator v0.34.0/go.mod h1:Li6rMllG/hYIyXfMuvUwhyC+ github.com/coreos/rkt v1.30.0/go.mod h1:O634mlH6U7qk87poQifK6M2rsFNt+FyUTWNMnP1hF1U= github.com/cpuguy83/go-md2man v1.0.4/go.mod h1:N6JayAiVKtlHSnuTCeuLSQVs75hb8q+dYQLjr7cDsKY= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/cyphar/filepath-securejoin v0.0.0-20170720062807-ae69057f2299/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= @@ -136,29 +199,34 @@ github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1 github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= -github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 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/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.0+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= github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo= github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libnetwork v0.0.0-20180830151422-a9cd636e3789/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 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/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= @@ -170,6 +238,8 @@ github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8 github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.6+incompatible h1:tfrHha8zJ01ywiOEC1miGY8st1/igzWB8OmvPgoYX7w= github.com/emicklei/go-restful v2.9.6+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -178,26 +248,26 @@ github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5I github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= -github.com/fatih/camelcase v0.0.0-20160318181535-f6a740d52f96 h1:5e8GDOdG6jKeeqNGbR+tlmqhf4vQVs3atTTMEWeEcAk= github.com/fatih/camelcase v0.0.0-20160318181535-f6a740d52f96/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structtag v1.1.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= +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 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 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-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -209,29 +279,23 @@ github.com/go-logr/zapr v0.1.1 h1:qXBXPDdNncunGs7XeEpsJt8wCjYBygluzfdLO0G5baE= github.com/go-logr/zapr v0.1.1/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.17.2 h1:eYp14J1o8TTSCzndHBtsNuckikV1PfZOSnx4BcBeu0c= github.com/go-openapi/analysis v0.17.2/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.17.2 h1:azEQ8Fnx0jmtFF2fxsnmd6I0x6rsweUF63qqSO1NmKk= github.com/go-openapi/errors v0.17.2/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= github.com/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0= github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonreference v0.17.0 h1:yJW3HCkTHg7NOA+gZ83IPHzUSnUzGXhGmsdiCcMexbA= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.17.2 h1:tEXYu6Xc0pevpzzQx5ghrMN9F7IVpN/+u4iD3rkYE5o= github.com/go-openapi/loads v0.17.2/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= -github.com/go-openapi/runtime v0.17.2 h1:/ZK67ikFhQAMFFH/aPu2MaGH7QjP4wHBvHYOVIzDAw0= github.com/go-openapi/runtime v0.17.2/go.mod h1:QO936ZXeisByFmZEO1IS1Dqhtf4QV1sYYFtIq6Ld86Q= github.com/go-openapi/spec v0.18.0 h1:aIjeyG5mo5/FrvDkpKKEGZPmF9MPHahS72mzfVqeQXQ= github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/strfmt v0.17.0 h1:1isAxYf//QDTnVzbLAMrUK++0k1EjeLJU/gTOR0o3Mc= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi880= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= -github.com/go-openapi/validate v0.18.0 h1:PVXYcP1GkTl+XIAJnyJxOmK6CSG5Q1UcvoCvNO++5Kg= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -239,6 +303,7 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= @@ -247,13 +312,15 @@ github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWS github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= 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.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48 h1:X+zN6RZXsvnrSJaAIQhZezPfAfvsqihKKR8oiLHid34= github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -262,13 +329,14 @@ github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/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-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v0.0.0-20160127222235-bd3c8e81be01/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -277,9 +345,9 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8= +github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e h1:KhcknUwkWHKZPbFy2P7jH5LKJ3La+0ZeknkkmrSgqb0= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -288,25 +356,39 @@ github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-containerregistry v0.0.0-20200115214256-379933c9c22b/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-licenses v0.0.0-20191112164736-212ea350c932/go.mod h1:16wa6pRqNDUIhOtwF0GcROVqMeXHZJ7H6eGDFUh5Pfk= 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/licenseclassifier v0.0.0-20190926221455-842c0d70d702/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M= 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= +github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= +github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww= +github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.0 h1:CcQijm0XKekKjP/YCz28LXVSpgguuB+nCxaSjCe09y0= github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= +github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 h1:L9JPKrtsHMQ4VCRQfHvbbHBfB2Urn8xf6QZeXZ+OrN4= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.2.0 h1:lD2Bce2xBAMNNcFZ0dObTpXkGLlVIb33RPVUNVpw6ic= @@ -316,22 +398,25 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190203031600-7a902570cb17/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/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.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.4/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-health-probe v0.2.1-0.20181220223928-2bf0a5b182db/go.mod h1:uBKkC2RbarFsvS5jMJHpVhTLvGlGQj9JJwkaePE3FWI= +github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig= @@ -341,12 +426,17 @@ github.com/hashicorp/go-getter v1.0.2/go.mod h1:q+PoBhh16brIKwJS9kt18jEtXHTg2EGk github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 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-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 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/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= +github.com/hashicorp/go-version v1.2.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 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v0.0.0-20160711231752-d8c773c4cba1/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= 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= @@ -362,11 +452,18 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/improbable-eng/thanos v0.3.2/go.mod h1:GZewVGILKuJVPNRn7L4Zw+7X96qzFOwj63b22xYGXBE= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jenkins-x/go-scm v1.5.65/go.mod h1:MgGRkJScE/rJ30J/bXYqduN5sDPZqZFITJopsnZmTOw= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -379,10 +476,11 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22 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.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jsonnet-bundler/jsonnet-bundler v0.1.0/go.mod h1:YKsSFc9VFhhLITkJS3X2PrRqWG9u2Jq99udTdDjQLfM= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jteeuwen/go-bindata v0.0.0-20151023091102-a0ff2567cfb7/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs= @@ -392,10 +490,11 @@ github.com/kardianos/osext v0.0.0-20150410034420-8fef92e41e22/go.mod h1:1NbS8ALr github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kelseyhightower/envconfig v1.3.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -405,6 +504,7 @@ github.com/kr/pretty v0.0.0-20140812000539-f31442d60e51/go.mod h1:Bvhd+E3laJ0AVk github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.0.0-20130911015532-6807e777504f/go.mod h1:sjUstKUATFIcff4qlB53Kml0wQPtJVc/3fWrmuUmcfA= 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= @@ -418,6 +518,7 @@ github.com/libopenstorage/openstorage v0.0.0-20170906232338-093a0c388875/go.mod 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/lpabon/godbc v0.1.1/go.mod h1:Jo9QV0cf3U6jZABgiJ2skINAXb9j8m51r07g4KI92ZA= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v0.0.0-20160816085511-61b492c03cf4/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -429,11 +530,9 @@ github.com/markbates/inflect v1.0.4/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzfe github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/martinlindhe/base36 v1.0.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8= github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= @@ -445,6 +544,7 @@ github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsO github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.1/go.mod h1:F9YacGpnZbLQMzuPI0rR6op21YvNu/RjL705LJJpM3k= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/mesos/mesos-go v0.0.9/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4= github.com/mholt/caddy v0.0.0-20180213163048-2de495001514/go.mod h1:Wb1PlT4DAYSqOEd03MsqkdkXnTxA8v9pKjdpxbqM1kY= github.com/miekg/dns v0.0.0-20160614162101-5d001d020961/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -455,7 +555,6 @@ github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnG github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 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= @@ -473,15 +572,21 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20190414153302-2ae31c8b6b30 h1:10VrZWOtDSvWhgViCi2J6VUp4p/B3pOA/efiMH3KjjI= github.com/munnerz/goautoneg v0.0.0-20190414153302-2ae31c8b6b30/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mvdan/xurls v0.0.0-20160110113200-1b768d7c393a/go.mod h1:tQlNn3BED8bE/15hnSL2HLkDeLWpNPAwtw7wkEq44oU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= +github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ= +github.com/nats-io/go-nats v1.7.0/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0= +github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= +github.com/nats-io/nuid v1.0.0/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= 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/onrik/logrus v0.2.1 h1:xEYR+opLvr+hNixPPAimuQppFYHaZ0XLO9hZ2G8WPLI= @@ -491,12 +596,16 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 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.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v0.0.0-20170604055404-372ad780f634/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= @@ -510,6 +619,7 @@ github.com/openshift/origin v0.0.0-20160503220234-8f127d736703/go.mod h1:0Rox5r9 github.com/openshift/prom-label-proxy v0.1.1-0.20191016113035-b8153a7f39f1/go.mod h1:p5MuxzsYP1JPsNGwtjtcgRHHlGziCJJfztff91nNixw= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.0/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/operator-framework/operator-lifecycle-manager v0.0.0-20191115003340-16619cd27fa5/go.mod h1:zL34MNy92LPutBH5gQK+gGhtgTUlZZX03I2G12vWHF4= github.com/operator-framework/operator-registry v1.5.1/go.mod h1:agrQlkWOo1q8U1SAaLSS2WQ+Z9vswNT2M2HFib9iuLY= github.com/operator-framework/operator-sdk v0.13.0 h1:AWiKOl6ZeAyQgbGVoD8fNd+eCbFuRWgr4hciaaOEBmE= @@ -517,7 +627,6 @@ github.com/operator-framework/operator-sdk v0.13.0/go.mod h1:XRnicDD4uZCNbJbMXc0 github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc= github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc= github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4= github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw= @@ -526,15 +635,20 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pborman/uuid v0.0.0-20170612153648-e790cca94e6c/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.2.6+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v0.0.0-20160930220758-4d0e916071f6/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk= 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= @@ -543,10 +657,8 @@ github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prY github.com/pquerna/ffjson v0.0.0-20180717144149-af8b230fcd20/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= @@ -558,13 +670,13 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 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 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/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-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 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= @@ -573,11 +685,14 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= 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/prometheus v2.3.2+incompatible/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.8.0/go.mod h1:fSI0j+IUQrDd7+ZtR9WKIGtoYAYAJUKcKhYLG25tN4g= github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/robfig/cron v0.0.0-20170309132418-df38d32658d8/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/robfig/cron v0.0.0-20170526150127-736158dc09e1/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= @@ -585,6 +700,7 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rubenv/sql-migrate v0.0.0-20191025130928-9355dd04f4b3/go.mod h1:WS0rl9eEliYI8DPnr3TOwz4439pay+qNgzJoVya/DmY= github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= @@ -595,6 +711,9 @@ github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24 github.com/seccomp/libseccomp-golang v0.0.0-20150813023252-1b506fc7c24e/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shurcooL/githubv4 v0.0.0-20190718010115-4ba037080260/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo= +github.com/shurcooL/githubv4 v0.0.0-20191102174205-af46314aec7b/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo= +github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg= github.com/shurcooL/sanitized_anchor_name v0.0.0-20151028001915-10ef21a441db/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sigma/go-inotify v0.0.0-20181102212354-c87b6cf5033d/go.mod h1:stlh9OsqBQSdwxTxX73mu41BBtRbIpZLQ7flcAoxAfo= github.com/sirupsen/logrus v1.0.5 h1:8c8b5uO0zS4X6RPl/sd1ENwSkIc0/H2PaHxE3udaE8I= @@ -627,7 +746,6 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6 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= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -637,9 +755,12 @@ github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= 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/storageos/go-api v0.0.0-20180912212459-343b3eff91fc/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= 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/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -647,7 +768,19 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/gocapability v0.0.0-20160928074757-e7cb7fa329f4/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/technosophos/moniker v0.0.0-20180509230615-a5dbd03a2245/go.mod h1:O1c8HleITsZqzNZDjSNzirUGsMT0oGu9LhHKoJrqO+A= +github.com/tektoncd/pipeline v0.10.1 h1:pDsYK2b70o/Ze/CE1nisELwKVVE54FxwyfLznsW1JiE= +github.com/tektoncd/pipeline v0.10.1/go.mod h1:D2X0exT46zYx95BU7ByM8+erpjoN7thmUBvlKThOszU= +github.com/tektoncd/plumbing v0.0.0-20191216083742-847dcf196de9/go.mod h1:QZHgU07PRBTRF6N57w4+ApRu8OgfYLFNqCDlfEZaD9Y= +github.com/tektoncd/plumbing/pipelinerun-logs v0.0.0-20191206114338-712d544c2c21/go.mod h1:S62EUWtqmejjJgUMOGB1CCCHRp6C706laH06BoALkzU= +github.com/tidwall/gjson v1.4.0 h1:w6iOJZt9BJOzz4VD9CSnRCX/oleCsAZWi+1FFzZA+SA= +github.com/tidwall/gjson v1.4.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= +github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= +github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.0.1 h1:WE4RBSZ1x6McVVC8S/Md+Qse8YUv6HRObAx6ke00NY8= +github.com/tidwall/pretty v1.0.1/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -655,12 +788,15 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok= github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo= +github.com/vdemeester/k8s-pkg-credentialprovider v1.13.12-1/go.mod h1:Fko0rTxEtDW2kju5Ky7yFJNS3IcNvW8IPsp4/e9oev0= github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vmware/govmomi v0.20.1/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/vmware/photon-controller-go-sdk v0.0.0-20170310013346-4a435daef6cc/go.mod h1:e6humHha1ekIwTCm+A5Qed5mG8V4JL+ChHcUOJ+L/8U= github.com/xanzy/go-cloudstack v0.0.0-20160728180336-1e2cbf647e57/go.mod h1:s3eL3z5pNXF5FVybcT+LIVdId8pYn709yv6v5mrkrQE= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= +github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -672,8 +808,12 @@ gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +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= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -695,18 +835,31 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72 golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20190806162312-597adff16ade/go.mod h1:AlhUtkH4DA4asiFC5RgK7ZKmauvtkAVcy9L0epCzlWo= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -721,15 +874,21 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r 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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-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 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68= golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914 h1:MlY3mEfbnWGmUi4rtHOtNnnnN4UJRGSyLPx+DXA5Sq4= +golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -741,6 +900,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= @@ -754,19 +915,30 @@ golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190219203350-90b0e4468f99/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-20190310054646-10058d7d4faa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-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-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190621203818-d432491b9138 h1:t8BZD9RDjkm9/h7yYN6kE8oaeov5r9aztkB7zKA5Tkg= golang.org/x/sys v0.0.0-20190621203818-d432491b9138/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 h1:gSbV7h1NRL2G1xTg/owz62CST1oJBmxy4QpMMregXVQ= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -775,10 +947,11 @@ 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-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg= 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-20170824195420-5d2fd3ccab98/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -796,14 +969,27 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/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-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010171213-8abd42400456/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191018212557-ed542cd5b28a/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-20191112005509-a3f652f18032/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200115165105-de0b1760071a h1:bEJ3JL2YUH3tt9KX9dsy0WUF3WOrhjtNjK93o0svepY= +golang.org/x/tools v0.0.0-20200115165105-de0b1760071a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 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= gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= @@ -814,6 +1000,9 @@ google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+ google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.10.0 h1:7tmAxx3oKE98VMZ+SBZzvYYWRQ9HODBxmC8mXUsraSQ= google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -821,24 +1010,40 @@ google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190708153700-3bdd9d9f5532/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 h1:4HYDjxeNXAOTv3o1N2tjo8UUSlhQgAD52FVkwxnWgM8= +google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= 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/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= @@ -857,21 +1062,31 @@ gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= 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/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= +gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= +gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= +gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= +gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/natefinch/lumberjack.v2 v2.0.0-20150622162204-20b71e5b60d7 h1:986b60BAz5vO2Vaf48yQaq+wb2bU4JsXxKu1+itW6x8= gopkg.in/natefinch/lumberjack.v2 v2.0.0-20150622162204-20b71e5b60d7/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.0.0-20180411045311-89060dee6a84/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= +gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.1.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -879,6 +1094,7 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 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-20190620084959-7cf5895f2711 h1:BblVYz/wE5WtBsD/Gvu54KyBUTJMflolzc5I2DTvh50= @@ -887,7 +1103,6 @@ k8s.io/apiextensions-apiserver v0.0.0-20190620085554-14e95df34f1f h1:+pHBUvIpLzm k8s.io/apiextensions-apiserver v0.0.0-20190620085554-14e95df34f1f/go.mod h1:++XMkbLSSAutLgulnUnXW4kNbSkyQzlPL8PaW4hjJT4= k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719 h1:uV4S5IB5g4Nvi+TBVNf3e9L4wrirlwYJ6w88jUQxTUw= k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= -k8s.io/apiserver v0.0.0-20190620085212-47dc9a115b18 h1:+C0wd/HnjyZ2I0SPqAy1cqfPoPxwZ0hUiNwj/EGTe6c= k8s.io/apiserver v0.0.0-20190620085212-47dc9a115b18/go.mod h1:Hc9PbFVOsMigd7B7OiY/6bIRkR8y31eIKsr1D+JtKg4= k8s.io/autoscaler v0.0.0-20190607113959-1b4f1855cb8e/go.mod h1:QEXezc9uKPT91dwqhSJq3GNI3B1HxFRQHiku9kmrsSA= k8s.io/cli-runtime v0.0.0-20190620085706-2090e6d8f84c h1:w9/2LqD258mHJmpbLczVn5bnsK6ppTqlA64NTsjXZMY= @@ -897,19 +1112,18 @@ k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aG k8s.io/cloud-provider v0.0.0-20190620090043-8301c0bda1f0/go.mod h1:UXU55LeVTrjyQNw86sHjagiYhSZjYxWKXvx0Ml17KvM= k8s.io/cluster-bootstrap v0.0.0-20190620090013-c9a0fc045dc1/go.mod h1:cCRw3eZzlJdySYRtkL/N4cAClxYCzyrBL3V8cblTlUo= k8s.io/code-generator v0.0.0-20190612205613-18da4a14b22b/go.mod h1:G8bQwmHm2eafm5bgtX67XDZQ8CWKSGu9DekI+yN4Y5I= -k8s.io/component-base v0.0.0-20190620085130-185d68e6e6ea h1:CAN9Jo6bb5+mp3s1/1w8TbaWIxYK1WGQwwYvlacSet4= k8s.io/component-base v0.0.0-20190620085130-185d68e6e6ea/go.mod h1:VLedAFwENz2swOjm0zmUXpAP2mV55c49xgaOzPBI/QQ= k8s.io/cri-api v0.0.0-20190531030430-6117653b35f1/go.mod h1:K6Ux7uDbzKhacgqW0OJg3rjXk/SR9kprCPfSUDXGB5A= k8s.io/csi-translation-lib v0.0.0-20190620090116-299a7b270edc/go.mod h1:L51Xd2IwQCsOBx41c4YZR9dY1h1IjMk8r3Nnv3L80KM= 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-20191010091904-7fa3014cb28f/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20191108084044-e500ee069b5c/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/heapster v1.2.0-beta.1/go.mod h1:h1uhptVXMwC8xtZBYsPXKVi8fpdlYkTs6k949KozGrM= k8s.io/helm v2.16.1+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= 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.3.3 h1:niceAagH1tzskmaie/icWd7ci1wbG7Bf2c6YGcQv+3c= k8s.io/klog v0.3.3/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= @@ -919,11 +1133,12 @@ k8s.io/kube-controller-manager v0.0.0-20190620085942-b7f18460b210/go.mod h1:FoQC k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190320154901-5e45bb682580/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= -k8s.io/kube-openapi v0.0.0-20190603182131-db7b694dc208 h1:5sW+fEHvlJI3Ngolx30CmubFulwH28DhKjGf70Xmtco= k8s.io/kube-openapi v0.0.0-20190603182131-db7b694dc208/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20190918143330-0270cf2f1c1d h1:Xpe6sK+RY4ZgCTyZ3y273UmFmURhjtoJiwOMbQsXitY= k8s.io/kube-openapi v0.0.0-20190918143330-0270cf2f1c1d/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-proxy v0.0.0-20190620085809-589f994ddf7f/go.mod h1:EP2frUhhC4rizGpCTYCnVS4+XZMh7Hyq40jOUvuAK5g= k8s.io/kube-scheduler v0.0.0-20190620085912-4acac5405ec6/go.mod h1:ktfBNqjRdtYUw2eFNk32TtxiGqOy00eiWua74iNEcLg= k8s.io/kube-state-metrics v1.7.2 h1:6vdtgXrrRRMSgnyDmgua+qvgCYv954JNfxXAtDkeLVQ= @@ -942,11 +1157,16 @@ k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d h1:1P0iBJsBzxRmR+dIFnM+Iu4aLxnoa7lBqozW/0uHbT8= k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +knative.dev/caching v0.0.0-20190719140829-2032732871ff/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg= +knative.dev/eventing-contrib v0.6.1-0.20190723221543-5ce18048c08b/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g= +knative.dev/pkg v0.0.0-20191111150521-6d806b998379/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +pack.ag/amqp v0.11.0/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/controller-runtime v0.2.0 h1:5gL30PXOisGZl+Osi4CmLhvMUj77BO3wJeouKF2va50= sigs.k8s.io/controller-runtime v0.2.0/go.mod h1:ZHqrRDZi3f6BzONcvlUxkqCKgwasGk5FZrnSv9TVZF4= sigs.k8s.io/controller-tools v0.2.2/go.mod h1:8SNGuj163x/sMwydREj7ld5mIMJu1cDanIfnx6xsU70= @@ -955,7 +1175,6 @@ sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5 sigs.k8s.io/kustomize/v3 v3.1.0 h1:FnNC1UtUjZlepvWUGwaAcFHw2rjNIaZvBUPCvaXz0Fo= sigs.k8s.io/kustomize/v3 v3.1.0/go.mod h1:ztX4zYc/QIww3gSripwF7TBOarBTm5BvyAMem0kCzOE= sigs.k8s.io/structured-merge-diff v0.0.0-20190302045857-e85c7b244fd2/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/testing_frameworks v0.1.1 h1:cP2l8fkA3O9vekpy5Ks8mmA0NW/F7yBdXf8brkWhVrs= sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U= diff --git a/pkg/kfapp/aws/OWNERS b/pkg/kfapp/aws/OWNERS new file mode 100644 index 00000000..0353f4d7 --- /dev/null +++ b/pkg/kfapp/aws/OWNERS @@ -0,0 +1,2 @@ +approvers: + - jeffwan diff --git a/pkg/kfapp/aws/aws.go b/pkg/kfapp/aws/aws.go index 4b8eee93..d3c2b2ce 100644 --- a/pkg/kfapp/aws/aws.go +++ b/pkg/kfapp/aws/aws.go @@ -19,18 +19,17 @@ package aws import ( "encoding/base64" "fmt" + "github.com/gogo/protobuf/proto" "io" "io/ioutil" "math/rand" "os" - "os/exec" "path" "path/filepath" "strconv" "strings" "time" - "github.com/kubeflow/kfctl/v3/pkg/utils" "golang.org/x/crypto/bcrypt" awssdk "github.com/aws/aws-sdk-go/aws" @@ -42,31 +41,35 @@ import ( kftypes "github.com/kubeflow/kfctl/v3/pkg/apis/apps" "github.com/kubeflow/kfctl/v3/pkg/kfconfig" "github.com/kubeflow/kfctl/v3/pkg/kfconfig/awsplugin" + "github.com/kubeflow/kfctl/v3/pkg/utils" "github.com/pkg/errors" log "github.com/sirupsen/logrus" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) const ( - KUBEFLOW_AWS_INFRA_DIR = "aws_config" - KUBEFLOW_MANIFEST_DIR = "kustomize" - CLUSTER_CONFIG_FILE = "cluster_config.yaml" - CLUSTER_FEATURE_CONFIG_FILE = "cluster_features.yaml" - PATH = "path" - BASIC_AUTH_SECRET = "kubeflow-login" - - // The namespace for Istio + KUBEFLOW_AWS_INFRA_DIR = "aws_config" + KUBEFLOW_MANIFEST_DIR = "kustomize" + CLUSTER_CONFIG_FILE = "cluster_config.yaml" + PATH = "path" + BASIC_AUTH_SECRET = "kubeflow-login" + // Path in manifests repo to where the additional configs are located + CONFIG_LOCAL_PATH = "aws/infra_configs" + + ALB_OIDC_SECRET = "alb-oidc-secret" + + // Namespace for istio IstioNamespace = "istio-system" // Plugin parameter constants AwsPluginName = kfconfig.AWS_PLUGIN_KIND - // Path in manifests repo to where the additional configs are located - CONFIG_LOCAL_PATH = "aws/infra_configs" + MINIMUM_EKSCTL_VERSION = "0.1.32" + + KUBEFLOW_ADMIN_ROLE_NAME = "kf-admin-%v" + KUBEFLOW_USER_ROLE_NAME = "kf-user-%v" ) // Aws implements KfApp Interface @@ -76,12 +79,16 @@ type Aws struct { iamClient *iam.IAM eksClient *eks.EKS sess *session.Session + k8sClient *clientset.Clientset + + cluster *Cluster region string roles []string - istioManifests []manifest - ingressManifests []manifest + istioManifests []manifest + ingressManifests []manifest + certManagerManifests []manifest } type manifest struct { @@ -91,6 +98,7 @@ type manifest struct { // GetKfApp returns the aws kfapp. It's called by coordinator.GetKfApp func GetPlatform(kfdef *kfconfig.KfConfig) (kftypes.Platform, error) { + // Manifest lists are used in `Delete` to make sure we track and clean up all the resources. istioManifests := []manifest{ { name: "Istio CRDs", @@ -101,23 +109,47 @@ func GetPlatform(kfdef *kfconfig.KfConfig) (kftypes.Platform, error) { path: path.Join(KUBEFLOW_MANIFEST_DIR, "istio-install", "base", "istio-noauth.yaml"), }, } - ingressManifests := []manifest{ { name: "ALB Ingress", path: path.Join(KUBEFLOW_MANIFEST_DIR, "istio-ingress", "base", "ingress.yaml"), }, } + certManagerManifests := []manifest{ + { + name: "Cert Manager", + path: path.Join(KUBEFLOW_MANIFEST_DIR, "cert-manager-crds", "base", "crd.yaml"), + }, + { + name: "Cert Manager API Service", + path: path.Join(KUBEFLOW_MANIFEST_DIR, "cert-manager", "base", "api-service.yaml"), + }, + { + name: "Cert Manager MutationWebhookConfig", + path: path.Join(KUBEFLOW_MANIFEST_DIR, "cert-manager", "base", "mutating-webhook-configuration.yaml"), + }, + { + name: "Cert Manager ValidatingWebhookConfiguration", + path: path.Join(KUBEFLOW_MANIFEST_DIR, "cert-manager", "base", "validating-webhook-configuration.yaml"), + }, + } session := session.Must(session.NewSession()) + k8sClient, err := getK8sclient() + if err != nil { + return nil, err + } + _aws := &Aws{ - kfDef: kfdef, - sess: session, - iamClient: iam.New(session), - eksClient: eks.New(session), - istioManifests: istioManifests, - ingressManifests: ingressManifests, + kfDef: kfdef, + sess: session, + iamClient: iam.New(session), + eksClient: eks.New(session), + k8sClient: k8sClient, + istioManifests: istioManifests, + ingressManifests: ingressManifests, + certManagerManifests: certManagerManifests, } return _aws, nil @@ -126,100 +158,24 @@ func GetPlatform(kfdef *kfconfig.KfConfig) (kftypes.Platform, error) { // GetPluginSpec gets the plugin spec. func (aws *Aws) GetPluginSpec() (*awsplugin.AwsPluginSpec, error) { awsPluginSpec := &awsplugin.AwsPluginSpec{} - err := aws.kfDef.GetPluginSpec(AwsPluginName, awsPluginSpec) - return awsPluginSpec, err } -// GetK8sConfig is only used with ksonnet packageManager. NotImplemented in this version, return nil to use default config for API compatibility. -func (aws *Aws) GetK8sConfig() (*rest.Config, *clientcmdapi.Config) { - return nil, nil -} - -func createNamespace(k8sClientset *clientset.Clientset, namespace string) error { - log.Infof("Creating namespace: %v", namespace) - _, err := k8sClientset.CoreV1().Namespaces().Get(namespace, metav1.GetOptions{}) - if err == nil { - log.Infof("Namespace already exists...") - return nil - } - log.Infof("Get namespace error: %v", err) - _, err = k8sClientset.CoreV1().Namespaces().Create( - &v1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: namespace, - }, - }, - ) - if err == nil { - return nil - } else { - return &kfapis.KfError{ - Code: int(kfapis.INTERNAL_ERROR), - Message: err.Error(), - } - } -} - -// Create a new EKS cluster if needed -func (aws *Aws) createEKSCluster() error { - config, err := aws.getFeatureConfig() - if err != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Reading config file error: %v", err), - } - } - - if _, ok := config["managed_cluster"]; !ok { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Unable to read YAML"), - } - } - - if config["managed_cluster"] == true { - log.Infoln("Start to create eks cluster. Please wait for 10-15 mins...") - clusterConfigFile := filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, CLUSTER_CONFIG_FILE) - output, err := exec.Command("eksctl", "create", "cluster", "--config-file="+clusterConfigFile).Output() - if err != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Call 'eksctl create cluster --config-file=%s' with errors: %v", clusterConfigFile, string(output)), - } - } - log.Infoln(string(output)) - - nodeGroupIamRoles, getRoleError := aws.getWorkerNodeGroupRoles(aws.kfDef.Name) - if getRoleError != nil { - return errors.WithStack(getRoleError) - } - - aws.roles = nodeGroupIamRoles - } else { - log.Infof("You already have cluster setup. Skip creating new eks cluster. ") - } - - return nil -} - -func (aws *Aws) attachPoliciesToWorkerRoles() error { - config, err := aws.getFeatureConfig() +func (aws *Aws) attachPoliciesToRoles(roles []string) error { + awsPluginSpec, err := aws.GetPluginSpec() if err != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Reading config file error: %v", err), - } + return err } - for _, iamRole := range aws.roles { + for _, iamRole := range roles { aws.attachIamInlinePolicy(iamRole, "iam_alb_ingress_policy", filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, "iam_alb_ingress_policy.json")) - aws.attachIamInlinePolicy(iamRole, "iam_csi_fsx_policy", - filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, "iam_csi_fsx_policy.json")) - - if config["worker_node_group_logging"] == "true" { + aws.attachIamInlinePolicy(iamRole, "iam_profile_controller_policy", + filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, "iam_profile_controller_policy.json")) + //aws.attachIamInlinePolicy(iamRole, "iam_csi_fsx_policy", + // filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, "iam_csi_fsx_policy.json")) + if awsPluginSpec.GetEnableNodeGroupLog() { aws.attachIamInlinePolicy(iamRole, "iam_cloudwatch_policy", filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, "iam_cloudwatch_policy.json")) } @@ -228,7 +184,7 @@ func (aws *Aws) attachPoliciesToWorkerRoles() error { return nil } -// TODO: waiting to be implemented. +// TODO: To be implemented. Consider to have EKS cluster config support. func (aws *Aws) updateEKSClusterConfig() error { return nil } @@ -331,7 +287,7 @@ func (aws *Aws) updateClusterConfig(clusterConfigFile string) error { return nil } -// ${KUBEFLOW_SRC}/${KFAPP}/aws_config -> destDir (dest) +// ${BASE_DIR}/${KFAPP}/aws_config -> destDir (dest) func (aws *Aws) generateInfraConfigs() error { // 1. Copy and Paste all files from `sourceDir` to `destDir` repo, ok := aws.kfDef.GetRepoCache(kftypes.ManifestsRepoName) @@ -348,21 +304,21 @@ func (aws *Aws) generateInfraConfigs() error { log.Infof("Creating AWS infrastructure configs in directory %v", destDir) destDirErr := os.MkdirAll(destDir, os.ModePerm) if destDirErr != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Cannot create directory %v", destDirErr), - } + return destDirErr } } else { log.Infof("AWS infrastructure configs already exist in directory %v", destDir) } - files := []string{"cluster_config.yaml", "cluster_features.yaml", "iam_alb_ingress_policy.json", - "iam_cloudwatch_policy.json", "iam_csi_fsx_policy.json"} + // List all the files under source directory + files, err := ioutil.ReadDir(sourceDir) + if err != nil { + return err + } for _, file := range files { - sourceFile := filepath.Join(sourceDir, file) - destFile := filepath.Join(destDir, file) + sourceFile := filepath.Join(sourceDir, file.Name()) + destFile := filepath.Join(destDir, file.Name()) copyErr := copyFile(sourceFile, destFile) if copyErr != nil { return &kfapis.KfError{ @@ -379,52 +335,11 @@ func (aws *Aws) generateInfraConfigs() error { return err } - // 3. Update managed_cluster based on roles - // By default, let's have managed_cluster true. If user pass roles, we make it false. - featureCfg, err := aws.getFeatureConfig() - if err != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Can not get AWS feature config file %v", err), - } - } - - if aws.roles != nil && len(aws.roles) != 0 { - featureCfg["managed_cluster"] = false - } else { - featureCfg["managed_cluster"] = true - } - - writeFeatureCfgErr := aws.writeFeatureConfig(featureCfg) - if writeFeatureCfgErr != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Can not update AWS feature config file %v", err), - } - } - + // 3. Update managed_cluster + // @Deprecated. Don't need to update the field, we add configs part of awsPluginSpec. It's false by default return nil } -func insertSecret(client *clientset.Clientset, secretName string, namespace string, data map[string][]byte) error { - secret := &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - Namespace: namespace, - }, - Data: data, - } - _, err := client.CoreV1().Secrets(namespace).Create(secret) - if err == nil { - return nil - } else { - return &kfapis.KfError{ - Code: int(kfapis.INTERNAL_ERROR), - Message: err.Error(), - } - } -} - // Use username and password provided by user and create secret for basic auth. func (aws *Aws) createBasicAuthSecret(client *clientset.Clientset) error { awsPluginSpec, err := aws.GetPluginSpec() @@ -462,7 +377,7 @@ func (aws *Aws) createBasicAuthSecret(client *clientset.Clientset) error { _, err = client.CoreV1().Secrets(aws.kfDef.Namespace).Update(secret) if err != nil { log.Warnf("Updating basic auth login failed, trying to create one: %v", err) - return insertSecret(client, BASIC_AUTH_SECRET, aws.kfDef.Namespace, map[string][]byte{ + return createSecret(client, BASIC_AUTH_SECRET, aws.kfDef.Namespace, map[string][]byte{ "username": []byte(awsPluginSpec.Auth.BasicAuth.Username), "passwordhash": []byte(encodedPassword), }) @@ -497,24 +412,20 @@ func (aws *Aws) Init(resources kftypes.ResourceEnum) error { } // 2. Check if current eksctl version meets minimum requirement - // [ℹ] version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.1.32"} - if err := utils.GetEksctlVersion(); err != nil { - if err != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Can not run eksctl version is %v", err), - } + version, err := utils.GetEksctlVersion() + if err != nil { + return &kfapis.KfError{ + Code: int(kfapis.INVALID_ARGUMENT), + Message: fmt.Sprintf("Can not run eksctl version %v", err), } } - // Should not need to write config here? - // createConfigErr := aws.kfDef.WriteToConfigFile() - // if createConfigErr != nil { - // return &kfapis.KfError{ - // Code: int(kfapis.INVALID_ARGUMENT), - // Message: fmt.Sprintf("Cannot create config file app.yaml in %v", aws.kfDef.Spec.AppDir), - // } - // } + if lessThan, err := isEksctlVersionLessThan(version, MINIMUM_EKSCTL_VERSION); err != nil || lessThan { + return &kfapis.KfError{ + Code: int(kfapis.INVALID_ARGUMENT), + Message: fmt.Sprintf("eksctl version has to be great than %s %v", MINIMUM_EKSCTL_VERSION, err), + } + } return nil } @@ -524,14 +435,14 @@ func (aws *Aws) Init(resources kftypes.ResourceEnum) error { func (aws *Aws) Generate(resources kftypes.ResourceEnum) error { awsDir := path.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR) if _, err := os.Stat(awsDir); err == nil { - log.Infof("folder %v exists, skip aws.Generate", awsDir) + log.Infof("Folder %v exists, skip aws.Generate", awsDir) return nil } else if !os.IsNotExist(err) { - log.Errorf("Stat folder %v error: %v; try deleting it...", awsDir, err) + log.Errorf("Stat folder %v error: %v; trying to delete it...", awsDir, err) _ = os.RemoveAll(awsDir) } - // use aws to call sts get-caller-identity to verify aws credential works. + // Use aws sts get-caller-identity to verify aws credential setting if err := utils.CheckAwsStsCallerIdentity(aws.sess); err != nil { return &kfapis.KfError{ Code: int(kfapis.INVALID_ARGUMENT), @@ -542,7 +453,7 @@ func (aws *Aws) Generate(resources kftypes.ResourceEnum) error { if setAwsPluginDefaultsErr := aws.setAwsPluginDefaults(); setAwsPluginDefaultsErr != nil { return &kfapis.KfError{ Code: setAwsPluginDefaultsErr.(*kfapis.KfError).Code, - Message: fmt.Sprintf("aws set aws plugin defaults Error %v", + Message: fmt.Sprintf("Set aws plugin defaults Error %v", setAwsPluginDefaultsErr.(*kfapis.KfError).Message), } } @@ -555,14 +466,6 @@ func (aws *Aws) Generate(resources kftypes.ResourceEnum) error { } } - awsFeatureConfig, getAwsFeatureConfigErr := aws.getFeatureConfig() - if getAwsFeatureConfigErr != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Reading config file error: %v", getAwsFeatureConfigErr), - } - } - pluginSpec, err := aws.GetPluginSpec() if err != nil { return errors.WithStack(err) @@ -576,6 +479,7 @@ func (aws *Aws) Generate(resources kftypes.ResourceEnum) error { return errors.WithStack(err) } + // TODO: AWS doesn't enable BasicAuth yet. if aws.kfDef.Spec.UseBasicAuth { if err := aws.kfDef.SetApplicationParameter("istio", "clusterRbacConfig", "OFF"); err != nil { return errors.WithStack(err) @@ -584,19 +488,12 @@ func (aws *Aws) Generate(resources kftypes.ResourceEnum) error { if pluginSpec.Auth.BasicAuth == nil { return errors.WithStack(fmt.Errorf("AwsPluginSpec has no BasicAuth but UseBasicAuth set to true")) } - - // TODO: enable Basic Auth later } else { - // TODO: Need to change profile header - //if err := aws.kfDef.SetApplicationParameter("istio", "clusterRbacConfig", "ON"); err != nil { - // return errors.WithStack(err) - //} - // - //if pluginSpec.Auth.Cognito == nil && pluginSpec.Auth.Oidc == nil { - // return errors.WithStack(fmt.Errorf("AwsPluginSpec has no OIDC or Cognito but UseBasicAuth set to false")) - //} - if pluginSpec.Auth.Cognito != nil { + if err := aws.kfDef.SetApplicationParameter("istio", "clusterRbacConfig", "ON"); err != nil { + return errors.WithStack(err) + } + if err := aws.kfDef.SetApplicationParameter("istio-ingress", "CognitoUserPoolArn", pluginSpec.Auth.Cognito.CognitoUserPoolArn); err != nil { return errors.WithStack(err) } @@ -614,7 +511,20 @@ func (aws *Aws) Generate(resources kftypes.ResourceEnum) error { } } + // By default we use cognito overlay in manifest, remove cognito and add oidc overlay if this is enabled. if pluginSpec.Auth.Oidc != nil { + if err := aws.kfDef.SetApplicationParameter("istio", "clusterRbacConfig", "ON"); err != nil { + return errors.WithStack(err) + } + + if err := aws.kfDef.RemoveApplicationOverlay("istio-ingress", "cognito"); err != nil { + return errors.WithStack(err) + } + + if err := aws.kfDef.AddApplicationOverlay("istio-ingress", "oidc"); err != nil { + return errors.WithStack(err) + } + if err := aws.kfDef.SetApplicationParameter("istio-ingress", "oidcIssuer", pluginSpec.Auth.Oidc.OidcIssuer); err != nil { return errors.WithStack(err) } @@ -635,18 +545,15 @@ func (aws *Aws) Generate(resources kftypes.ResourceEnum) error { return errors.WithStack(err) } - if err := aws.kfDef.SetApplicationParameter("istio-ingress", "clientId", pluginSpec.Auth.Oidc.OAuthClientId); err != nil { - return errors.WithStack(err) - } - - if err := aws.kfDef.SetApplicationParameter("istio-ingress", "clientSecret", pluginSpec.Auth.Oidc.OAuthClientSecret); err != nil { + //TODO: consider to use secret from secretGenerator? + if err := aws.kfDef.SetApplicationParameter("istio-ingress", "oidcSecretName", ALB_OIDC_SECRET); err != nil { return errors.WithStack(err) } } } // Special handling for cloud watch logs of worker node groups - if awsFeatureConfig["worker_node_group_logging"] == true { + if pluginSpec.GetEnableNodeGroupLog() { //aws.kfDef.Spec.Components = append(aws.kfDef.Spec.Components, "fluentd-cloud-watch") if err := aws.kfDef.SetApplicationParameter("fluentd-cloud-watch", "clusterName", aws.kfDef.Name); err != nil { return errors.WithStack(err) @@ -656,6 +563,64 @@ func (aws *Aws) Generate(resources kftypes.ResourceEnum) error { } } + // Special handling for managed SQL service + if pluginSpec.ManagedRelationDatabase != nil { + // Setup metadata -> remove `db` overlay, add `external-mysql` overlay + if err := aws.kfDef.RemoveApplicationOverlay("metadata", "db"); err != nil { + return errors.WithStack(err) + } + + if err := aws.kfDef.AddApplicationOverlay("metadata", "external-mysql"); err != nil { + return errors.WithStack(err) + } + + // add external-mysql to pipeline/api-service and external-mysql to metadata, + if err := aws.kfDef.SetApplicationParameter("metadata", "MYSQL_HOST", pluginSpec.ManagedRelationDatabase.Host); err != nil { + return errors.WithStack(err) + } + + if err := aws.kfDef.SetApplicationParameter("metadata", "MYSQL_USERNAME", string(pluginSpec.ManagedRelationDatabase.Username)); err != nil { + return errors.WithStack(err) + } + + if err := aws.kfDef.SetApplicationParameter("metadata", "MYSQL_ROOT_PASSWORD", string(pluginSpec.ManagedRelationDatabase.Password)); err != nil { + return errors.WithStack(err) + } + + if pluginSpec.ManagedRelationDatabase.Port != nil { + if err := aws.kfDef.SetApplicationParameter("metadata", "MYSQL_PORT", string(*pluginSpec.ManagedRelationDatabase.Port)); err != nil { + return errors.WithStack(err) + } + } + + // Setup pipeline/api-service -> move mysql application, add external-mysql overlay to pipeline/api-service + if err := aws.kfDef.DeleteApplication("mysql"); err != nil { + return errors.WithStack(err) + } + + if err := aws.kfDef.AddApplicationOverlay("api-service", "external-mysql"); err != nil { + return errors.WithStack(err) + } + + // add external-mysql to pipeline/api-service and external-mysql to metadata, + if err := aws.kfDef.SetApplicationParameter("api-service", "mysqlHost", pluginSpec.ManagedRelationDatabase.Host); err != nil { + return errors.WithStack(err) + } + + if err := aws.kfDef.SetApplicationParameter("api-service", "mysqlUser", pluginSpec.ManagedRelationDatabase.Username); err != nil { + return errors.WithStack(err) + } + + if err := aws.kfDef.SetApplicationParameter("api-service", "mysqlPassword", pluginSpec.ManagedRelationDatabase.Password); err != nil { + return errors.WithStack(err) + } + } + + // Special handling for managed object storage + if pluginSpec.ManagedObjectStorage != nil { + // TODO: replace worker-controller, pipeline, etc layer + } + // Special handling for sparkakus rand.Seed(time.Now().UnixNano()) if err := aws.kfDef.SetApplicationParameter("spartakus", "usageId", strconv.Itoa(rand.Int())); err != nil { @@ -664,40 +629,49 @@ func (aws *Aws) Generate(resources kftypes.ResourceEnum) error { } } - // Should not need to write config here. - // if createConfigErr := aws.kfDef.WriteToConfigFile(); createConfigErr != nil { - // return &kfapis.KfError{ - // Code: createConfigErr.(*kfapis.KfError).Code, - // Message: fmt.Sprintf("Cannot create config file app.yaml in %v: %v", aws.kfDef.Spec.AppDir, - // createConfigErr.(*kfapis.KfError).Message), - // } - // } return nil } func (aws *Aws) setAwsPluginDefaults() error { awsPluginSpec, err := aws.GetPluginSpec() - if err != nil { return err } - // TODO: enable validation once we support basic auth - //if isValid, msg := awsPluginSpec.IsValid(); !isValid { - // log.Errorf("AwsPluginSpec isn't valid; error %v", msg) - // return fmt.Errorf(msg) - //} + if isValid, msg := awsPluginSpec.IsValid(); !isValid { + log.Errorf("AwsPluginSpec isn't valid; error %v", msg) + return fmt.Errorf(msg) + } aws.region = awsPluginSpec.Region aws.roles = awsPluginSpec.Roles + if awsPluginSpec.ManagedCluster == nil { + awsPluginSpec.ManagedCluster = proto.Bool(awsPluginSpec.GetManagedCluster()) + log.Infof("ManagedCluster set defaulting to %v", *awsPluginSpec.ManagedCluster) + } + + if awsPluginSpec.EnablePodIamPolicy == nil { + awsPluginSpec.EnablePodIamPolicy = proto.Bool(awsPluginSpec.GetEnablePodIamPolicy()) + log.Infof("EnablePodIamPolicy set defaulting to %v", *awsPluginSpec.EnablePodIamPolicy) + } + + if awsPluginSpec.EnableNodeGroupLog == nil { + awsPluginSpec.EnableNodeGroupLog = proto.Bool(awsPluginSpec.GetEnableNodeGroupLog()) + log.Infof("EnableNodeGroupLog set defaulting to %v", *awsPluginSpec.EnableNodeGroupLog) + } + + if awsPluginSpec.Auth == nil { + awsPluginSpec.Auth = &awsplugin.Auth{} + } + return nil } // Apply create eks cluster if needed, bind IAM policy to node group roles and enable cluster level configs. // Remind: Need to be thread-safe: this entry is share among kfctl and deploy app func (aws *Aws) Apply(resources kftypes.ResourceEnum) error { - // use aws to call sts get-caller-identity to verify aws credential works. + // use aws sts get-caller-identity to verify aws credential works. if err := utils.CheckAwsStsCallerIdentity(aws.sess); err != nil { return &kfapis.KfError{ Code: int(kfapis.INVALID_ARGUMENT), @@ -722,20 +696,58 @@ func (aws *Aws) Apply(resources kftypes.ResourceEnum) error { } } - // 2. Attach IAM policies like ALB, FSX, EFS, cloudWatch Fluentd to worker node group roles - // TODO: Once pod level IAM complete, we don't need worker group roles. Authorize cloud services using service account. - if err := aws.attachPoliciesToWorkerRoles(); err != nil { + // 2. For non-eks cluster (kops) or user doesn't enable pod level IAM policy, + // attach IAM policies like ALB, FSX, EFS, cloudWatch Fluentd to worker node group roles + // For eks cluster enable pod IAM, we create identity provider and role. Override kubeflow components service account with annotation. + awsPluginSpec, err := aws.GetPluginSpec() + if err != nil { + return &kfapis.KfError{ + Code: int(kfapis.INVALID_ARGUMENT), + Message: fmt.Sprintf("Could not get awsPluginSpec %v", err), + } + } + + isEksCluster, err := aws.IsEksCluster(aws.kfDef.Name) + if err != nil { + return &kfapis.KfError{ + Code: int(kfapis.INVALID_ARGUMENT), + Message: fmt.Sprintf("Could not determinte it's EKS cluster %v", err), + } + } + + if err := createNamespace(aws.k8sClient, aws.kfDef.Namespace); err != nil { + return &kfapis.KfError{ + Code: int(kfapis.INTERNAL_ERROR), + Message: fmt.Sprintf("Could not create namespace %v", err), + } + } + + // Create IAM role binding for k8s service account. + if awsPluginSpec.GetEnablePodIamPolicy() && isEksCluster { + err := aws.setupIamRoleForServiceAccount() + if err != nil { + return &kfapis.KfError{ + Code: int(kfapis.INVALID_ARGUMENT), + Message: fmt.Sprintf("Could not setup pod IAM policy %v", err), + } + } + } else if awsPluginSpec.GetEnablePodIamPolicy() { + return &kfapis.KfError{ + Code: int(kfapis.INVALID_ARGUMENT), + Message: fmt.Sprintf("IAM for Service Account is not supported on non-EKS cluster %v", err), + } + } + + // 3. Attach policies to worker node groups. This will be used by both EKS and non-EKS AWS Kubernetes clusters. + if err := aws.attachPoliciesToRoles(aws.roles); err != nil { return &kfapis.KfError{ Code: err.(*kfapis.KfError).Code, Message: fmt.Sprintf("Failed to attach IAM policies %v", err.(*kfapis.KfError).Message), } - } - // 3. Update cluster configs to enable master log or private access config. - // TODO: Once CloudFormation add support for master log/ private access, we can configure in cluster_config.yaml. - // https://github.com/weaveworks/eksctl/issues/778 + // 4. Update cluster configs to enable master log or private access config. if err := aws.updateEKSClusterConfig(); err != nil { return &kfapis.KfError{ Code: err.(*kfapis.KfError).Code, @@ -744,6 +756,15 @@ func (aws *Aws) Apply(resources kftypes.ResourceEnum) error { } } + // 5. Setup OIDC create OIDC secret for ALB + if err := aws.setupOIDC(); err != nil { + return &kfapis.KfError{ + Code: err.(*kfapis.KfError).Code, + Message: fmt.Sprintf("Failed to update create OIDC secret for ALB %v", + err.(*kfapis.KfError).Message), + } + } + return nil } @@ -765,7 +786,7 @@ func (aws *Aws) Delete(resources kftypes.ResourceEnum) error { } } - // 1. Delete ingress and istio dependencies + // 1. Delete ingress and istio, cert-manager dependencies if err := aws.uninstallK8sDependencies(); err != nil { return &kfapis.KfError{ Code: err.(*kfapis.KfError).Code, @@ -774,61 +795,33 @@ func (aws *Aws) Delete(resources kftypes.ResourceEnum) error { } // 2. Detach inline policies from worker IAM Roles - if err := aws.detachPoliciesToWorkerRoles(); err != nil { + if err := aws.detachPoliciesFromWorkerRoles(); err != nil { return &kfapis.KfError{ Code: err.(*kfapis.KfError).Code, Message: fmt.Sprintf("Could not detach iam role Error: %v", err.(*kfapis.KfError).Message), } } - // 3. Delete EKS cluster - if err := aws.uninstallEKSCluster(); err != nil { + // 3. Delete WebIdentityIAMRole and OIDC Provider and pre-configured roles + if err := aws.deleteWebIdentityRolesAndProvider(); err != nil { return &kfapis.KfError{ Code: err.(*kfapis.KfError).Code, - Message: fmt.Sprintf("Could not uninstall eks cluster Error: %v", err.(*kfapis.KfError).Message), + Message: fmt.Sprintf("Could not detach iam role Error: %v", err.(*kfapis.KfError).Message), } } - return nil -} - -// writeFeatureConfig writes KfDef to app.yaml -func (aws *Aws) writeFeatureConfig(featureConfig map[string]interface{}) error { - buf, bufErr := yaml.Marshal(featureConfig) - if bufErr != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("AWS marshaling error: %v", bufErr), - } - } - featureCfgFilePath := filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, CLUSTER_FEATURE_CONFIG_FILE) - featureCfgFilePathErr := ioutil.WriteFile(featureCfgFilePath, buf, 0644) - if featureCfgFilePathErr != nil { + // 4. Delete EKS cluster + if err := aws.deleteEKSCluster(); err != nil { return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("AWS config file writing error: %v", featureCfgFilePathErr), + Code: err.(*kfapis.KfError).Code, + Message: fmt.Sprintf("Could not uninstall eks cluster Error: %v", err.(*kfapis.KfError).Message), } } - return nil -} - -func (aws *Aws) getFeatureConfig() (map[string]interface{}, error) { - configPath := filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, CLUSTER_FEATURE_CONFIG_FILE) - log.Infof("Reading config file: %v", configPath) - configBuf, bufErr := ioutil.ReadFile(configPath) - if bufErr != nil { - return nil, bufErr - } - - var config map[string]interface{} - if err := yaml.Unmarshal(configBuf, &config); err != nil { - return nil, err - } - - return config, nil + return nil } +// uninstallK8sDependencies delete istio-ingress, istio and cert-manager dependencies. func (aws *Aws) uninstallK8sDependencies() error { rev := func(manifests []manifest) []manifest { var r []manifest @@ -839,6 +832,7 @@ func (aws *Aws) uninstallK8sDependencies() error { return r } + // 1. Delete Ingress and wait for 15s for alb-ingress-controller to clean up resources if err := deleteManifests(rev(aws.ingressManifests)); err != nil { return errors.WithStack(err) } @@ -847,6 +841,17 @@ func (aws *Aws) uninstallK8sDependencies() error { log.Infof("Wait for %d seconds for alb ingress controller to clean up ALB", albCleanUpInSeconds) time.Sleep(time.Duration(albCleanUpInSeconds) * time.Second) + // 2. Delete cert-manager manifest. + // Simplify process by deleting cert-manager namespace, don't have to delete every single manifest + if err := deleteNamespace(aws.k8sClient, "cert-manager"); err != nil { + return errors.WithStack(err) + } + + if err := deleteManifests(rev(aws.certManagerManifests)); err != nil { + return errors.WithStack(err) + } + + // 3. Delete istio dependencies if err := deleteManifests(rev(aws.istioManifests)); err != nil { return errors.WithStack(err) } @@ -874,47 +879,42 @@ func deleteManifests(manifests []manifest) error { return nil } -func (aws *Aws) detachPoliciesToWorkerRoles() error { - config, err := aws.getFeatureConfig() +func (aws *Aws) detachPoliciesFromWorkerRoles() error { + awsPluginSpec, err := aws.GetPluginSpec() if err != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Reading config file error: %v", err), - } - } - - if _, ok := config["worker_node_group_logging"]; !ok { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Unable to read feature config YAML: %v", err), - } + return errors.WithStack(err) } var roles []string + eksCluster, err := aws.getEksCluster(aws.kfDef.Name) + if err != nil { + return err + } - // Find worker roles based on new cluster kfctl created or existing cluster - if config["managed_cluster"] == true { - workerRoles, err := aws.getWorkerNodeGroupRoles(aws.kfDef.Name) - if err != nil { - return errors.WithStack(err) - } - - roles = workerRoles + if awsPluginSpec.GetEnablePodIamPolicy() { + // no matter it's managed or self-managed cluster, we setup kf-admin roles. + roles = append(roles, fmt.Sprintf(KUBEFLOW_ADMIN_ROLE_NAME, eksCluster.name)) } else { - awsPluginSpec, err := aws.GetPluginSpec() - if err != nil { - return errors.WithStack(err) + // Find worker roles based on new cluster kfctl created or existing cluster + if awsPluginSpec.GetManagedCluster() { + workerRoles, err := aws.getWorkerNodeGroupRoles(aws.kfDef.Name) + if err != nil { + return errors.WithStack(err) + } + roles = workerRoles + } else { + roles = awsPluginSpec.Roles } - - roles = awsPluginSpec.Roles } // Detach IAM Policies for _, iamRole := range roles { aws.deleteIamRolePolicy(iamRole, "iam_alb_ingress_policy") - aws.deleteIamRolePolicy(iamRole, "iam_csi_fsx_policy") + aws.deleteIamRolePolicy(iamRole, "iam_profile_controller_policy") - if config["worker_node_group_logging"] == "true" { + // TODO: use Addon to check permissions + // aws.deleteIamRolePolicy(iamRole, "iam_csi_fsx_policy") + if awsPluginSpec.GetEnableNodeGroupLog() { aws.deleteIamRolePolicy(iamRole, "iam_cloudwatch_policy") } } @@ -922,40 +922,7 @@ func (aws *Aws) detachPoliciesToWorkerRoles() error { return nil } -func (aws *Aws) uninstallEKSCluster() error { - config, err := aws.getFeatureConfig() - if err != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Reading feature config file error: %v", err), - } - } - - if _, ok := config["managed_cluster"]; !ok { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("Unable to read YAML: %v", err), - } - } - - // Delete cluster if it's a managed cluster created by kfctl - if config["managed_cluster"] == true { - log.Infoln("Start to delete eks cluster. Please wait for 5 mins...") - clusterConfigFile := filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, CLUSTER_CONFIG_FILE) - output, err := exec.Command("eksctl", "delete", "cluster", "--config-file="+clusterConfigFile).Output() - log.Infoln("Please go to aws console to check CloudFormation status and double make sure your cluster has been shutdown.") - if err != nil { - return &kfapis.KfError{ - Code: int(kfapis.INVALID_ARGUMENT), - Message: fmt.Sprintf("could not call 'eksctl delete cluster --config-file=%s': %v", clusterConfigFile, string(output)), - } - } - log.Infoln(string(output)) - } - - return nil -} - +// deleteIamRolePolicy detach inline policy from the role func (aws *Aws) deleteIamRolePolicy(roleName, policyName string) error { log.Infof("Deleting inline policy %s for iam role %s", policyName, roleName) @@ -964,18 +931,17 @@ func (aws *Aws) deleteIamRolePolicy(roleName, policyName string) error { RoleName: awssdk.String(roleName), } - result, err := aws.iamClient.DeleteRolePolicy(input) + _, err := aws.iamClient.DeleteRolePolicy(input) // This error can be skipped and should not block delete process. // It's possible user make any changes on IAM role. if err != nil { log.Warnf("Unable to delete iam inline policy %s because %v", policyName, err.Error()) - } else { - log.Infof("Successfully delete policy from IAM Role %v", result) } return nil } +// attachIamInlinePolicy attach inline policy to IAM role func (aws *Aws) attachIamInlinePolicy(roleName, policyName, policyDocumentPath string) error { log.Infof("Attaching inline policy %s for iam role %s", policyName, roleName) policyDocumentJSONBytes, _ := ioutil.ReadFile(policyDocumentPath) @@ -995,3 +961,138 @@ func (aws *Aws) attachIamInlinePolicy(roleName, policyName, policyDocumentPath s log.Infof("Successfully attach policy to IAM Role %v", roleName) return nil } + +// setupIamRoleForServiceAccount will create/reuse IAM identity provider and create/reuse web identity role. +func (aws *Aws) setupIamRoleForServiceAccount() error { + eksCluster, err := aws.getEksCluster(aws.kfDef.Name) + if err != nil { + return err + } + + accountId, err := utils.CheckAwsAccountId(aws.sess) + if err != nil { + return errors.Errorf("Can not find accountId for cluster %v", aws.kfDef.Name) + } + + // Create Identity Provider. + issuerURLWithoutProtocol := eksCluster.oidcIssuerUrl[len("https://"):] + exist, arn, err := aws.checkIdentityProviderExists(accountId, issuerURLWithoutProtocol) + if err != nil { + return errors.Errorf("Can not check identity provider existence: %v", err) + } + + oidcProviderArn := arn + if !exist { + arn, err := aws.createIdentityProvider(eksCluster.oidcIssuerUrl) + if err != nil { + return errors.Errorf("Can not check identity provider existence: %v", err) + } + oidcProviderArn = arn + } + + // Link service account, role and policy + kubeflowSAIamRoleMapping := map[string]string{ + "kf-admin": fmt.Sprintf(KUBEFLOW_ADMIN_ROLE_NAME, eksCluster.name), + "alb-ingress-controller": fmt.Sprintf(KUBEFLOW_ADMIN_ROLE_NAME, eksCluster.name), + "profiles-controller-service-account": fmt.Sprintf(KUBEFLOW_ADMIN_ROLE_NAME, eksCluster.name), + "fluentd": fmt.Sprintf(KUBEFLOW_ADMIN_ROLE_NAME, eksCluster.name), + "kf-user": fmt.Sprintf(KUBEFLOW_USER_ROLE_NAME, eksCluster.name), + } + + for ksa, iamRoleName := range kubeflowSAIamRoleMapping { + // 1. Create AWS IAM Roles with web identity provider as trusted identities + if err := aws.createOrUpdateWebIdentityRole(oidcProviderArn, issuerURLWithoutProtocol, iamRoleName, aws.kfDef.Namespace, ksa); err != nil { + return errors.Errorf("Can not create web identity role: %v", err) + } + + // 2. Create Kubernetes Service Account + iamRoleArn := fmt.Sprintf(AWS_IAM_ROLE_ARN, accountId, iamRoleName) + if err := aws.createOrUpdateK8sServiceAccount(aws.k8sClient, aws.kfDef.Namespace, ksa, iamRoleArn); err != nil { + return errors.Errorf("Can not create Service Account %s/%s, %v", aws.kfDef.Namespace, ksa, err) + } + + // 3. Link KSA to IAM Role - add service account in Role Trust Relationships + if err := aws.updateRoleTrustIdentity(iamRoleName, aws.kfDef.Namespace, ksa); err != nil { + return errors.Errorf("Can not update IAM role trust relationships %v", err) + } + } + + // We only want to attach admin role at this moment. + // Grant kf-user policies later, based on the potential actions use may have, like ECR access, S3 access, etc. + aws.roles = append(aws.roles, fmt.Sprintf(KUBEFLOW_ADMIN_ROLE_NAME, eksCluster.name)) + return nil +} + +func (aws *Aws) deleteWebIdentityRolesAndProvider() error { + awsPluginSpec, err := aws.GetPluginSpec() + if err != nil { + return errors.WithStack(err) + } + + if !awsPluginSpec.GetEnablePodIamPolicy() { + log.Infof("Pod IAM Policy is not set, skip delete web identity provider") + return nil + } + + eksCluster, err := aws.getEksCluster(aws.kfDef.Name) + if err != nil { + return err + } + + // Delete IAM role we created + kfAdminRoleName := fmt.Sprintf(KUBEFLOW_ADMIN_ROLE_NAME, eksCluster.name) + kfUserRoleName := fmt.Sprintf(KUBEFLOW_USER_ROLE_NAME, eksCluster.name) + aws.deleteIAMRole(kfAdminRoleName) + aws.deleteIAMRole(kfUserRoleName) + log.Infof("IAM Role %s, %s has been deleted", kfAdminRoleName, kfUserRoleName) + + accountId, err := utils.CheckAwsAccountId(aws.sess) + if err != nil { + return errors.Errorf("Can not find accountId for cluster %v", aws.kfDef.Name) + } + + // Delete oidc web identity provider + issuerURLWithoutProtocol := eksCluster.oidcIssuerUrl[len("https://"):] + exist, arn, err := aws.checkIdentityProviderExists(accountId, issuerURLWithoutProtocol) + if err != nil { + return errors.Errorf("Can not check identity provider existence: %v", err) + } + + if !exist { + log.Warnf("Identity provider %v of cluster %v does not exist", arn, eksCluster.name) + return nil + } + + if err := aws.DeleteIdentityProvider(arn); err != nil { + return err + } + + log.Infof("OIDC Identity Provider has been delete %s", issuerURLWithoutProtocol) + + return nil +} + +// setupOIDC creates secret for ALB ingress controller +func (aws *Aws) setupOIDC() error { + awsPluginSpec, err := aws.GetPluginSpec() + if err != nil { + return err + } + + if awsPluginSpec.Auth.Oidc != nil { + // Create OIDC Secret from clientId and clientSecret. + _, err = aws.k8sClient.CoreV1().Secrets(IstioNamespace).Get(ALB_OIDC_SECRET, metav1.GetOptions{}) + if err == nil { + log.Warnf("Secret %v already exists...", ALB_OIDC_SECRET) + return nil + } + + // This secret need to be in istio-system, same namespace as istio-ingress + return createSecret(aws.k8sClient, ALB_OIDC_SECRET, IstioNamespace, map[string][]byte{ + "clientId": []byte(awsPluginSpec.Auth.Oidc.OAuthClientId), + "clientSecret": []byte(awsPluginSpec.Auth.Oidc.OAuthClientSecret), + }) + } + + return nil +} diff --git a/pkg/kfapp/aws/eks.go b/pkg/kfapp/aws/eks.go new file mode 100644 index 00000000..964a4afa --- /dev/null +++ b/pkg/kfapp/aws/eks.go @@ -0,0 +1,143 @@ +package aws + +import ( + "fmt" + awssdk "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/eks" + versionChecker "github.com/hashicorp/go-version" + kfapis "github.com/kubeflow/kfctl/v3/pkg/apis" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" + "os/exec" + "path/filepath" +) + +type Cluster struct { + name string + apiServerEndpoint string + oidcIssuerUrl string + clusterArn string + roleArn string + kubernetesVersion string +} + +// getEksCluster obtain detail info of an eks cluster +func (aws *Aws) getEksCluster(clusterName string) (*Cluster, error) { + input := &eks.DescribeClusterInput{ + Name: awssdk.String(clusterName), + } + + result, err := aws.eksClient.DescribeCluster(input) + if err != nil { + return nil, err + } + + cluster := &Cluster{ + name: awssdk.StringValue(result.Cluster.Name), + apiServerEndpoint: awssdk.StringValue(result.Cluster.Endpoint), + oidcIssuerUrl: awssdk.StringValue(result.Cluster.Identity.Oidc.Issuer), + clusterArn: awssdk.StringValue(result.Cluster.Arn), + roleArn: awssdk.StringValue(result.Cluster.RoleArn), + kubernetesVersion: awssdk.StringValue(result.Cluster.Version), + } + + return cluster, nil +} + +// IsEksCluster checks if an AWS cluster is EKS cluster. +func (aws *Aws) IsEksCluster(clusterName string) (bool, error) { + input := &eks.DescribeClusterInput{ + Name: awssdk.String(clusterName), + } + + exist := true + if _, err := aws.eksClient.DescribeCluster(input); err != nil { + if aerr, ok := err.(awserr.Error); ok { + if aerr.Code() != eks.ErrCodeResourceNotFoundException { + return false, err + } + exist = false + } + } + + return exist, nil +} + +// createEKSCluster creates a new EKS cluster if want kfctl to manage cluster +// @Deprecated. In order to simplify workflow, user should always brings their own cluster and install kubeflow on top of it. +// We still leave this option here and probably remove codes in future version +func (aws *Aws) createEKSCluster() error { + awsPluginSpec, err := aws.GetPluginSpec() + if err != nil { + return err + } + + if awsPluginSpec.GetManagedCluster() { + log.Infoln("Start to create eks cluster. Please wait for 10-15 mins...") + clusterConfigFile := filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, CLUSTER_CONFIG_FILE) + output, err := exec.Command("eksctl", "create", "cluster", "--config-file="+clusterConfigFile).Output() + if err != nil { + return &kfapis.KfError{ + Code: int(kfapis.INVALID_ARGUMENT), + Message: fmt.Sprintf("Call 'eksctl create cluster --config-file=%s' with errors: %v", clusterConfigFile, string(output)), + } + } + log.Infoln(string(output)) + + nodeGroupIamRoles, getRoleError := aws.getWorkerNodeGroupRoles(aws.kfDef.Name) + if getRoleError != nil { + return errors.WithStack(getRoleError) + } + + aws.roles = nodeGroupIamRoles + } else { + log.Infof("You already have cluster setup. Skip creating new eks cluster. ") + } + + return nil +} + +// deleteEKSCluster deletes eks cluster if current cluster is a managed cluster +func (aws *Aws) deleteEKSCluster() error { + awsPluginSpec, err := aws.GetPluginSpec() + if err != nil { + return err + } + + // Delete cluster if it's a managed cluster created by kfctl + if awsPluginSpec.GetManagedCluster() { + log.Infoln("Start to delete eks cluster. Please wait for 5 mins...") + clusterConfigFile := filepath.Join(aws.kfDef.Spec.AppDir, KUBEFLOW_AWS_INFRA_DIR, CLUSTER_CONFIG_FILE) + output, err := exec.Command("eksctl", "delete", "cluster", "--config-file="+clusterConfigFile).Output() + log.Infoln("Please go to aws console to check CloudFormation status and double make sure your cluster has been shutdown.") + if err != nil { + return &kfapis.KfError{ + Code: int(kfapis.INVALID_ARGUMENT), + Message: fmt.Sprintf("could not call 'eksctl delete cluster --config-file=%s': %v", clusterConfigFile, string(output)), + } + } + log.Infoln(string(output)) + } + + return nil +} + +// isEksctlVersionLessThan compare two version and return true if v1 is less than v2 +func isEksctlVersionLessThan(v1, v2 string) (bool, error) { + version1, err := versionChecker.NewVersion(v1) + if err != nil { + return false, err + } + + version2, err := versionChecker.NewVersion(v2) + if err != nil { + return false, err + } + + if version1.LessThan(version2) { + return true, nil + } + + return false, nil +} diff --git a/pkg/kfapp/aws/eks_test.go b/pkg/kfapp/aws/eks_test.go new file mode 100644 index 00000000..dec4f0e6 --- /dev/null +++ b/pkg/kfapp/aws/eks_test.go @@ -0,0 +1,20 @@ +package aws + +import ( + "github.com/golangplus/testing/assert" + "testing" +) + +func TestIsEksctlVersionLessThan(t *testing.T) { + v1 := "0.1.30" + result, _ := isEksctlVersionLessThan(v1, MINIMUM_EKSCTL_VERSION) + assert.True(t, "eksctl version", result) + + v1 = "0.1.32" + result, _ = isEksctlVersionLessThan(v1, MINIMUM_EKSCTL_VERSION) + assert.False(t, "eksctl version", result) + + v1 = "0.1.33" + result, _ = isEksctlVersionLessThan(v1, MINIMUM_EKSCTL_VERSION) + assert.False(t, "eksctl version", result) +} diff --git a/pkg/kfapp/aws/identity.go b/pkg/kfapp/aws/identity.go new file mode 100644 index 00000000..59cb2165 --- /dev/null +++ b/pkg/kfapp/aws/identity.go @@ -0,0 +1,336 @@ +package aws + +import ( + "crypto/sha1" + "crypto/tls" + json "encoding/json" + "fmt" + awssdk "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/iam" + kfapis "github.com/kubeflow/kfctl/v3/pkg/apis" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" + "github.com/tidwall/gjson" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clientset "k8s.io/client-go/kubernetes" + "net/http" + "net/url" + "strings" +) + +const ( + AWS_DEFAULT_AUDIENCE = "sts.amazonaws.com" + AWS_TRUST_IDENTITY_SUBJECT = "system:serviceaccount:%s:%s" + AWS_SERVICE_ACCOUNT_ANNOTATION_KEY = "eks.amazonaws.com/role-arn" + AWS_IAM_ROLE_TAG_KEY = "kubeflow/cluster-name" + AWS_IAM_ROLE_ARN = "arn:aws:iam::%s:role/%s" +) + +// checkIdentityProviderExists will return true when the iam identity provider exists, it may return errors +// if it was unable to call IAM API +func (aws *Aws) checkIdentityProviderExists(accountId, issuerURLWithoutProtocol string) (bool, string, error) { + input := &iam.GetOpenIDConnectProviderInput{ + OpenIDConnectProviderArn: awssdk.String( + fmt.Sprintf("arn:aws:iam::%s:oidc-provider/%s", accountId, issuerURLWithoutProtocol), + ), + } + _, err := aws.iamClient.GetOpenIDConnectProvider(input) + if err != nil { + awsError := err.(awserr.Error) + if awsError.Code() == iam.ErrCodeNoSuchEntityException { + return false, "", nil + } + return false, "", err + } + + return true, awssdk.StringValue(input.OpenIDConnectProviderArn), nil +} + +// createIdentityProvider create an OpenIDConnectProvider, it's one to one mapping to EKS cluster. +func (aws *Aws) createIdentityProvider(issuerUrl string) (string, error) { + issuerCAThumbprint, err := getIssueCAThumbprint(issuerUrl) + + oidcProviderInput := &iam.CreateOpenIDConnectProviderInput{ + ClientIDList: []*string{awssdk.String(AWS_DEFAULT_AUDIENCE)}, + ThumbprintList: []*string{awssdk.String(issuerCAThumbprint)}, + Url: awssdk.String(issuerUrl), + } + + output, err := aws.iamClient.CreateOpenIDConnectProvider(oidcProviderInput) + if err != nil { + return "", errors.Wrap(err, "creating OIDC identity provider") + } + + log.Infof("Creating OpenIDConnectProvider %v", *output.OpenIDConnectProviderArn) + return awssdk.StringValue(output.OpenIDConnectProviderArn), nil +} + +// DeleteIdentityProvider will delete the identity provider, it may return an error the API call fails +func (aws *Aws) DeleteIdentityProvider(providerArn string) error { + input := &iam.DeleteOpenIDConnectProviderInput{ + OpenIDConnectProviderArn: awssdk.String(providerArn), + } + if _, err := aws.iamClient.DeleteOpenIDConnectProvider(input); err != nil { + return errors.Wrap(err, "deleting oidc provider") + } + return nil +} + +// createOrUpdateWebIdentityRole creates an IAM role with trusted entity Web Identity if role doesn't exist +func (aws *Aws) createOrUpdateWebIdentityRole(oidcProviderArn, issuerUrl, roleName, serviceAccountNamespace, serviceAccountName string) error { + input := &iam.GetRoleInput{ + RoleName: awssdk.String(roleName), + } + + // Don't need to update role, return immediately. + if _, err := aws.iamClient.GetRole(input); err != nil { + // check non exist or other failures. + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case iam.ErrCodeNoSuchEntityException: + log.Infof("Role %v doesn't exist, creating for KSA %s/%s", roleName, serviceAccountNamespace, serviceAccountName) + default: + return err + } + } else { + return err + } + } else { + log.Infof("Role %v exists, skip creating role", roleName) + return nil + } + + // Create role + statement := MakeAssumeRoleWithWebIdentityPolicyDocument(oidcProviderArn, MapOfInterfaces{ + "StringEquals": map[string][]string{ + issuerUrl + ":aud": []string{AWS_DEFAULT_AUDIENCE}, + issuerUrl + ":sub": []string{fmt.Sprintf(AWS_TRUST_IDENTITY_SUBJECT, serviceAccountNamespace, serviceAccountName)}, + }, + }) + + assumeRolePolicyDocument := MakePolicyDocument(statement) + document, err := json.Marshal(assumeRolePolicyDocument) + if err != nil { + return errors.Errorf("%v can not be marshal to bytes", document) + } + + roleInput := &iam.CreateRoleInput{ + RoleName: awssdk.String(roleName), + AssumeRolePolicyDocument: awssdk.String(string(document)), + Tags: []*iam.Tag{ + { + Key: awssdk.String(AWS_IAM_ROLE_TAG_KEY), + // roleName is like kf-admin-clusterName + Value: awssdk.String(roleName[strings.LastIndex("roleName", "-")+1:]), + }, + }, + } + + _, err = aws.iamClient.CreateRole(roleInput) + if err != nil { + return err + } + return nil +} + +// createOrUpdateK8sServiceAccount creates or updates k8s service account with annotation +func (aws *Aws) createOrUpdateK8sServiceAccount(k8sClientset *clientset.Clientset, serviceAccountNamespace, serviceAccountName, iamRoleArn string) error { + existingSA, err := k8sClientset.CoreV1().ServiceAccounts(serviceAccountNamespace).Get(serviceAccountName, metav1.GetOptions{}) + if err == nil { + log.Infof("Service account %v already exists", serviceAccountName) + if existingSA.Annotations == nil { + existingSA.Annotations = map[string]string{} + } + + existingSA.Annotations[AWS_SERVICE_ACCOUNT_ANNOTATION_KEY] = iamRoleArn + _, err = k8sClientset.CoreV1().ServiceAccounts(serviceAccountNamespace).Update(existingSA) + if err != nil { + return &kfapis.KfError{ + Code: int(kfapis.INTERNAL_ERROR), + Message: err.Error(), + } + } + return nil + } + + log.Infof("Can not find existing service account, creating %s/%s", serviceAccountNamespace, serviceAccountName) + _, err = k8sClientset.CoreV1().ServiceAccounts(serviceAccountNamespace).Create( + &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceAccountName, + Namespace: serviceAccountNamespace, + Annotations: map[string]string{ + AWS_SERVICE_ACCOUNT_ANNOTATION_KEY: iamRoleArn, + }, + }, + }, + ) + if err == nil { + return nil + } else { + return &kfapis.KfError{ + Code: int(kfapis.INTERNAL_ERROR), + Message: err.Error(), + } + } +} + +// updateRoleTrustIdentity add namespace/serviceAccount to IAM Role trust entity +func (aws *Aws) updateRoleTrustIdentity(roleName, serviceAccountNamespace, serviceAccountName string) error { + roleInput := &iam.GetRoleInput{ + RoleName: awssdk.String(roleName), + } + + output, err := aws.iamClient.GetRole(roleInput) + if err != nil { + return err + } + + // Seems AssumeRolePolicyDocument is URL encoded, decode string to get string policy document + decodeValue, err := url.QueryUnescape(awssdk.StringValue(output.Role.AssumeRolePolicyDocument)) + if err != nil { + return err + } + + updatedRolePolicy, err := getUpdatedAssumeRolePolicy(decodeValue, serviceAccountNamespace, serviceAccountName) + if err != nil { + return err + } + + input := &iam.UpdateAssumeRolePolicyInput{ + RoleName: awssdk.String(roleName), + PolicyDocument: awssdk.String(updatedRolePolicy), + } + if _, err = aws.iamClient.UpdateAssumeRolePolicy(input); err != nil { + return err + } + + return nil +} + +// getUpdatedAssumeRolePolicy creates a new policy document with a new ns/sa record +func getUpdatedAssumeRolePolicy(policyDocument, serviceAccountNamespace, serviceAccountName string) (string, error) { + var oldDoc MapOfInterfaces + json.Unmarshal([]byte(policyDocument), &oldDoc) + var statements []MapOfInterfaces + statementInBytes, err := json.Marshal(oldDoc["Statement"]) + if err != nil { + return "", err + } + json.Unmarshal(statementInBytes, &statements) + + oidcRoleArn := gjson.Get(policyDocument, "Statement.0.Principal.Federated").String() + issuerUrlWithProtocol := getIssuerUrlFromRoleArn(oidcRoleArn) + + key := fmt.Sprintf("%s:sub", issuerUrlWithProtocol) + trustIdentity := fmt.Sprintf(AWS_TRUST_IDENTITY_SUBJECT, serviceAccountNamespace, serviceAccountName) + + // We assume we only operator on first statement, don't add/remove new statement + statement := statements[0] + statementInBytes, err = json.Marshal(statement) + identities := gjson.Get(string(statementInBytes), "Condition.StringEquals").Map() + + var originalIdentities []string + val, ok := identities[key] + if ok { + for _, identity := range val.Array() { + // avoid adding duplicate record + if identity.Str == trustIdentity { + return policyDocument, nil + } + originalIdentities = append(originalIdentities, identity.Str) + } + } + originalIdentities = append(originalIdentities, trustIdentity) + + document := MakeAssumeRoleWithWebIdentityPolicyDocument(oidcRoleArn, MapOfInterfaces{ + "StringEquals": map[string][]string{ + issuerUrlWithProtocol + ":aud": []string{AWS_DEFAULT_AUDIENCE}, + issuerUrlWithProtocol + ":sub": originalIdentities, + }, + }) + newAssumeRolePolicyDocument := MakePolicyDocument(document) + newPolicyDoc, err := json.Marshal(newAssumeRolePolicyDocument) + if err != nil { + return "", err + } + return string(newPolicyDoc), nil +} + +// getIssueCAThumbprint will generate CAThumbprint from a given issuerURL, this is used to create an oidc provider +func getIssueCAThumbprint(issuerURL string) (string, error) { + var issuerCAThumbprint string + + client := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + Proxy: http.ProxyFromEnvironment, + }, + } + + response, err := client.Get(issuerURL) + if err != nil { + return "", errors.Wrap(err, "connecting to issuer OIDC") + } + + if response.TLS != nil { + if numCerts := len(response.TLS.PeerCertificates); numCerts >= 1 { + root := response.TLS.PeerCertificates[numCerts-1] + issuerCAThumbprint = fmt.Sprintf("%x", sha1.Sum(root.Raw)) + return issuerCAThumbprint, nil + } + } + return "", errors.Errorf("unable to get OIDC issuer's certificate") +} + +// deleteIAMRole delete an IAM role +func (aws *Aws) deleteIAMRole(roleName string) error { + input := &iam.DeleteRoleInput{ + RoleName: awssdk.String(roleName), + } + + if _, err := aws.iamClient.DeleteRole(input); err != nil { + return err + } + + return nil +} + +// getIAMRoleNameFromIAMRoleArn converts roleArn to roleName +func getIAMRoleNameFromIAMRoleArn(arn string) string { + return arn[strings.LastIndex(arn, "/")+1:] +} + +// getIssuerUrlFromRoleArn parse issuerUrl from Arn: arn:aws:iam::${accountId}:oidc-provider/${issuerUrl} +func getIssuerUrlFromRoleArn(arn string) string { + return arn[strings.Index(arn, "/")+1:] +} + +// MakeAssumeRoleWithWebIdentityPolicyDocument constructs a trust policy statement for given web identity provider with given conditions +func MakeAssumeRoleWithWebIdentityPolicyDocument(providerARN string, condition MapOfInterfaces) MapOfInterfaces { + return MapOfInterfaces{ + "Effect": "Allow", + "Action": "sts:AssumeRoleWithWebIdentity", + "Principal": map[string]string{ + "Federated": providerARN, + }, + "Condition": condition, + } +} + +// MakePolicyDocument constructs a policy document with given statements +func MakePolicyDocument(statements ...MapOfInterfaces) MapOfInterfaces { + return MapOfInterfaces{ + "Version": "2012-10-17", + "Statement": statements, + } +} + +type ( + // MapOfInterfaces is an alias for map[string]interface{} + MapOfInterfaces = map[string]interface{} +) diff --git a/pkg/kfapp/aws/k8sClient.go b/pkg/kfapp/aws/k8sClient.go new file mode 100644 index 00000000..b5fefd1c --- /dev/null +++ b/pkg/kfapp/aws/k8sClient.go @@ -0,0 +1,95 @@ +package aws + +import ( + kfapis "github.com/kubeflow/kfctl/v3/pkg/apis" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + "os" + "path/filepath" +) + +// getK8sclient creates a Kubernetes client set +func getK8sclient() (*clientset.Clientset, error) { + home := homeDir() + kubeconfig := filepath.Join(home, ".kube", "config") + + // use the current context in kubeconfig + config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) + if err != nil { + return nil, errors.Errorf("Failed to create config file from %s", kubeconfig) + } + + clientset, err := clientset.NewForConfig(config) + if err != nil { + return nil, errors.Errorf("Failed to create kubernetes clientset") + } + + return clientset, nil +} + +// homeDir returns home folder and it's used to detect kubeconfig file +func homeDir() string { + if h := os.Getenv("HOME"); h != "" { + return h + } + return os.Getenv("USERPROFILE") // windows +} + +func createNamespace(client *clientset.Clientset, namespace string) error { + _, err := client.CoreV1().Namespaces().Get(namespace, metav1.GetOptions{}) + if err == nil { + log.Infof("Namespace %v already exists...", namespace) + return nil + } + log.Infof("Creating namespace: %v", namespace) + _, err = client.CoreV1().Namespaces().Create( + &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + }, + ) + + return err +} + +func deleteNamespace(client *clientset.Clientset, namespace string) error { + _, err := client.CoreV1().Namespaces().Get(namespace, metav1.GetOptions{}) + if err != nil { + log.Infof("Namespace %v does not exist, skip deleting", namespace) + return nil + } + log.Infof("Deleting namespace: %v", namespace) + background := metav1.DeletePropagationBackground + err = client.CoreV1().Namespaces().Delete( + namespace, &metav1.DeleteOptions{ + PropagationPolicy: &background, + }, + ) + + return err +} + +func createSecret(client *clientset.Clientset, secretName string, namespace string, data map[string][]byte) error { + secret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: namespace, + }, + Data: data, + } + log.Infof("Creating secret: %v/%v", namespace, secretName) + _, err := client.CoreV1().Secrets(namespace).Create(secret) + if err == nil { + return nil + } else { + return &kfapis.KfError{ + Code: int(kfapis.INTERNAL_ERROR), + Message: err.Error(), + } + } +} diff --git a/pkg/kfconfig/awsplugin/OWNERS b/pkg/kfconfig/awsplugin/OWNERS new file mode 100644 index 00000000..0353f4d7 --- /dev/null +++ b/pkg/kfconfig/awsplugin/OWNERS @@ -0,0 +1,2 @@ +approvers: + - jeffwan diff --git a/pkg/kfconfig/awsplugin/types.go b/pkg/kfconfig/awsplugin/types.go index 9b9db1c7..fe9d60bd 100644 --- a/pkg/kfconfig/awsplugin/types.go +++ b/pkg/kfconfig/awsplugin/types.go @@ -23,6 +23,35 @@ type AwsPluginSpec struct { Region string `json:"region,omitempty"` Roles []string `json:"roles,omitempty"` + + EnablePodIamPolicy *bool `json:"enablePodIamPolicy,omitempty"` + + EnableNodeGroupLog *bool `json:"enableNodeGroupLog,omitempty"` + + ManagedCluster *bool `json:"managedCluster,omitempty"` + + ManagedRelationDatabase *RelationDatabaseConfig `json:"managedRelationDatabase,omitempty"` + + ManagedObjectStorage *ObjectStorageConfig `json:"managedObjectStorage,omitempty"` + + // TODO: Addon is used to host some optional aws specific components + // EFS, FSX CSI Plugin, Device Plugin, etc + //AddOns []string `json:"addons,omitempty"` +} + +type RelationDatabaseConfig struct { + Host string `json:"host,omitempty"` + Port *int `json:"port,omitempty"` + Database string `json:"database,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` +} + +type ObjectStorageConfig struct { + Endpoint string `json:"endpoint,omitempty"` + Region string `json:"region,omitempty"` + Bucket string `json:"bucket,omitempty"` + PathPrefix string `json:"pathPrefix,omitempty"` } type Auth struct { @@ -56,13 +85,8 @@ type Coginito struct { // IsValid returns true if the spec is a valid and complete spec. // If false it will also return a string providing a message about why its invalid. func (plugin *AwsPluginSpec) IsValid() (bool, string) { - basicAuthSet := plugin.Auth.BasicAuth != nil - oidcAuthSet := plugin.Auth.Oidc != nil - cognitoAuthSet := plugin.Auth.Cognito != nil - - if basicAuthSet { + if plugin.Auth.BasicAuth != nil { msg := "" - isValid := true if plugin.Auth.BasicAuth.Username == "" { @@ -78,7 +102,7 @@ func (plugin *AwsPluginSpec) IsValid() (bool, string) { return isValid, msg } - if oidcAuthSet { + if plugin.Auth.Oidc != nil { msg := "" isValid := true @@ -120,7 +144,7 @@ func (plugin *AwsPluginSpec) IsValid() (bool, string) { return isValid, msg } - if cognitoAuthSet { + if plugin.Auth.Cognito != nil { msg := "" isValid := true @@ -147,8 +171,79 @@ func (plugin *AwsPluginSpec) IsValid() (bool, string) { return isValid, msg } - // return false, "Either BasicAuth, ODC or Cognito must be set" - // TODO: BasicAuth is configured to be working in AWS env. Let's add validation back once it's supported. + if plugin.ManagedRelationDatabase != nil { + msg := "" + isValid := true + + if plugin.ManagedRelationDatabase.Host == "" { + isValid = false + msg += "ManagedRelationDatabase.Host is required" + } + + if plugin.ManagedRelationDatabase.Username == "" { + isValid = false + msg += "ManagedRelationDatabase.Username is required" + } + + if plugin.ManagedRelationDatabase.Password == "" { + isValid = false + msg += "ManagedRelationDatabase.Password is required" + } + + return isValid, msg + } + + if plugin.ManagedObjectStorage != nil { + msg := "" + isValid := true + + if plugin.ManagedObjectStorage.Endpoint == "" { + isValid = false + msg += "ManagedObjectStorage.Endpoint is required" + } + + if plugin.ManagedObjectStorage.Region == "" { + isValid = false + msg += "ManagedObjectStorage.Region is required" + } + + if plugin.ManagedObjectStorage.Bucket == "" { + isValid = false + msg += "ManagedObjectStorage.Bucket is required" + } + + return isValid, msg + } + return true, "" +} + +// GetEnablePodIamPolicy return true if user want to enable pod iam policy +func (p *AwsPluginSpec) GetEnablePodIamPolicy() bool { + if p.EnablePodIamPolicy == nil { + return false + } + + v := p.EnablePodIamPolicy + return *v +} + +// GetEnableNodeGroupLog return true if user want to enable fluentd cloud watch logs +func (p *AwsPluginSpec) GetEnableNodeGroupLog() bool { + if p.EnableNodeGroupLog == nil { + return false + } + + v := p.EnableNodeGroupLog + return *v +} + +// GetManagedCluster return true if user want to create a new cluster and then deploy kubeflow +func (p *AwsPluginSpec) GetManagedCluster() bool { + if p.ManagedCluster == nil { + return false + } + v := p.ManagedCluster + return *v } diff --git a/pkg/kfconfig/awsplugin/zz_generated.deepcopy.go b/pkg/kfconfig/awsplugin/zz_generated.deepcopy.go index e7705663..8f72baf5 100644 --- a/pkg/kfconfig/awsplugin/zz_generated.deepcopy.go +++ b/pkg/kfconfig/awsplugin/zz_generated.deepcopy.go @@ -69,6 +69,31 @@ func (in *AwsPluginSpec) DeepCopyInto(out *AwsPluginSpec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.EnablePodIamPolicy != nil { + in, out := &in.EnablePodIamPolicy, &out.EnablePodIamPolicy + *out = new(bool) + **out = **in + } + if in.EnableNodeGroupLog != nil { + in, out := &in.EnableNodeGroupLog, &out.EnableNodeGroupLog + *out = new(bool) + **out = **in + } + if in.ManagedCluster != nil { + in, out := &in.ManagedCluster, &out.ManagedCluster + *out = new(bool) + **out = **in + } + if in.ManagedRelationDatabase != nil { + in, out := &in.ManagedRelationDatabase, &out.ManagedRelationDatabase + *out = new(RelationDatabaseConfig) + (*in).DeepCopyInto(*out) + } + if in.ManagedObjectStorage != nil { + in, out := &in.ManagedObjectStorage, &out.ManagedObjectStorage + *out = new(ObjectStorageConfig) + **out = **in + } return } @@ -161,3 +186,40 @@ func (in *OIDC) DeepCopy() *OIDC { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectStorageConfig) DeepCopyInto(out *ObjectStorageConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStorageConfig. +func (in *ObjectStorageConfig) DeepCopy() *ObjectStorageConfig { + if in == nil { + return nil + } + out := new(ObjectStorageConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RelationDatabaseConfig) DeepCopyInto(out *RelationDatabaseConfig) { + *out = *in + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RelationDatabaseConfig. +func (in *RelationDatabaseConfig) DeepCopy() *RelationDatabaseConfig { + if in == nil { + return nil + } + out := new(RelationDatabaseConfig) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/kfconfig/types.go b/pkg/kfconfig/types.go index 3a3c5779..2c5648e2 100644 --- a/pkg/kfconfig/types.go +++ b/pkg/kfconfig/types.go @@ -684,6 +684,89 @@ func (c *KfConfig) SetApplicationParameter(appName string, paramName string, val return nil } +func (c *KfConfig) DeleteApplication(appName string) error { + // First we check applications for an application with the specified name. + if c.Spec.Applications != nil { + appIndex := -1 + for i, a := range c.Spec.Applications { + if a.Name == appName { + appIndex = i + } + } + + if appIndex >= 0 { + c.Spec.Applications = append(c.Spec.Applications[:appIndex], c.Spec.Applications[appIndex+1:]...) + return nil + } + + } + log.Warnf("Application %v not found", appName) + return nil +} + +func (c *KfConfig) AddApplicationOverlay(appName, overlayName string) error { + // First we check applications for an application with the specified name. + if c.Spec.Applications != nil { + appIndex := -1 + for i, a := range c.Spec.Applications { + if a.Name == appName { + appIndex = i + } + } + + if appIndex >= 0 { + overlayIndex := -1 + for i, o := range c.Spec.Applications[appIndex].KustomizeConfig.Overlays { + if o == overlayName { + overlayIndex = i + } + } + + if overlayIndex >= 0 { + log.Warnf("Found existing overlay %v in Application %v, skip adding", appName, overlayName) + } else { + c.Spec.Applications[appIndex].KustomizeConfig.Overlays = append(c.Spec.Applications[appIndex].KustomizeConfig.Overlays, overlayName) + } + } else { + log.Warnf("Application %v not found, overlay %v cannot be added", appName, overlayName) + } + } + + return nil +} + +func (c *KfConfig) RemoveApplicationOverlay(appName, overlayName string) error { + // First we check applications for an application with the specified name. + if c.Spec.Applications != nil { + appIndex := -1 + for i, a := range c.Spec.Applications { + if a.Name == appName { + appIndex = i + } + } + + if appIndex >= 0 { + overlayIndex := -1 + for i, o := range c.Spec.Applications[appIndex].KustomizeConfig.Overlays { + if o == overlayName { + overlayIndex = i + } + } + + if overlayIndex >= 0 { + c.Spec.Applications[appIndex].KustomizeConfig.Overlays = append(c.Spec.Applications[appIndex].KustomizeConfig.Overlays[:overlayIndex], + c.Spec.Applications[appIndex].KustomizeConfig.Overlays[overlayIndex+1:]...) + } else { + log.Warnf("Cannot find overlay %v in Application %v, skip removing", appName, overlayName) + } + } else { + log.Warnf("Application %v not found, overlay %v cannot be deleted", appName, overlayName) + } + } + + return nil +} + // SetSecret sets the specified secret; if a secret with the given name already exists it is overwritten. func (c *KfConfig) SetSecret(newSecret Secret) { for i, s := range c.Spec.Secrets { diff --git a/pkg/kfconfig/types_test.go b/pkg/kfconfig/types_test.go index 3f200d35..e562872d 100644 --- a/pkg/kfconfig/types_test.go +++ b/pkg/kfconfig/types_test.go @@ -574,6 +574,399 @@ func TestKfConfig_GetApplicationParameter(t *testing.T) { } } +func TestKfConfig_DeleteApplication(t *testing.T) { + type testCase struct { + Input *KfConfig + AppNameToDelete string + Expected *KfConfig + } + + cases := []testCase{ + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{}, + }, + { + Name: "app2", + KustomizeConfig: &KustomizeConfig{}, + }, + }, + }, + }, + AppNameToDelete: "app1", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app2", + KustomizeConfig: &KustomizeConfig{}, + }, + }, + }, + }, + }, + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Parameters: []NameValue{ + { + Name: "p1", + Value: "old1", + }, + }, + }, + }, + }, + }, + }, + AppNameToDelete: "app1", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{}, + }, + }, + }, + } + + for _, c := range cases { + c.Input.DeleteApplication(c.AppNameToDelete) + if !reflect.DeepEqual(c.Input, c.Expected) { + pGot, _ := Pformat(c.Input) + pWant, _ := Pformat(c.Expected) + t.Errorf("Error setting App %v; got;\n%v\nwant;\n%v", c.AppNameToDelete, pGot, pWant) + } + } +} + +func TestKfConfig_AddApplicationOverlay(t *testing.T) { + type testCase struct { + Input *KfConfig + AppName string + OverlayToAdd string + Expected *KfConfig + } + + cases := []testCase{ + // overlay already exist + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay2", + "overlay3", + }, + }, + }, + }, + }, + }, + AppName: "app1", + OverlayToAdd: "overlay1", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay2", + "overlay3", + }, + }, + }, + }, + }, + }, + }, + // app not found + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + }, + }, + }, + }, + }, + }, + AppName: "app2", + OverlayToAdd: "overlay1", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + }, + }, + }, + }, + }, + }, + }, + // normal + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + }, + }, + }, + }, + }, + }, + AppName: "app1", + OverlayToAdd: "overlay2", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay2", + }, + }, + }, + }, + }, + }, + }, + } + + for _, c := range cases { + c.Input.AddApplicationOverlay(c.AppName, c.OverlayToAdd) + if !reflect.DeepEqual(c.Input, c.Expected) { + pGot, _ := Pformat(c.Input) + pWant, _ := Pformat(c.Expected) + t.Errorf("Error setting App %v; got;\n%v\nwant;\n%v", c.OverlayToAdd, pGot, pWant) + } + } +} + +func TestKfConfig_RemoveApplicationOverlay(t *testing.T) { + type testCase struct { + Input *KfConfig + AppName string + OverlayToRemove string + Expected *KfConfig + } + + cases := []testCase{ + // Normal case - remove overlay on boarder + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay2", + "overlay3", + }, + }, + }, + }, + }, + }, + AppName: "app1", + OverlayToRemove: "overlay1", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay2", + "overlay3", + }, + }, + }, + }, + }, + }, + }, + // Normal case - remove overlay in the middle + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay2", + "overlay3", + }, + }, + }, + }, + }, + }, + AppName: "app1", + OverlayToRemove: "overlay2", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay3", + }, + }, + }, + }, + }, + }, + }, + // Can not find app -> remain same + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay2", + "overlay3", + }, + }, + }, + }, + }, + }, + AppName: "app2", + OverlayToRemove: "overlay2", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay2", + "overlay3", + }, + }, + }, + }, + }, + }, + }, + // Can not find overlay -> remain same + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay2", + "overlay3", + }, + }, + }, + }, + }, + }, + AppName: "app1", + OverlayToRemove: "overlay4", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{ + "overlay1", + "overlay2", + "overlay3", + }, + }, + }, + }, + }, + }, + }, + // no overlay -> remain same + { + Input: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{}, + }, + }, + }, + }, + }, + AppName: "app1", + OverlayToRemove: "overlay1", + Expected: &KfConfig{ + Spec: KfConfigSpec{ + Applications: []Application{ + { + Name: "app1", + KustomizeConfig: &KustomizeConfig{ + Overlays: []string{}, + }, + }, + }, + }, + }, + }, + } + + for _, c := range cases { + c.Input.RemoveApplicationOverlay(c.AppName, c.OverlayToRemove) + if !reflect.DeepEqual(c.Input, c.Expected) { + pGot, _ := Pformat(c.Input) + pWant, _ := Pformat(c.Expected) + t.Errorf("Error setting App %v; overlay %v; got;\n%v\nwant;\n%v", c.AppName, c.OverlayToRemove, pGot, pWant) + } + } +} + // Pformat returns a pretty format output of any value. func Pformat(value interface{}) (string, error) { if s, ok := value.(string); ok { diff --git a/pkg/utils/awsutil.go b/pkg/utils/awsutil.go index 0495bef4..4c214244 100644 --- a/pkg/utils/awsutil.go +++ b/pkg/utils/awsutil.go @@ -17,14 +17,17 @@ limitations under the License. package utils import ( + "fmt" + awssdk "github.com/aws/aws-sdk-go/aws" "os/exec" + "regexp" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/sts" log "github.com/sirupsen/logrus" ) -// CheckAwsStsCallerIdentity runs GetCallIdentity to make sure aws credentials is configured correclty +// CheckAwsStsCallerIdentity runs GetCallIdentity to make sure aws credentials is configured correctly func CheckAwsStsCallerIdentity(sess *session.Session) error { svc := sts.New(sess) input := &sts.GetCallerIdentityInput{} @@ -39,6 +42,20 @@ func CheckAwsStsCallerIdentity(sess *session.Session) error { return nil } +// CheckAwsAccountId runs GetCallIdentity to retrieve account information +func CheckAwsAccountId(sess *session.Session) (string, error) { + svc := sts.New(sess) + input := &sts.GetCallerIdentityInput{} + + output, err := svc.GetCallerIdentity(input) + if err != nil { + log.Warnf("AWS Credentials seems not correct %v", err.Error()) + return "", err + } + + return awssdk.StringValue(output.Account), nil +} + // CheckCommandExist check if a command can be found in PATH. func CheckCommandExist(commandName string) error { _, err := exec.LookPath(commandName) @@ -49,18 +66,25 @@ func CheckCommandExist(commandName string) error { return nil } -// GetEksctlVersion return eksctl version on user's machine -func GetEksctlVersion() error { +// GetEksctlVersion return eksctl version on user's environment +func GetEksctlVersion() (string, error) { log.Infof("Running `eksctl version` ...") output, err := exec.Command("eksctl", "version").Output() if err != nil { log.Errorf("Failed to run `eksctl version` command %v", err) - return err + return "", err } - log.Infof("output: %v", string(output)) // [ℹ] version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.1.32"} - // We'd like to extract 0.1.32 and compare with minimum version we support. - return nil + r := regexp.MustCompile("[0-9]+.[0-9]+.[0-9]+") + matchGroups := r.FindStringSubmatch(string(output)) + + if len(matchGroups) == 0 { + return "", fmt.Errorf("can not find eksctl version from %v", string(output)) + } + + version := matchGroups[0] + log.Infof("eksctl version: %s", version) + return version, nil }