From 3b9eb17783b9a4a0daa605990563e798e0db1b43 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Wed, 18 Nov 2020 18:14:22 +0200 Subject: [PATCH 01/16] Integrate kommons --- controllers/template_controller.go | 8 +- go.mod | 30 +- go.sum | 261 +++-- k8s/builder.go | 474 -------- k8s/client.go | 1675 ---------------------------- k8s/kustomize/json6902.go | 61 - k8s/kustomize/kustomize.go | 284 ----- k8s/kustomize/strategicmerge.go | 136 --- k8s/template_manager.go | 14 +- k8s/types.go | 29 - k8s/utils.go | 340 ------ k8s/walk.go | 64 -- main.go | 4 +- 13 files changed, 153 insertions(+), 3227 deletions(-) delete mode 100644 k8s/builder.go delete mode 100644 k8s/client.go delete mode 100644 k8s/kustomize/json6902.go delete mode 100644 k8s/kustomize/kustomize.go delete mode 100644 k8s/kustomize/strategicmerge.go delete mode 100644 k8s/types.go delete mode 100644 k8s/utils.go delete mode 100644 k8s/walk.go diff --git a/controllers/template_controller.go b/controllers/template_controller.go index d6ec975..1df20db 100644 --- a/controllers/template_controller.go +++ b/controllers/template_controller.go @@ -19,21 +19,21 @@ package controllers import ( "context" + "github.com/flanksource/kommons" + templatev1 "github.com/flanksource/template-operator/api/v1" + "github.com/flanksource/template-operator/k8s" "github.com/go-logr/logr" kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - - templatev1 "github.com/flanksource/template-operator/api/v1" - "github.com/flanksource/template-operator/k8s" ) // TemplateReconciler reconciles a Template object type TemplateReconciler struct { ControllerClient client.Client - Client *k8s.Client + Client *kommons.Client Log logr.Logger Scheme *runtime.Scheme } diff --git a/go.mod b/go.mod index 008e783..2c9f083 100644 --- a/go.mod +++ b/go.mod @@ -3,29 +3,29 @@ module github.com/flanksource/template-operator go 1.13 require ( - 9fans.net/go v0.0.2 // indirect - github.com/AlekSi/pointer v1.1.0 - github.com/flanksource/commons v1.4.0 - github.com/ghodss/yaml v1.0.0 - github.com/go-logr/logr v0.2.1 - github.com/go-logr/zapr v0.2.0 - github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 + github.com/flanksource/commons v1.4.3 + github.com/flanksource/kommons v0.1.5 + github.com/go-logr/logr v0.3.0 + github.com/go-logr/zapr v0.3.0 // indirect github.com/hairyhenderson/gomplate/v3 v3.6.0 - github.com/mitchellh/mapstructure v1.1.2 github.com/onsi/ginkgo v1.12.1 github.com/onsi/gomega v1.10.1 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.4.2 github.com/tidwall/gjson v1.6.1 + golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5 // indirect gopkg.in/flanksource/yaml.v3 v3.1.1 - k8s.io/api v0.19.1 - k8s.io/apimachinery v0.19.1 - k8s.io/cli-runtime v0.19.1 - k8s.io/client-go v11.0.0+incompatible + k8s.io/api v0.19.4 + k8s.io/apimachinery v0.19.4 + k8s.io/cli-runtime v0.19.3 + k8s.io/client-go v12.0.0+incompatible sigs.k8s.io/controller-runtime v0.6.3 - sigs.k8s.io/controller-tools v0.4.0 // indirect sigs.k8s.io/kustomize v2.0.3+incompatible sigs.k8s.io/yaml v1.2.0 ) -replace k8s.io/client-go => k8s.io/client-go v0.19.1 +replace ( + github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.0.0+incompatible + google.golang.org/genproto => google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb + google.golang.org/grpc => google.golang.org/grpc v1.26.0 + k8s.io/client-go => k8s.io/client-go v0.19.4 +) diff --git a/go.sum b/go.sum index 187aa58..eba77c5 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,4 @@ -9fans.net/go v0.0.2 h1:RYM6lWITV8oADrwLfdzxmt8ucfW6UtP9v1jg4qAbqts= -9fans.net/go v0.0.2/go.mod h1:lfPdxjq9v8pVQXUMBCx5EO5oLXWQFlKRQgs1kEkjoIM= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -12,8 +10,11 @@ cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTj cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.51.0 h1:PvKAVQWCtlGUSlZkGW3QLelKaWq7KYv/MW1EboG8bfM= cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= +cloud.google.com/go/bigquery v1.0.1 h1:hL+ycaJpVE9M7nLoiXb/Pn10ENE2u+oddxbD8uu0ZVU= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0 h1:Kt+gOPPp2LEPWp8CSfxhsM8ik9CcyE/gYu+0r+RnZvM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1 h1:W9tAK3E57P75u0XLLR82LZyw8VpAnhmyTOxW9qzmyj8= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0 h1:VV2nUM3wwLLGh9lSABFgZMjInyUbJeaRSE64WuAIQ+4= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= @@ -22,7 +23,12 @@ contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrL contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= +dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= @@ -34,21 +40,28 @@ github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbI github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFEY95rZLK0Tj6o= github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-autorest v12.0.0+incompatible h1:N+VqClcomLGD/sHb3smbSYYtNMgKpVV3Cd5r5i8z6bQ= -github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v13.0.0+incompatible h1:56c11ykhsFSPNNQuS73Ri8h/ezqVhr2h6t9LJIEKVO0= +github.com/Azure/go-autorest v13.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.6 h1:5YWtOnckcudzIw8lPPBcWOnmIFWMtHci1ZWAZulMSx0= github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest/adal v0.5.0 h1:q2gDruN08/guU9vAjuPWff0+QIrpH6ediguzdAzXAUU= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= github.com/Azure/go-autorest/autorest/adal v0.8.2/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/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.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.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/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= @@ -64,9 +77,6 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= -github.com/RaveNoX/go-jsonmerge v1.0.0 h1:2e0nqnadoGUP8rAvcA0hkQelZreVO5X3BHomT2XMrAk= -github.com/RaveNoX/go-jsonmerge v1.0.0/go.mod h1:qYM/NA77LhO4h51JJM7Z+xBU3ovqrNIACZe+SkSNVFo= github.com/Shopify/ejson v1.2.1 h1:Dx0Ipn0mUgrZlzIa5oIUrH0rdSmBOyod/UJmQQK1KHo= github.com/Shopify/ejson v1.2.1/go.mod h1:J8cw5GOA0l/aMOPp+uDfwNYVbeqIaBhzRkv1+76UCvk= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= @@ -106,9 +116,10 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1U github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/brancz/gojsontoyaml v0.0.0-20191212081931-bf2969bbd742/go.mod h1:IyUJYN1gvWjtLF5ZuygmxbnsAyP3aJS6cHzIuZY50B0= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -118,27 +129,31 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= +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/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= @@ -151,10 +166,11 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QL github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKBAG3Klr9cn7N+LcYc82AZ2S7+cA= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad/go.mod h1:mPKfmRa823oBIgl2r20LeMSpTAteW5j7FLkc0vjmzyQ= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= @@ -173,8 +189,10 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/flanksource/commons v1.4.0 h1:l6PqQ4+a4+A/79NsX8Tv2+zbLoZLowKBi2rRqtARwd4= -github.com/flanksource/commons v1.4.0/go.mod h1:cGrz4qFi4NrP04vjMxv6DQk0SD0u6nnYppKpgFShj0c= +github.com/flanksource/commons v1.4.3 h1:arEom5vkh5RrEWNy+kj32PmCbZ8d3OdZ0K7X7wQAi9k= +github.com/flanksource/commons v1.4.3/go.mod h1:cGrz4qFi4NrP04vjMxv6DQk0SD0u6nnYppKpgFShj0c= +github.com/flanksource/kommons v0.1.5 h1:1o8PyBNngemau4Q14NOkvXVqddqheOtDDELoVcRQtoc= +github.com/flanksource/kommons v0.1.5/go.mod h1:Dc/oeDDXgybBm1LFr1iSAgARLCja8ep9K42Qouu+yPM= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= @@ -189,6 +207,7 @@ github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXt github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= @@ -203,14 +222,14 @@ github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.2.1-0.20200730175230-ee2de8da5be6 h1:ZPVluSmhtMIHlqUDMZu70FgMpRzbQfl4h9oKCAXOVDE= -github.com/go-logr/logr v0.2.1-0.20200730175230-ee2de8da5be6/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.2.1 h1:fV3MLmabKIZ383XifUjFSwcoGee0v9qgPp8wy5svibE= github.com/go-logr/logr v0.2.1/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs= +github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= -github.com/go-logr/zapr v0.2.0 h1:v6Ji8yBW77pva6NkJKQdHLAJKrIJKRHz0RXwPqCHSR4= -github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= +github.com/go-logr/zapr v0.3.0 h1:iyiCRZ29uPmbO7mWIjOEiYMXrTxZWTyK4tCatLyGpUY= +github.com/go-logr/zapr v0.3.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= 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.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -263,19 +282,15 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 h1:28FVBuwkwowZMjbA7M0wXsI6t3PYulRTMio3SO+eKCM= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/gobuffalo/flect v0.2.0 h1:EWCvMGGxOjsgwlWaP+f4+Hh6yrrte7JeFL2S6b+0hdM= -github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= +github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7 h1:u4bArs140e9+AfE52mFHOXVFnOSBJBRlzTHrOPLOIhE= -github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -310,11 +325,12 @@ 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-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-replayers/grpcreplay v0.1.0 h1:eNb1y9rZFmY4ax45uEEECSa8fsxGRU+8Bil52ASAwic= github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= github.com/google/go-replayers/httpreplay v0.1.0 h1:AX7FUb4BjrrzNvblr/OlgwrmFiep6soj5K2QSDW7BGk= github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= -github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= @@ -333,6 +349,7 @@ github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.3.0 h1:imGQZGEVEHpje5056+K+cgdO72p0LQv2xIIFXNGUf60= github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= 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 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc= @@ -345,22 +362,25 @@ github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJ github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= -github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gosimple/slug v1.9.0 h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs= github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4vDJbg= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.5.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.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hairyhenderson/gomplate/v3 v3.6.0 h1:EryWG7cCxvZ2awoZ957B3AMAd20Zy0uRXeZ7TXXMIp0= github.com/hairyhenderson/gomplate/v3 v3.6.0/go.mod h1:RbEC6Y14nNTHCtNWpBAkwqDP4ICFUrAH0S8PUFa0qT4= @@ -439,14 +459,13 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= 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= @@ -455,8 +474,8 @@ github.com/johannesboyne/gofakes3 v0.0.0-20191029185751-e238f04965fe h1:9kkgzfTj github.com/johannesboyne/gofakes3 v0.0.0-20191029185751-e238f04965fe/go.mod h1:cPDudDcSR9fls3ZmrXgt0GU2QpQGQRJc4JBNtKyNr1s= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= @@ -464,10 +483,10 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= @@ -481,6 +500,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -514,6 +534,7 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 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/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -530,11 +551,12 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -542,6 +564,8 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= @@ -549,7 +573,6 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= @@ -557,11 +580,10 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34= -github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -578,11 +600,11 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.8.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/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -594,11 +616,13 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-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.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/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= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -609,7 +633,6 @@ github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ= github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q= -github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -626,17 +649,45 @@ github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shabbyrobe/gocovmerge v0.0.0-20180507124511-f6ea450bfb63 h1:J6qvD6rbmOil46orKqJaRPG+zTpoGlBTUdyv8ki63L0= github.com/shabbyrobe/gocovmerge v0.0.0-20180507124511-f6ea450bfb63/go.mod h1:n+VKSARF5y/tS9XFSP7vWDfS+GUC5vs/YT7M5XDTUEM= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.0/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -656,17 +707,16 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws= github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= @@ -675,6 +725,7 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= github.com/tidwall/pretty v1.0.2/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 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -691,18 +742,22 @@ github.com/vbauerster/mpb/v5 v5.0.3/go.mod h1:h3YxU5CSr8rZP4Q3xZPVB3jJLhWPou63lH github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zealic/xignore v0.3.3 h1:EpLXUgZY/JEzFkTc+Y/VYypzXtNz+MSOMVCGW5Q4CKQ= github.com/zealic/xignore v0.3.3/go.mod h1:lhS8V7fuSOtJOKsvKI7WfsZE276/7AYEqokv3UiqEAU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -718,18 +773,21 @@ go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= gocloud.dev v0.18.0 h1:HX6uFZYZs9tUP87jzoWgB8dl4ihsRpiAsBDKTthiApY= gocloud.dev v0.18.0/go.mod h1:lhLOb91+9tKB8RnNlsx+weJGEd0AHM94huK1bmrhPwM= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -738,8 +796,6 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -751,21 +807,19 @@ golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-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-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299 h1:zQpM52jfKHG6II1ISZY1ZcpygvuSFZpLwfluuF89XOg= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 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-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/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= @@ -780,6 +834,7 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -811,12 +866,14 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -826,15 +883,14 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4 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-20180823144017-11551d06cbcc/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= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -888,10 +944,9 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190308174544-00c44ba9c14f/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -901,7 +956,6 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-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-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -928,9 +982,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.6.0 h1:2tJEkRfnZL5g1GeBUlITh/rqT5HG3sFcoVCUUxmgJ2g= @@ -940,7 +993,7 @@ google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.15.0 h1:yzlyyDW/J0w8yNFJIhiAJy4kq74S+1DOLdawELNxFMA= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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= @@ -948,34 +1001,10 @@ google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3 google.golang.org/appengine v1.6.1/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-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/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -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-20191230161307-f3c370f40bfb h1:ADPHZzpzM4tk4V4S5cnCrr5SwzvlrPRmqqCuJDB8UTs= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -983,7 +1012,6 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1021,6 +1049,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= @@ -1029,58 +1058,38 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966 h1:B0J02caTR6tpSJozBJyiAzT6CtBzjclw4pgm9gg8Ys0= -gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20190924164351-c8b7dadae555 h1:4Yrwvx9yMvZx+vK3wdX7aX2UCNZJJn0TDc+BNOJTE00= gopkg.in/yaml.v3 v3.0.0-20190924164351-c8b7dadae555/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.0 h1:d+tVGRu6X0ZBQ+kyAR8JKi6AXhTP2gmQaoIYaGFz634= gotest.tools/v3 v3.0.0/go.mod h1:TUP+/YtXl/dp++T+SZ5v2zUmLVBHmptSb/ajDLCJ+3c= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-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.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -k8s.io/api v0.17.2 h1:NF1UFXcKN7/OOv1uxdRz3qfra8AHsPav5M93hlV9+Dc= -k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4= -k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= -k8s.io/api v0.18.3 h1:2AJaUQdgUZLoDZHrun21PW2Nx9+ll6cUzvn3IKhSIn0= -k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA= k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= -k8s.io/api v0.19.1 h1:oZf4bYsBdjC49PdTwNfLmrfUFCwKUi94HY/+emXI8Qw= -k8s.io/api v0.19.1/go.mod h1:+u/k4/K/7vp4vsfdT7dyl8Oxk1F26Md4g5F26Tu85PU= -k8s.io/apiextensions-apiserver v0.17.2 h1:cP579D2hSZNuO/rZj9XFRzwJNYb41DbNANJb6Kolpss= -k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs= -k8s.io/apiextensions-apiserver v0.18.2 h1:I4v3/jAuQC+89L3Z7dDgAiN4EOjN6sbm6iBqQwHTah8= -k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= +k8s.io/api v0.19.3 h1:GN6ntFnv44Vptj/b+OnMW7FmzkpDoIDLZRvKX3XH9aU= +k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= +k8s.io/api v0.19.4 h1:I+1I4cgJYuCDgiLNjKx7SLmIbwgj9w7N7Zr5vSIdwpo= +k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk= k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrqOzaMo= k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M= -k8s.io/apimachinery v0.17.2 h1:hwDQQFbdRlpnnsR64Asdi55GyCaIP/3WQpMmbNBeWr4= -k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= -k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= -k8s.io/apimachinery v0.18.3 h1:pOGcbVAhxADgUYnjS08EFXs9QMl8qaH5U4fr5LGUrSk= -k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= -k8s.io/apimachinery v0.19.1 h1:cwsxZazM/LA9aUsBaL4bRS5ygoM6bYp8dFk22DSYQa4= -k8s.io/apimachinery v0.19.1/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo= -k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= +k8s.io/apimachinery v0.19.3 h1:bpIQXlKjB4cB/oNpnNnV+BybGPR7iP5oYpsOTEJ4hgc= +k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apimachinery v0.19.4 h1:+ZoddM7nbzrDCp0T3SWnyxqf8cbWPT2fkZImoyvHUG0= +k8s.io/apimachinery v0.19.4/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg= -k8s.io/cli-runtime v0.19.1 h1:OXC7ssdUQZ6LnHGWD16cMXECr8gKMrO5EPe3zhm211Q= -k8s.io/cli-runtime v0.19.1/go.mod h1:X6g8e4NBiG8GMsKewXsRpo36MO6xrvXa+0wCg7zO4aU= -k8s.io/client-go v0.18.3 h1:QaJzz92tsN67oorwzmoB0a9r9ZVHuD5ryjbCKP0U22k= -k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw= -k8s.io/client-go v0.19.1 h1:xfFwj+YFKa8rcihlFYZABjxcy7Sm/wJQ+GxW3JyVtKI= -k8s.io/client-go v0.19.1/go.mod h1:AZOIVSI9UUtQPeJD3zJFp15CEhSjRgAuQP5PWRJrCIQ= -k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= -k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= +k8s.io/cli-runtime v0.19.3 h1:vZUTphJIvlh7+867cXiLmyzoCAuQdukbPLIad6eEajQ= +k8s.io/cli-runtime v0.19.3/go.mod h1:q+l845i5/uWzcUpCrl+L4f3XLaJi8ZeLVQ/decwty0A= +k8s.io/client-go v0.19.4 h1:85D3mDNoLF+xqpyE9Dh/OtrJDyJrSRKkHmDXIbEzer8= +k8s.io/client-go v0.19.4/go.mod h1:ZrEy7+wj9PjH5VMBCuu/BDlvtUAku0oVFk4MmnW9mWA= k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= -k8s.io/component-base v0.17.2/go.mod h1:zMPW3g5aH7cHJpKYQ/ZsGMcgbsA/VyhEugF3QT1awLs= -k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= @@ -1090,42 +1099,22 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -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-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kubernetes v1.19.1 h1:3Gdl9EtBiV3SYuzml1915nFLVxlx08L6bRz1b07C60k= -k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo= -k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -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.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= -sigs.k8s.io/controller-runtime v0.5.0 h1:CbqIy5fbUX+4E9bpnBFd204YAzRYlM9SWW77BbrcDQo= -sigs.k8s.io/controller-runtime v0.5.0/go.mod h1:REiJzC7Y00U+2YkMbT8wxgrsX5USpXKGhb2sCtAXiT8= -sigs.k8s.io/controller-runtime v0.6.0 h1:Fzna3DY7c4BIP6KwfSlrfnj20DJ+SeMBK8HSFvOk9NM= -sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo= sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE= sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= -sigs.k8s.io/controller-tools v0.4.0 h1:9zIdrc6q9RKke8+DnVPVBVZ+cfF9L0TwM01cxNnklYo= -sigs.k8s.io/controller-tools v0.4.0/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= -sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU= -sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= @@ -1135,3 +1124,5 @@ sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/k8s/builder.go b/k8s/builder.go deleted file mode 100644 index 69bc99c..0000000 --- a/k8s/builder.go +++ /dev/null @@ -1,474 +0,0 @@ -package k8s - -import ( - apps "k8s.io/api/apps/v1" - batchv1 "k8s.io/api/batch/v1" - batchv1beta1 "k8s.io/api/batch/v1beta1" - v1 "k8s.io/api/core/v1" - rbac "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/intstr" -) - -type Builder struct { - Objects []runtime.Object - Namespace string - Labels map[string]string - Annotations map[string]string -} - -func (b *Builder) ObjectMeta(name string) metav1.ObjectMeta { - return metav1.ObjectMeta{ - Name: name, - Namespace: b.Namespace, - Labels: b.Labels, - Annotations: b.Annotations, - } -} - -func (b *Builder) Append(objects ...runtime.Object) *Builder { - Objects := b.Objects - Objects = append(Objects, objects...) - b.Objects = Objects - return b -} - -func (b *Builder) AddLabels(labels map[string]string) *Builder { - b.Labels = labels - return b -} - -func (b *Builder) AddAnnotations(annotations map[string]string) *Builder { - b.Annotations = annotations - return b -} - -func (b *Builder) SetNamespace(namespace string) *Builder { - b.Namespace = namespace - return b -} - -func (b *Builder) ConfigMap(name string, data map[string]string) *Builder { - b.Append(&v1.ConfigMap{ - TypeMeta: metav1.TypeMeta{Kind: "ConfigMap", APIVersion: "v1"}, - - ObjectMeta: b.ObjectMeta(name), - Data: data, - }) - return b -} - -func (b *Builder) Secret(name string, data map[string][]byte) *Builder { - b.Append(&v1.Secret{ - TypeMeta: metav1.TypeMeta{Kind: "Secret", APIVersion: "v1"}, - ObjectMeta: b.ObjectMeta(name), - Type: "opaque", - Data: data, - }) - return b -} - -func (b *Builder) Deployment(name, image string) *DeploymentBuilder { - return &DeploymentBuilder{ - Builder: b, - Name: name, - Image: image, - replicas: 1, - resources: LowResourceRequirements(), - labels: b.Labels, - annotations: b.Annotations, - } -} - -func Deployment(name, image string) *DeploymentBuilder { - return &DeploymentBuilder{ - Builder: &Builder{}, - Name: name, - Image: image, - replicas: 1, - labels: make(map[string]string), - annotations: make(map[string]string), - resources: LowResourceRequirements(), - } -} - -type DeploymentBuilder struct { - Builder *Builder - Name, Image, sa string - replicas int32 - args []string - resources v1.ResourceRequirements - volumeMounts []v1.VolumeMount - ports []v1.ContainerPort - volumes []v1.Volume - labels map[string]string - annotations map[string]string - env []v1.EnvVar - nodeAffinity *v1.Affinity - podAffinity *v1.Affinity - cmd []string -} - -func (d *DeploymentBuilder) Command(cmd ...string) *DeploymentBuilder { - d.cmd = append(d.cmd, cmd...) - return d -} - -func (d *DeploymentBuilder) EnvVarFromField(env, field string) *DeploymentBuilder { - d.env = append(d.env, v1.EnvVar{ - Name: env, - ValueFrom: &v1.EnvVarSource{ - FieldRef: &v1.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: field, - }, - }, - }) - return d -} - -func (d *DeploymentBuilder) EnvVarFromSecret(env, secret, key string) *DeploymentBuilder { - d.env = append(d.env, v1.EnvVar{ - Name: env, - ValueFrom: &v1.EnvVarSource{ - SecretKeyRef: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: secret, - }, - Key: key, - }, - }, - }) - return d -} - -func (d *DeploymentBuilder) EnvVarFromConfigMap(env, configmap, key string) *DeploymentBuilder { - d.env = append(d.env, v1.EnvVar{ - Name: env, - ValueFrom: &v1.EnvVarSource{ - ConfigMapKeyRef: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: configmap, - }, - Key: key, - }, - }, - }) - return d -} - -func (d *DeploymentBuilder) AsCronJob(schedule string) *batchv1beta1.CronJob { - pod := d.PodTemplate() - pod.Spec.RestartPolicy = v1.RestartPolicyNever - return &batchv1beta1.CronJob{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "batch/v1beta1", - Kind: "CronJob", - }, - ObjectMeta: d.Builder.ObjectMeta(d.Name), - Spec: batchv1beta1.CronJobSpec{ - Schedule: schedule, - JobTemplate: batchv1beta1.JobTemplateSpec{ - Spec: batchv1.JobSpec{ - Template: pod, - }, - }, - ConcurrencyPolicy: batchv1beta1.ForbidConcurrent, - }, - } -} - -func (d *DeploymentBuilder) PodSpec() v1.PodSpec { - return v1.PodSpec{ - ServiceAccountName: d.sa, - Volumes: d.volumes, - Containers: []v1.Container{ - { - Command: d.cmd, - Name: d.Name, - Image: d.Image, - ImagePullPolicy: v1.PullIfNotPresent, - Ports: d.ports, - VolumeMounts: d.volumeMounts, - Env: d.env, - Args: d.args, - Resources: d.resources, - }, - }, - } -} - -func (d *DeploymentBuilder) ObjectMeta() metav1.ObjectMeta { - return d.Builder.ObjectMeta(d.Name) -} - -func (d *DeploymentBuilder) PodTemplate() v1.PodTemplateSpec { - return v1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: d.GetLabels(), - }, - Spec: d.PodSpec(), - } -} - -func (d *DeploymentBuilder) AsOneShotJob() *v1.Pod { - pod := v1.Pod{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Pod", - }, - ObjectMeta: d.ObjectMeta(), - Spec: d.PodSpec(), - } - pod.Spec.RestartPolicy = "Never" - return &pod -} - -func (d *DeploymentBuilder) EnvVars(env map[string]string) *DeploymentBuilder { - for k, v := range env { - d.env = append(d.env, v1.EnvVar{ - Name: k, - Value: v, - }) - } - return d -} - -func (d *DeploymentBuilder) NodeAffinity(nodeReadinessLabel map[string]string) *DeploymentBuilder { - matchExpressions := make([]v1.NodeSelectorRequirement, 0) - if len(nodeReadinessLabel) == 0 { - return nil - } - for k, v := range nodeReadinessLabel { - matchExpressions = append(matchExpressions, v1.NodeSelectorRequirement{ - Key: k, - Operator: v1.NodeSelectorOpIn, - Values: []string{v}, - }) - } - - d.nodeAffinity = &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{{MatchExpressions: matchExpressions}}, - }, - }, - } - return d -} - -func (d *DeploymentBuilder) PodAffinity(labels map[string]string, topologyKey string) *DeploymentBuilder { - podAffinity := v1.Affinity{ - PodAntiAffinity: &v1.PodAntiAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{{ - LabelSelector: &metav1.LabelSelector{ - MatchLabels: labels, - }, - TopologyKey: topologyKey, - }}, - }, - } - - if d.nodeAffinity != nil && d.nodeAffinity.NodeAffinity != nil { - podAffinity.NodeAffinity = d.nodeAffinity.NodeAffinity - } - - d.podAffinity = &podAffinity - return d -} - -func (d *DeploymentBuilder) Labels(labels map[string]string) *DeploymentBuilder { - for k, v := range labels { - if d.labels == nil { - d.labels = make(map[string]string) - } - d.labels[k] = v - } - return d -} - -func (d *DeploymentBuilder) Annotations(annotations map[string]string) *DeploymentBuilder { - for k, v := range annotations { - if d.annotations == nil { - d.annotations = make(map[string]string) - } - d.annotations[k] = v - } - return d -} - -func (d *DeploymentBuilder) Args(args ...string) *DeploymentBuilder { - d.args = args - return d -} - -func (d *DeploymentBuilder) Replicas(replicas int) *DeploymentBuilder { - d.replicas = int32(replicas) - return d -} - -func (d *DeploymentBuilder) Resources(resources v1.ResourceRequirements) *DeploymentBuilder { - d.resources = resources - return d -} - -func (d *DeploymentBuilder) MountSecret(secret, path string, mode int32) *DeploymentBuilder { - d.volumes = append(d.volumes, v1.Volume{ - Name: secret, - VolumeSource: v1.VolumeSource{ - Secret: &v1.SecretVolumeSource{ - SecretName: secret, - DefaultMode: &mode, - }, - }, - }) - d.volumeMounts = append(d.volumeMounts, v1.VolumeMount{ - Name: secret, - MountPath: path, - ReadOnly: true, - }) - - return d -} - -func (d *DeploymentBuilder) MountConfigMap(cm, path string) *DeploymentBuilder { - d.volumes = append(d.volumes, v1.Volume{ - Name: cm, - VolumeSource: v1.VolumeSource{ - ConfigMap: &v1.ConfigMapVolumeSource{ - LocalObjectReference: v1.LocalObjectReference{ - Name: cm, - }, - }, - }, - }) - d.volumeMounts = append(d.volumeMounts, v1.VolumeMount{ - Name: cm, - MountPath: path, - }) - return d -} - -func (d *DeploymentBuilder) ServiceAccount(name string) *DeploymentBuilder { - d.sa = name - return d -} - -func (d *DeploymentBuilder) GetLabels() map[string]string { - if len(d.labels) == 0 { - return map[string]string{ - "name": d.Name, - } - } - return d.labels -} - -func (d *DeploymentBuilder) Ports(ports ...int32) *DeploymentBuilder { - for _, port := range ports { - d.ports = append(d.ports, v1.ContainerPort{ - ContainerPort: port, - Protocol: v1.ProtocolTCP, - }) - } - return d -} - -func (d *DeploymentBuilder) Expose(ports ...int32) *DeploymentBuilder { - var servicePorts []v1.ServicePort - - for _, port := range ports { - d.ports = append(d.ports, v1.ContainerPort{ - ContainerPort: port, - }) - servicePorts = append(servicePorts, v1.ServicePort{ - Port: port, - TargetPort: intstr.FromInt(int(port)), - }) - } - d.Builder.Append(&v1.Service{ - TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: "v1"}, - ObjectMeta: d.Builder.ObjectMeta(d.Name), - Spec: v1.ServiceSpec{ - Selector: d.GetLabels(), - Ports: servicePorts, - }, - }) - return d -} - -func (d *DeploymentBuilder) Build() *Builder { - d.Builder.Append(&apps.Deployment{ - TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: "apps/v1"}, - ObjectMeta: d.Builder.ObjectMeta(d.Name), - Spec: apps.DeploymentSpec{ - Replicas: &d.replicas, - Selector: &metav1.LabelSelector{ - MatchLabels: d.GetLabels(), - }, - Template: d.PodTemplate(), - }, - }) - return d.Builder -} - -func (b *Builder) ServiceAccount(name string) *ServiceAccountBuilder { - b.Append(&v1.ServiceAccount{ - TypeMeta: metav1.TypeMeta{Kind: "ServiceAccount", APIVersion: "v1"}, - ObjectMeta: b.ObjectMeta(name), - }) - return &ServiceAccountBuilder{ - Builder: b, - Name: name, - } -} - -type ServiceAccountBuilder struct { - *Builder - Name string -} - -func (s *ServiceAccountBuilder) AddRole(role string) *ServiceAccountBuilder { - s.Append(&rbac.RoleBinding{ - ObjectMeta: s.ObjectMeta(s.Name + "-" + role), - TypeMeta: metav1.TypeMeta{ - Kind: "RoleBinding", - APIVersion: "rbac.authorization.k8s.io/v1", - }, - Subjects: []rbac.Subject{ - rbac.Subject{ - Name: s.Name, - Kind: "ServiceAccount", - }, - }, - RoleRef: rbac.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: role, - }, - }) - return s -} - -func (s *ServiceAccountBuilder) AddClusterRole(role string) *ServiceAccountBuilder { - s.Append(&rbac.ClusterRoleBinding{ - ObjectMeta: s.ObjectMeta(s.Name + "-" + role), - TypeMeta: metav1.TypeMeta{ - Kind: "ClusterRoleBinding", - APIVersion: "rbac.authorization.k8s.io/v1", - }, - Subjects: []rbac.Subject{ - rbac.Subject{ - Name: s.Name, - Kind: "ServiceAccount", - Namespace: s.Namespace, - }, - }, - RoleRef: rbac.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: role, - }, - }) - return s -} diff --git a/k8s/client.go b/k8s/client.go deleted file mode 100644 index 782c1d6..0000000 --- a/k8s/client.go +++ /dev/null @@ -1,1675 +0,0 @@ -package k8s - -import ( - "bufio" - "bytes" - "context" - "encoding/base64" - "fmt" - - "net" - "net/http" - "reflect" - - "io/ioutil" - "os" - "path/filepath" - "strings" - "sync" - "time" - - "github.com/AlekSi/pointer" - certs "github.com/flanksource/commons/certs" - "github.com/flanksource/commons/files" - "github.com/flanksource/commons/logger" - utils "github.com/flanksource/commons/utils" - "github.com/flanksource/template-operator/k8s/kustomize" - "github.com/go-test/deep" - "github.com/mitchellh/mapstructure" - "gopkg.in/flanksource/yaml.v3" - v1 "k8s.io/api/core/v1" - - "k8s.io/api/networking/v1beta1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/intstr" - cliresource "k8s.io/cli-runtime/pkg/resource" - "k8s.io/client-go/discovery/cached/disk" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "k8s.io/client-go/restmapper" - "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/tools/clientcmd/api" - "k8s.io/client-go/tools/remotecommand" - "k8s.io/client-go/transport" -) - -type Client struct { - logger.Logger - GetKubeConfigBytes func() ([]byte, error) - ApplyDryRun bool - ApplyHook ApplyHook - Trace bool - GetKustomizePatches func() ([]string, error) - client *kubernetes.Clientset - dynamicClient dynamic.Interface - restConfig *rest.Config - kustomizeManager *kustomize.Manager - restMapper meta.RESTMapper -} - -func NewClient(config *rest.Config, logger logger.Logger) *Client { - return &Client{ - restConfig: config, - Logger: logger, - } -} - -func (c *Client) ResetConnection() { - c.client = nil - c.dynamicClient = nil - c.restConfig = nil -} - -func (c *Client) ScalePod(pod v1.Pod, replicas int32) error { - client, err := c.GetClientset() - if err != nil { - return err - } - - for _, owner := range pod.GetOwnerReferences() { - if owner.Kind == "ReplicaSet" { - replicasets := client.AppsV1().ReplicaSets(pod.Namespace) - rs, err := replicasets.Get(context.TODO(), owner.Name, metav1.GetOptions{}) - if err != nil { - return err - } - if *rs.Spec.Replicas != replicas { - c.Infof("Scaling %s/%s => %d", pod.Namespace, owner.Name, replicas) - rs.Spec.Replicas = &replicas - _, err := replicasets.Update(context.TODO(), rs, metav1.UpdateOptions{}) - if err != nil { - return err - } - } else { - c.Infof("Scaling %s/%s => %d (no-op)", pod.Namespace, owner.Name, replicas) - } - } - } - return nil -} - -func (c *Client) GetPodReplicas(pod v1.Pod) (int, error) { - client, err := c.GetClientset() - if err != nil { - return 0, err - } - - for _, owner := range pod.GetOwnerReferences() { - if owner.Kind == "ReplicaSet" { - replicasets := client.AppsV1().ReplicaSets(pod.Namespace) - rs, err := replicasets.Get(context.TODO(), owner.Name, metav1.GetOptions{}) - if err != nil { - return 0, err - } - return int(*rs.Spec.Replicas), nil - } - } - return 1, nil -} - -func (c *Client) Cordon(nodeName string) error { - c.Infof("[%s] cordoning", nodeName) - - client, err := c.GetClientset() - if err != nil { - return nil - } - nodes := client.CoreV1().Nodes() - node, err := nodes.Get(context.TODO(), nodeName, metav1.GetOptions{}) - if err != nil { - return err - } - node.Spec.Unschedulable = true - _, err = nodes.Update(context.TODO(), node, metav1.UpdateOptions{}) - return err -} - -func (c *Client) Uncordon(nodeName string) error { - c.Infof("[%s] uncordoning", nodeName) - client, err := c.GetClientset() - if err != nil { - return nil - } - nodes := client.CoreV1().Nodes() - node, err := nodes.Get(context.TODO(), nodeName, metav1.GetOptions{}) - if err != nil { - return err - } - node.Spec.Unschedulable = false - _, err = nodes.Update(context.TODO(), node, metav1.UpdateOptions{}) - return err -} - -func (c *Client) GetKustomize() (*kustomize.Manager, error) { - if c.kustomizeManager != nil { - return c.kustomizeManager, nil - } - dir, _ := ioutil.TempDir("", "platform-cli-kustomize") - patches, err := c.GetKustomizePatches() - if err != nil { - return nil, err - } - no := 1 - var ( - patchData *[]byte - name string - ) - for _, patch := range patches { - if files.Exists(patch) { - name = filepath.Base(patch) - patchBytes, err := ioutil.ReadFile(patch) - if err != nil { - return nil, err - } - patchData = &patchBytes - } else { - patchBytes := []byte(patch) - patchData = &patchBytes - name = fmt.Sprintf("patch-%d.yaml", no) - no++ - } - patchData, err = templatizePatch(patchData) - if err != nil { - return nil, err - } - if c.Trace { - c.Tracef("patch file %v after templating:\n%v\n\n", name, string(*patchData)) - } - if _, err := files.CopyFromReader(bytes.NewBuffer(*patchData), dir+"/"+name, 0644); err != nil { - return nil, err - } - } - kustomizeManager, err := kustomize.GetManager(dir) - c.kustomizeManager = kustomizeManager - return c.kustomizeManager, err -} - -// templatizePatch takes a patch stream (possibly containing multiple -// YAML documents) and templatizes each. -// blank documents are skipped. -func templatizePatch(patch *[]byte) (*[]byte, error) { - var result []byte - remainingData := patch - for { - first, rest := getDocumentsFromYamlFile(*remainingData) - remainingData = &rest - if len(first) == 0 { - continue - } - templated, err := templatizeDocument(first) - if err != nil { - return nil, err - } - if len(result) > 0 { - result = append(result, []byte("---\n")...) - } - result = append(result, *templated...) - if len(rest) == 0 { - break - } - } - return &result, nil -} - -// templatizeDocument applies templating to a supplied YAML -// document via the templating functionality in -// "gopkg.in/flanksource/yaml.v3" -// NOTE: only the first YAML document in a stream will be processed. -func templatizeDocument(patch []byte) (*[]byte, error) { - var body interface{} - if err := yaml.Unmarshal(patch, &body); err != nil { - return nil, err - } - if body == nil { - return &[]byte{}, nil - } - templated, err := yaml.Marshal(body) - if err != nil { - return nil, err - } - return &templated, nil -} - -// getDocumentsFromYamlFile returns the first YAML document -// from a stream and a byte slice containing the remainder of the stream. -// This is needed since yaml.v3 (and the flanksource derived yaml.v3) only -// unmarshalls the **first** document in a stream. -// -// (see https://pkg.go.dev/gopkg.in/flanksource/yaml.v3@v3.1.1?tab=doc#Unmarshal) -func getDocumentsFromYamlFile(yamlData []byte) (firstDoc []byte, rest []byte) { - endIndex := bytes.Index(yamlData, []byte("---")) - if endIndex == -1 { - return yamlData, []byte{} - } - return yamlData[:endIndex], yamlData[endIndex+3:] -} - -// GetDynamicClient creates a new k8s client -func (c *Client) GetDynamicClient() (dynamic.Interface, error) { - if c.dynamicClient != nil { - return c.dynamicClient, nil - } - cfg, err := c.GetRESTConfig() - if err != nil { - return nil, fmt.Errorf("getClientset: failed to get REST config: %v", err) - } - c.dynamicClient, err = dynamic.NewForConfig(cfg) - return c.dynamicClient, err -} - -// GetClientset creates a new k8s client -func (c *Client) GetClientset() (*kubernetes.Clientset, error) { - if c.client != nil { - return c.client, nil - } - - cfg, err := c.GetRESTConfig() - if err != nil { - return nil, fmt.Errorf("getClientset: failed to get REST config: %v", err) - } - c.client, err = kubernetes.NewForConfig(cfg) - return c.client, err -} - -func (c *Client) GetRESTConfig() (*rest.Config, error) { - if c.restConfig != nil { - return c.restConfig, nil - } - data, err := c.GetKubeConfigBytes() - if err != nil { - return nil, fmt.Errorf("getRESTConfig: failed to get kubeconfig: %v", err) - } - if len(data) == 0 { - return nil, fmt.Errorf("kubeConfig is empty") - } - - c.restConfig, err = clientcmd.RESTConfigFromKubeConfig(data) - return c.restConfig, err -} - -// GetSecret returns the data of a secret or nil for any error -func (c *Client) GetSecret(namespace, name string) *map[string][]byte { - k8s, err := c.GetClientset() - if err != nil { - c.Tracef("failed to get client %v", err) - return nil - } - secret, err := k8s.CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil { - c.Tracef("failed to get secret %s/%s: %v\n", namespace, name, err) - return nil - } - return &secret.Data -} - -// GetConfigMap returns the data of a secret or nil for any error -func (c *Client) GetConfigMap(namespace, name string) *map[string]string { - k8s, err := c.GetClientset() - if err != nil { - c.Tracef("failed to get client %v", err) - return nil - } - cm, err := k8s.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil { - c.Tracef("failed to get secret %s/%s: %v\n", namespace, name, err) - return nil - } - return &cm.Data -} - -func (c *Client) Get(namespace string, name string, obj runtime.Object) error { - client, _, _, err := c.GetDynamicClientFor(namespace, obj) - if err != nil { - return err - } - unstructuredObj, err := client.Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil { - return fmt.Errorf("get: failed to get client: %v", err) - } - - err = runtime.DefaultUnstructuredConverter. - FromUnstructured(unstructuredObj.Object, obj) - if err == nil { - return nil - } - // if c.IsLevelEnabled(logger.TraceLevel) { - // spew.Dump(unstructuredObj.Object) - // } - - // FIXME(moshloop) getting the zalando operationconfiguration fails with "unrecognized type: int64" so we fall back to brute-force - c.Warnf("Using mapstructure to decode %s: %v", obj.GetObjectKind().GroupVersionKind().Kind, err) - config := &mapstructure.DecoderConfig{ - WeaklyTypedInput: true, - TagName: "json", - DecodeHook: mapstructure.ComposeDecodeHookFunc(decodeStringToTime, decodeStringToDuration, decodeStringToTimeDuration), - Result: obj, - } - - decoder, err := mapstructure.NewDecoder(config) - if err != nil { - return fmt.Errorf("get: failed to decode config: %v", err) - } - return decoder.Decode(unstructuredObj.Object) -} - -func decodeStringToTimeDuration(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(time.Duration(5)) { - return data, nil - } - d, err := time.ParseDuration(data.(string)) - if err != nil { - return data, fmt.Errorf("decodeStringToTimeDuration: Failed to parse duration: %v", err) - } - return d, nil -} - -func decodeStringToDuration(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(metav1.Duration{Duration: time.Duration(5)}) { - return data, nil - } - d, err := time.ParseDuration(data.(string)) - if err != nil { - return data, fmt.Errorf("decodeStringToDuration: Failed to parse duration: %v", err) - } - return metav1.Duration{Duration: d}, nil -} - -func decodeStringToTime(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(metav1.Time{Time: time.Now()}) { - return data, nil - } - d, err := time.Parse(time.RFC3339, data.(string)) - if err != nil { - return data, fmt.Errorf("decodeStringToTime: failed to decode to time: %v", err) - } - return metav1.Time{Time: d}, nil -} - -func (c *Client) GetRestMapper() (meta.RESTMapper, error) { - if c.restMapper != nil { - return c.restMapper, nil - } - - config, _ := c.GetRESTConfig() - - // re-use kubectl cache - host := config.Host - host = strings.ReplaceAll(host, "https://", "") - host = strings.ReplaceAll(host, "-", "_") - host = strings.ReplaceAll(host, ":", "_") - cacheDir := os.ExpandEnv("$HOME/.kube/cache/discovery/" + host) - cache, err := disk.NewCachedDiscoveryClientForConfig(config, cacheDir, "", 10*time.Minute) - if err != nil { - return nil, err - } - c.restMapper = restmapper.NewDeferredDiscoveryRESTMapper(cache) - return c.restMapper, err -} - -func (c *Client) GetClientByKind(kind string) (dynamic.NamespaceableResourceInterface, error) { - dynamicClient, err := c.GetDynamicClient() - if err != nil { - return nil, err - } - rm, _ := c.GetRestMapper() - gvk, err := rm.KindFor(schema.GroupVersionResource{ - Resource: kind, - }) - if err != nil { - return nil, err - } - gk := schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind} - mapping, err := rm.RESTMapping(gk, gvk.Version) - if err != nil { - return nil, err - } - return dynamicClient.Resource(mapping.Resource), nil -} - -func (c *Client) GetDynamicClientFor(namespace string, obj runtime.Object) (dynamic.ResourceInterface, *schema.GroupVersionResource, *unstructured.Unstructured, error) { - dynamicClient, err := c.GetDynamicClient() - if err != nil { - return nil, nil, nil, fmt.Errorf("getDynamicClientFor: failed to get dynamic client: %v", err) - } - - return c.getDynamicClientFor(dynamicClient, namespace, obj) -} - -func (c *Client) GetDynamicClientForUser(namespace string, obj runtime.Object, user string) (dynamic.ResourceInterface, *schema.GroupVersionResource, *unstructured.Unstructured, error) { - data, err := c.GetKubeConfigBytes() - if err != nil { - return nil, nil, nil, fmt.Errorf("getRESTConfig: failed to get kubeconfig: %v", err) - } - if len(data) == 0 { - return nil, nil, nil, fmt.Errorf("kubeConfig is empty") - } - - cfg, err := clientcmd.RESTConfigFromKubeConfig(data) - if err != nil { - return nil, nil, nil, fmt.Errorf("getClientset: failed to get REST config: %v", err) - } - - impersonate := transport.ImpersonationConfig{UserName: user} - - transportConfig, err := cfg.TransportConfig() - if err != nil { - return nil, nil, nil, fmt.Errorf("failed to get transport config: %v", err) - } - tlsConfig, err := transport.TLSConfigFor(transportConfig) - if err != nil { - return nil, nil, nil, fmt.Errorf("failed to get tls config: %v", err) - } - timeout := 5 * time.Second - - tr := &http.Transport{ - DialContext: (&net.Dialer{ - Timeout: timeout, - KeepAlive: 30 * time.Second, - DualStack: false, // K8s do not work well with IPv6 - }).DialContext, - TLSHandshakeTimeout: timeout, - ResponseHeaderTimeout: 10 * time.Second, - MaxIdleConns: 10, - MaxIdleConnsPerHost: 2, - IdleConnTimeout: 20 * time.Second, - TLSClientConfig: tlsConfig, - } - - cfg.Transport = transport.NewImpersonatingRoundTripper(impersonate, tr) - cfg.TLSClientConfig = rest.TLSClientConfig{} - dynamicClient, err := dynamic.NewForConfig(cfg) - if err != nil { - return nil, nil, nil, fmt.Errorf("failed to get dynamic from config: %v", err) - } - - return c.getDynamicClientFor(dynamicClient, namespace, obj) -} - -func (c *Client) getDynamicClientFor(dynamicClient dynamic.Interface, namespace string, obj runtime.Object) (dynamic.ResourceInterface, *schema.GroupVersionResource, *unstructured.Unstructured, error) { - gvk := obj.GetObjectKind().GroupVersionKind() - gk := schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind} - rm, _ := c.GetRestMapper() - - mapping, err := rm.RESTMapping(gk, gvk.Version) - if err != nil && meta.IsNoMatchError(err) && !c.ApplyDryRun { - // new CRD may still becoming ready, flush caches and retry - time.Sleep(5 * time.Second) - c.restMapper = nil - rm, _ := c.GetRestMapper() - mapping, err = rm.RESTMapping(gk, gvk.Version) - } - if err != nil { - return nil, nil, nil, err - } - - resource := mapping.Resource - - convertedObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj) - if err != nil { - return nil, nil, nil, fmt.Errorf("getDynamicClientFor: failed to convert object: %v", err) - } - - unstructuredObj := &unstructured.Unstructured{Object: convertedObj} - - if mapping.Scope == meta.RESTScopeRoot { - return dynamicClient.Resource(mapping.Resource), &resource, unstructuredObj, nil - } - if namespace == "" { - namespace = unstructuredObj.GetNamespace() - } - return dynamicClient.Resource(mapping.Resource).Namespace(namespace), &resource, unstructuredObj, nil -} - -func (c *Client) GetRestClient(obj unstructured.Unstructured) (*cliresource.Helper, error) { - rm, _ := c.GetRestMapper() - restConfig, _ := c.GetRESTConfig() - // Get some metadata needed to make the REST request. - gvk := obj.GetObjectKind().GroupVersionKind() - gk := schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind} - mapping, err := rm.RESTMapping(gk, gvk.Version) - if err != nil { - return nil, err - } - - gv := mapping.GroupVersionKind.GroupVersion() - restConfig.ContentConfig = cliresource.UnstructuredPlusDefaultContentConfig() - restConfig.GroupVersion = &gv - if len(gv.Group) == 0 { - restConfig.APIPath = "/api" - } else { - restConfig.APIPath = "/apis" - } - - restClient, err := rest.RESTClientFor(restConfig) - if err != nil { - return nil, err - } - - return cliresource.NewHelper(restClient, mapping), nil -} - -func (c *Client) ApplyUnstructured(namespace string, objects ...*unstructured.Unstructured) error { - for _, unstructuredObj := range objects { - client, err := c.GetRestClient(*unstructuredObj) - if err != nil { - return err - } - - if c.ApplyHook != nil { - c.ApplyHook(namespace, *unstructuredObj) - } - if c.ApplyDryRun { - c.Debugf("[dry-run] %s/%s/%s created/configured", client.Resource, unstructuredObj, unstructuredObj.GetName()) - } else { - _, err = client.Create(namespace, true, unstructuredObj) - if errors.IsAlreadyExists(err) { - existingRuntime, err := client.Get(namespace, unstructuredObj.GetName()) - existing := existingRuntime.(*unstructured.Unstructured) - - if unstructuredObj.GetKind() == "Service" { - // Workaround for immutable spec.clusterIP error message - spec := unstructuredObj.Object["spec"].(map[string]interface{}) - spec["clusterIP"] = existing.Object["spec"].(map[string]interface{})["clusterIP"] - } else if unstructuredObj.GetKind() == "ServiceAccount" { - unstructuredObj.Object["secrets"] = existing.Object["secrets"] - } - - unstructuredObj.SetResourceVersion(existing.GetResourceVersion()) - unstructuredObj.SetSelfLink(existing.GetSelfLink()) - unstructuredObj.SetUID(existing.GetUID()) - unstructuredObj.SetCreationTimestamp(existing.GetCreationTimestamp()) - unstructuredObj.SetGeneration(existing.GetGeneration()) - - updated, err := client.Replace(namespace, unstructuredObj.GetName(), true, unstructuredObj) - if err != nil { - c.Errorf("error handling: %s : %+v", client.Resource, err) - } else { - updatedUnstructured := updated.(*unstructured.Unstructured) - if updatedUnstructured.GetResourceVersion() == unstructuredObj.GetResourceVersion() { - c.Debugf("%s/%s/%s (unchanged)", client.Resource, unstructuredObj.GetNamespace(), unstructuredObj.GetName()) - } else { - // remove "runtime" fields from objects that woulds otherwise increase the verbosity of diffs - unstructured.RemoveNestedField(unstructuredObj.Object, "metadata", "managedFields") - unstructured.RemoveNestedField(unstructuredObj.Object, "metadata", "ownerReferences") - unstructured.RemoveNestedField(unstructuredObj.Object, "metadata", "generation") - unstructured.RemoveNestedField(unstructuredObj.Object, "metadata", "annotations", "deprecated.daemonset.template.generation") - unstructured.RemoveNestedField(unstructuredObj.Object, "metadata", "annotations", "template-operator-owner-ref") - unstructured.RemoveNestedField(updatedUnstructured.Object, "metadata", "managedFields") - unstructured.RemoveNestedField(updatedUnstructured.Object, "metadata", "ownerReferences") - unstructured.RemoveNestedField(updatedUnstructured.Object, "metadata", "generation") - unstructured.RemoveNestedField(updatedUnstructured.Object, "metadata", "annotations", "deprecated.daemonset.template.generation") - unstructured.RemoveNestedField(updatedUnstructured.Object, "metadata", "annotations", "template-operator-owner-ref") - - diff := deep.Equal(unstructuredObj.Object, updatedUnstructured.Object) - if len(diff) > 0 { - c.Debugf("Diff: %s", diff) - c.Infof("%s/%s/%s configured %d", client.Resource, unstructuredObj.GetNamespace(), unstructuredObj.GetName(), len(diff)) - } else { - c.Debugf("%s/%s/%s (unchanged)", client.Resource, unstructuredObj.GetNamespace(), unstructuredObj.GetName()) - } - - } - } - } else if err == nil { - c.Infof("%s/%s/%s created", client.Resource, unstructuredObj.GetNamespace(), unstructuredObj.GetName()) - } else { - c.Errorf("error handling: %s : %+v", client.Resource, err) - } - } - } - return nil -} - -func (c *Client) trace(msg string, objects ...runtime.Object) { - if !c.Trace { - return - } - for _, obj := range objects { - data, err := yaml.Marshal(obj) - if err != nil { - c.Errorf("Error tracing %s", err) - } else { - fmt.Printf("%s\n%s", msg, string(data)) - } - } -} - -func (c *Client) DeleteUnstructured(namespace string, objects ...*unstructured.Unstructured) error { - for _, unstructuredObj := range objects { - client, err := c.GetRestClient(*unstructuredObj) - if err != nil { - return err - } - - if c.ApplyDryRun { - c.Debugf("[dry-run] %s/%s/%s removed", namespace, client.Resource, unstructuredObj.GetName()) - } else { - if _, err := client.Delete(namespace, unstructuredObj.GetName()); err != nil { - return err - } - c.Infof("%s/%s/%s removed", namespace, client.Resource, unstructuredObj.GetName()) - } - } - return nil -} - -type ApplyHook func(namespace string, obj unstructured.Unstructured) - -func (c *Client) Apply(namespace string, objects ...runtime.Object) error { - for _, obj := range objects { - client, resource, unstructuredObj, err := c.GetDynamicClientFor(namespace, obj) - if err != nil { - if c.ApplyDryRun && strings.HasPrefix(err.Error(), "no matches for kind") { - c.Debugf("[dry-run] failed to get dynamic client for namespace %s", namespace) - continue - } - return fmt.Errorf("failed to get dynamic client for %v: %v", obj, err) - } - - if c.ApplyHook != nil { - c.ApplyHook(namespace, *unstructuredObj) - } - if c.ApplyDryRun { - c.trace("apply", unstructuredObj) - c.Debugf("[dry-run] %s/%s created/configured", resource.Resource, unstructuredObj.GetName()) - continue - } - - existing, _ := client.Get(context.TODO(), unstructuredObj.GetName(), metav1.GetOptions{}) - - if existing == nil { - c.trace("creating", unstructuredObj) - _, err = client.Create(context.TODO(), unstructuredObj, metav1.CreateOptions{}) - if err != nil { - c.Errorf("error creating: %s/%s/%s : %+v", resource.Group, resource.Version, resource.Resource, err) - } else { - c.Infof("%s/%s/%s created", resource.Resource, unstructuredObj.GetNamespace(), unstructuredObj.GetName()) - } - } else { - if unstructuredObj.GetKind() == "Service" { - // Workaround for immutable spec.clusterIP error message - spec := unstructuredObj.Object["spec"].(map[string]interface{}) - spec["clusterIP"] = existing.Object["spec"].(map[string]interface{})["clusterIP"] - } else if unstructuredObj.GetKind() == "ServiceAccount" { - unstructuredObj.Object["secrets"] = existing.Object["secrets"] - } - // apps/DameonSet MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable - // webhook CA's - - c.trace("updating", unstructuredObj) - unstructuredObj.SetResourceVersion(existing.GetResourceVersion()) - unstructuredObj.SetSelfLink(existing.GetSelfLink()) - unstructuredObj.SetUID(existing.GetUID()) - unstructuredObj.SetCreationTimestamp(existing.GetCreationTimestamp()) - unstructuredObj.SetGeneration(existing.GetGeneration()) - if existing.GetAnnotations() != nil && existing.GetAnnotations()["deployment.kubernetes.io/revision"] != "" { - annotations := unstructuredObj.GetAnnotations() - if annotations == nil { - annotations = make(map[string]string) - } - annotations["deployment.kubernetes.io/revision"] = existing.GetAnnotations()["deployment.kubernetes.io/revision"] - unstructuredObj.SetAnnotations(annotations) - } - updated, err := client.Update(context.TODO(), unstructuredObj, metav1.UpdateOptions{}) - if err != nil { - c.Errorf("error updating: %s/%s/%s : %+v", unstructuredObj.GetNamespace(), resource.Resource, unstructuredObj.GetName(), err) - continue - } - - if updated.GetResourceVersion() == unstructuredObj.GetResourceVersion() { - c.Debugf("%s/%s/%s (unchanged)", resource.Resource, unstructuredObj.GetNamespace(), unstructuredObj.GetName()) - } else { - c.Infof("%s/%s/%s configured", resource.Resource, unstructuredObj.GetNamespace(), unstructuredObj.GetName()) - if logger.IsTraceEnabled() { - // remove "runtime" fields from objects that woulds otherwise increase the verbosity of diffs - unstructured.RemoveNestedField(unstructuredObj.Object, "metadata", "managedFields") - unstructured.RemoveNestedField(unstructuredObj.Object, "metadata", "generation") - unstructured.RemoveNestedField(unstructuredObj.Object, "metadata", "annotations", "deprecated.daemonset.template.generation") - - unstructured.RemoveNestedField(existing.Object, "metadata", "managedFields") - unstructured.RemoveNestedField(existing.Object, "metadata", "generation") - unstructured.RemoveNestedField(existing.Object, "metadata", "annotations", "deprecated.daemonset.template.generation") - - diff := deep.Equal(unstructuredObj.Object["metadata"], existing.Object["metadata"]) - if len(diff) > 0 { - c.Tracef("%s", diff) - } - } - } - } - } - return nil -} - -func (c *Client) Annotate(obj runtime.Object, annotations map[string]string) error { - client, resource, unstructuredObj, err := c.GetDynamicClientFor("", obj) - if err != nil { - return fmt.Errorf("annotate: failed to get dynamic client: %s", err) - } - existing := unstructuredObj.GetAnnotations() - for k, v := range annotations { - existing[k] = v - } - unstructuredObj.SetAnnotations(existing) - _, err = client.Update(context.TODO(), unstructuredObj, metav1.UpdateOptions{}) - if err != nil { - return fmt.Errorf("annotate: failed to update object: #{err}") - } - c.Infof("%s/%s/%s annotated", resource.Resource, unstructuredObj.GetNamespace(), unstructuredObj.GetName()) - return nil -} - -func (c *Client) Label(obj runtime.Object, labels map[string]string) error { - client, resource, unstructuredObj, err := c.GetDynamicClientFor("", obj) - if err != nil { - return fmt.Errorf("label: failed to get dynamic client: %v", err) - } - existing := unstructuredObj.GetLabels() - for k, v := range labels { - existing[k] = v - } - unstructuredObj.SetLabels(existing) - if _, err := client.Update(context.TODO(), unstructuredObj, metav1.UpdateOptions{}); err != nil { - return fmt.Errorf("label: failed to update client: %v", err) - } - c.Infof("%s/%s/%s labelled", resource.Resource, unstructuredObj.GetNamespace(), unstructuredObj.GetName()) - return nil -} - -func (c *Client) CreateOrUpdateNamespace(name string, labels, annotations map[string]string) error { - k8s, err := c.GetClientset() - if err != nil { - return fmt.Errorf("createOrUpdateNamespace: failed to get client set: %v", err) - } - - ns := k8s.CoreV1().Namespaces() - cm, err := ns.Get(context.TODO(), name, metav1.GetOptions{}) - - if cm == nil || err != nil { - cm = &v1.Namespace{} - cm.Name = name - cm.Labels = labels - cm.Annotations = annotations - - c.Debugf("Creating namespace %s", name) - if !c.ApplyDryRun { - if _, err := ns.Create(context.TODO(), cm, metav1.CreateOptions{}); err != nil { - return err - } - } - } else { - // update incoming and current labels - if cm.ObjectMeta.Labels != nil { - for k, v := range labels { - cm.ObjectMeta.Labels[k] = v - } - labels = cm.ObjectMeta.Labels - } - - // update incoming and current annotations - if cm.ObjectMeta.Annotations != nil && annotations != nil { - for k, v := range annotations { - cm.ObjectMeta.Annotations[k] = v - } - annotations = cm.ObjectMeta.Annotations - } - } - (*cm).Name = name - (*cm).Labels = labels - (*cm).Annotations = annotations - if !c.ApplyDryRun { - c.Debugf("Updating namespace %s", name) - if _, err := ns.Update(context.TODO(), cm, metav1.UpdateOptions{}); err != nil { - return err - } - } - return nil -} - -// ForceDeleteNamespace deletes a namespace forcibly -// by overriding it's finalizers first -func (c *Client) ForceDeleteNamespace(ns string, timeout time.Duration) error { - c.Warnf("Clearing finalizers for %v", ns) - k8s, err := c.GetClientset() - if err != nil { - return fmt.Errorf("ForceDeleteNamespace: failed to get client set: %v", err) - } - - namespace, err := k8s.CoreV1().Namespaces().Get(context.TODO(), ns, metav1.GetOptions{}) - if err != nil { - return fmt.Errorf("ForceDeleteNamespace: failed to get namespace: %v", err) - } - namespace.Spec.Finalizers = []v1.FinalizerName{} - _, err = k8s.CoreV1().Namespaces().Finalize(context.TODO(), namespace, metav1.UpdateOptions{}) - if err != nil { - return fmt.Errorf("ForceDeleteNamespace: error removing finalisers: %v", err) - } - err = k8s.CoreV1().Namespaces().Delete(context.TODO(), ns, metav1.DeleteOptions{}) - if err != nil { - return fmt.Errorf("ForceDeleteNamespace: error deleting namespace: %v", err) - } - return nil -} - -func (c *Client) HasSecret(ns, name string) bool { - client, err := c.GetClientset() - if err != nil { - c.Tracef("hasSecret: failed to get client set: %v", err) - return false - } - secrets := client.CoreV1().Secrets(ns) - cm, err := secrets.Get(context.TODO(), name, metav1.GetOptions{}) - return cm != nil && err == nil -} - -func (c *Client) HasConfigMap(ns, name string) bool { - client, err := c.GetClientset() - if err != nil { - c.Tracef("hasConfigMap: failed to get client set: %v", err) - return false - } - configmaps := client.CoreV1().ConfigMaps(ns) - cm, err := configmaps.Get(context.TODO(), name, metav1.GetOptions{}) - return cm != nil && err == nil -} - -func (c *Client) GetOrCreateSecret(name, ns string, data map[string][]byte) error { - if c.HasSecret(name, ns) { - return nil - } - return c.CreateOrUpdateSecret(name, ns, data) -} - -func (c *Client) CreateOrUpdateSecret(name, ns string, data map[string][]byte) error { - if c.ApplyDryRun { - c.Debugf("[dry-run] secrets/%s/%s created/configured", ns, name) - return nil - } - return c.Apply(ns, &v1.Secret{ - TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Secret"}, - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns}, - Data: data, - }) -} - -func (c *Client) CreateOrUpdateConfigMap(name, ns string, data map[string]string) error { - if c.ApplyDryRun { - c.Debugf("[dry-run] configmaps/%s/%s created/configured", ns, name) - return nil - } - return c.Apply(ns, &v1.ConfigMap{ - TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"}, - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns}, - Data: data}) -} - -func (c *Client) ExposeIngress(namespace, service string, domain string, port int, annotations map[string]string) error { - k8s, err := c.GetClientset() - if err != nil { - return fmt.Errorf("exposeIngress: failed to get client set: %v", err) - } - ingresses := k8s.NetworkingV1beta1().Ingresses(namespace) - ingress, err := ingresses.Get(context.TODO(), service, metav1.GetOptions{}) - if ingress == nil || err != nil { - ingress = &v1beta1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: service, - Namespace: namespace, - Annotations: annotations, - }, - Spec: v1beta1.IngressSpec{ - TLS: []v1beta1.IngressTLS{ - { - Hosts: []string{domain}, - }, - }, - Rules: []v1beta1.IngressRule{ - { - Host: domain, - IngressRuleValue: v1beta1.IngressRuleValue{ - HTTP: &v1beta1.HTTPIngressRuleValue{ - Paths: []v1beta1.HTTPIngressPath{ - { - Backend: v1beta1.IngressBackend{ - ServiceName: service, - ServicePort: intstr.FromInt(port), - }, - }, - }, - }, - }, - }, - }, - }, - } - c.Infof("Creating %s/ingress/%s", namespace, service) - if !c.ApplyDryRun { - if _, err := ingresses.Create(context.TODO(), ingress, metav1.CreateOptions{}); err != nil { - return fmt.Errorf("exposeIngress: failed to create ingress: %v", err) - } - } - } - return nil -} - -func (c *Client) GetOrCreatePVC(namespace, name, size, class string) error { - client, err := c.GetClientset() - if err != nil { - return fmt.Errorf("getOrCreatePVC: failed to get client set: %v", err) - } - qty, err := resource.ParseQuantity(size) - if err != nil { - return fmt.Errorf("getOrCreatePVC: failed to parse quantity: %v", err) - } - pvcs := client.CoreV1().PersistentVolumeClaims(namespace) - - existing, err := pvcs.Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil && errors.IsNotFound(err) { - c.Tracef("GetOrCreatePVC: failed to get PVC: %s", err) - c.Infof("Creating PVC %s/%s (%s %s)\n", namespace, name, size, class) - _, err = pvcs.Create(context.TODO(), &v1.PersistentVolumeClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Spec: v1.PersistentVolumeClaimSpec{ - StorageClassName: &class, - AccessModes: []v1.PersistentVolumeAccessMode{ - v1.ReadWriteOnce, - }, - Resources: v1.ResourceRequirements{ - Requests: v1.ResourceList{ - v1.ResourceStorage: qty, - }, - }, - }, - }, metav1.CreateOptions{}) - } else if err != nil { - return fmt.Errorf("getOrCreatePVC: failed to create PVC: %v", err) - } else { - c.Infof("Found existing PVC %s/%s (%s %s) ==> %s\n", namespace, name, size, class, existing.UID) - return nil - } - return err -} - -func (c *Client) StreamLogs(namespace, name string) error { - client, err := c.GetClientset() - if err != nil { - return err - } - pods := client.CoreV1().Pods(namespace) - pod, err := pods.Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil { - return err - } - c.Debugf("Waiting for %s/%s to be running", namespace, name) - if err := c.WaitForPod(namespace, name, 120*time.Second, v1.PodRunning, v1.PodSucceeded); err != nil { - return err - } - c.Debugf("%s/%s running, streaming logs", namespace, name) - var wg sync.WaitGroup - for _, container := range append(pod.Spec.Containers, pod.Spec.InitContainers...) { - logs := pods.GetLogs(pod.Name, &v1.PodLogOptions{ - Container: container.Name, - }) - - prefix := pod.Name - if len(pod.Spec.Containers) > 1 { - prefix += "/" + container.Name - } - podLogs, err := logs.Stream(context.TODO()) - if err != nil { - return err - } - wg.Add(1) - go func() { - defer podLogs.Close() - defer wg.Done() - - scanner := bufio.NewScanner(podLogs) - for scanner.Scan() { - incoming := scanner.Bytes() - buffer := make([]byte, len(incoming)) - copy(buffer, incoming) - fmt.Printf("\x1b[38;5;244m[%s]\x1b[0m %s\n", prefix, string(buffer)) - } - }() - } - wg.Wait() - if err = c.WaitForPod(namespace, name, 120*time.Second, v1.PodSucceeded); err != nil { - return err - } - pod, err = pods.Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil { - return err - } - if pod.Status.Phase == v1.PodSucceeded { - return nil - } - return fmt.Errorf("pod did not finish successfully %s - %s", pod.Status.Phase, pod.Status.Message) -} - -func CreateKubeConfig(clusterName string, ca certs.CertificateAuthority, endpoint string, group string, user string, expiry time.Duration) ([]byte, error) { - contextName := fmt.Sprintf("%s@%s", user, clusterName) - cert := certs.NewCertificateBuilder(user).Organization(group).Client().Certificate - if cert.X509.PublicKey == nil && cert.PrivateKey != nil { - cert.X509.PublicKey = cert.PrivateKey.Public() - } - signed, err := ca.Sign(cert.X509, expiry) - if err != nil { - return nil, fmt.Errorf("createKubeConfig: failed to sign certificate: %v", err) - } - cert = &certs.Certificate{ - X509: signed, - PrivateKey: cert.PrivateKey, - } - - cfg := api.Config{ - Clusters: map[string]*api.Cluster{ - clusterName: { - Server: "https://" + endpoint + ":6443", - InsecureSkipTLSVerify: true, - // The CA used for signing the client certificate is not the same as the - // as the CA (kubernetes-ca) that signed the api-server cert. The kubernetes-ca - // is ephemeral. - // TODO dynamically download CA from master server - // CertificateAuthorityData: []byte(platform.Certificates.CA.X509), - }, - }, - Contexts: map[string]*api.Context{ - contextName: { - Cluster: clusterName, - AuthInfo: contextName, - Namespace: "kube-system", - }, - }, - AuthInfos: map[string]*api.AuthInfo{ - contextName: { - ClientKeyData: cert.EncodedPrivateKey(), - ClientCertificateData: cert.EncodedCertificate(), - }, - }, - CurrentContext: contextName, - } - - return clientcmd.Write(cfg) -} - -func CreateOIDCKubeConfig(clusterName string, ca certs.CertificateAuthority, endpoint, idpURL, idToken, accessToken, refreshToken string) ([]byte, error) { - if !strings.HasPrefix("https://", endpoint) { - endpoint = "https://" + endpoint - } - - if !strings.HasPrefix("https://", idpURL) { - idpURL = "https://" + idpURL - } - cfg := api.Config{ - Clusters: map[string]*api.Cluster{ - clusterName: { - Server: endpoint + ":6443", - InsecureSkipTLSVerify: true, - }, - }, - Contexts: map[string]*api.Context{ - clusterName: { - Cluster: clusterName, - AuthInfo: "sso@" + clusterName, - }, - }, - AuthInfos: map[string]*api.AuthInfo{ - "sso@" + clusterName: { - AuthProvider: &api.AuthProviderConfig{ - Name: "oidc", - Config: map[string]string{ - "client-id": "kubernetes", - "client-secret": "ZXhhbXBsZS1hcHAtc2VjcmV0", - "extra-scopes": "offline_access openid profile email groups", - "idp-certificate-authority-data": base64.StdEncoding.EncodeToString(ca.GetPublicChain()[0].EncodedCertificate()), - "idp-issuer-url": idpURL, - "id-token": idToken, - "access-token": accessToken, - "refresh-token": refreshToken, - }, - }, - }, - }, - CurrentContext: clusterName, - } - - return clientcmd.Write(cfg) -} - -// CreateMultiKubeConfig creates a kubeconfig file contents for a map of -// cluster name -> cluster API endpoint hosts, all with a shared -// user name, group and cert expiry. -// NOTE: these clusters all need to share the same plaform CA -func CreateMultiKubeConfig(ca certs.CertificateAuthority, clusters map[string]string, group string, user string, expiry time.Duration) ([]byte, error) { - if len(clusters) < 1 { - return []byte{}, fmt.Errorf("CreateMultiKubeConfig failed since it was given an empty cluster map") - } - cfg := api.Config{ - Clusters: map[string]*api.Cluster{}, - Contexts: map[string]*api.Context{}, - AuthInfos: map[string]*api.AuthInfo{}, - CurrentContext: "", - } - for clusterName, endpoint := range clusters { - cert := certs.NewCertificateBuilder(user).Organization(group).Client().Certificate - if cert.X509.PublicKey == nil && cert.PrivateKey != nil { - cert.X509.PublicKey = cert.PrivateKey.Public() - } - signed, err := ca.Sign(cert.X509, expiry) - if err != nil { - return nil, fmt.Errorf("createKubeConfig: failed to sign certificate: %v", err) - } - cert = &certs.Certificate{ - X509: signed, - PrivateKey: cert.PrivateKey, - } - cfg.Clusters[clusterName] = &api.Cluster{ - Server: endpoint, - InsecureSkipTLSVerify: true, - } - context := fmt.Sprintf("%s@%s", user, clusterName) - cfg.Contexts[clusterName] = &api.Context{ - Cluster: clusterName, - AuthInfo: context, - Namespace: "kube-system", //TODO: verify - } - cfg.AuthInfos[context] = &api.AuthInfo{ - ClientKeyData: cert.EncodedPrivateKey(), - ClientCertificateData: cert.EncodedCertificate(), - } - } - return clientcmd.Write(cfg) -} - -// PingMaster attempts to connect to the API server and list nodes and services -// to ensure the API server is ready to accept any traffic -func (c *Client) PingMaster() bool { - client, err := c.GetClientset() - if err != nil { - c.Tracef("pingMaster: Failed to get clientset: %v", err) - return false - } - - nodes, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) - if err != nil { - c.Tracef("pingMaster: Failed to get nodes list: %v", err) - return false - } - if nodes == nil && len(nodes.Items) == 0 { - return false - } - - _, err = client.CoreV1().ServiceAccounts("kube-system").Get(context.TODO(), "default", metav1.GetOptions{}) - if err != nil { - c.Tracef("pingMaster: Failed to get service account: %v", err) - return false - } - return true -} - -func (c *Client) WaitForResource(kind, namespace, name string, timeout time.Duration) error { - client, err := c.GetClientByKind(kind) - if err != nil { - return err - } - start := time.Now() - for { - item, err := client.Namespace(namespace).Get(context.TODO(), name, metav1.GetOptions{}) - - if errors.IsNotFound(err) { - return err - } - - if start.Add(timeout).Before(time.Now()) { - return fmt.Errorf("timeout exceeded waiting for %s/%s is %s, error: %v", kind, name, "", err) - } - - if err != nil { - c.Debugf("Unable to get %s/%s: %v", kind, name, err) - continue - } - - conditions := item.Object["status"].(map[string]interface{})["conditions"].([]interface{}) - - for _, raw := range conditions { - condition := raw.(map[string]interface{}) - c.Debugf("%s/%s is %s/%s: %s", namespace, name, condition["type"], condition["status"], condition["message"]) - if condition["type"] == "Ready" && condition["status"] == "True" { - return nil - } - } - time.Sleep(1 * time.Second) - } -} - -// WaitForPod waits for a pod to be in the specified phase, or returns an -// error if the timeout is exceeded -func (c *Client) WaitForPod(ns, name string, timeout time.Duration, phases ...v1.PodPhase) error { - client, err := c.GetClientset() - if err != nil { - return fmt.Errorf("waitForPod: Failed to get clientset: %v", err) - } - pods := client.CoreV1().Pods(ns) - start := time.Now() - for { - pod, err := pods.Get(context.TODO(), name, metav1.GetOptions{}) - if start.Add(timeout).Before(time.Now()) { - return fmt.Errorf("timeout exceeded waiting for %s is %s, error: %v", name, pod.Status.Phase, err) - } - - if pod == nil || pod.Status.Phase == v1.PodPending { - time.Sleep(5 * time.Second) - continue - } - if pod.Status.Phase == v1.PodFailed { - return nil - } - - for _, phase := range phases { - if pod.Status.Phase == phase { - return nil - } - } - } -} - -// WaitForDeployment waits for a deployment to have at least 1 ready replica, or returns an -// error if the timeout is exceeded -func (c *Client) WaitForDeployment(ns, name string, timeout time.Duration) error { - client, err := c.GetClientset() - if err != nil { - return err - } - deployments := client.AppsV1().Deployments(ns) - start := time.Now() - msg := false - for { - deployment, _ := deployments.Get(context.TODO(), name, metav1.GetOptions{}) - if start.Add(timeout).Before(time.Now()) { - return fmt.Errorf("timeout exceeded waiting for deployment to become ready %s", name) - } - if deployment != nil && deployment.Status.ReadyReplicas > 1 { - return nil - } - - if !msg { - c.Infof("waiting for %s/%s to have 1 ready replica", ns, name) - msg = true - } - - time.Sleep(2 * time.Second) - } -} - -func (c *Client) GetConditionsForNode(name string) (map[v1.NodeConditionType]v1.ConditionStatus, error) { - client, err := c.GetClientset() - if err != nil { - return nil, err - } - node, err := client.CoreV1().Nodes().Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil { - return nil, err - } - - if node == nil { - return nil, nil - } - - var out = make(map[v1.NodeConditionType]v1.ConditionStatus) - for _, condition := range node.Status.Conditions { - out[condition.Type] = condition.Status - } - return out, nil -} - -// WaitForNode waits for a pod to be in the specified phase, or returns an -// error if the timeout is exceeded -func (c *Client) WaitForNode(name string, timeout time.Duration, condition v1.NodeConditionType, statii ...v1.ConditionStatus) (map[v1.NodeConditionType]v1.ConditionStatus, error) { - start := time.Now() - for { - conditions, err := c.GetConditionsForNode(name) - if start.Add(timeout).Before(time.Now()) { - return conditions, fmt.Errorf("timeout exceeded waiting for %s is %s, error: %v", name, conditions, err) - } - - for _, status := range statii { - if conditions[condition] == status { - return conditions, nil - } - } - time.Sleep(2 * time.Second) - } -} - -// WaitForNode waits for a pod to be in the specified phase, or returns an -// error if the timeout is exceeded -func (c *Client) WaitForTaintRemoval(name string, timeout time.Duration, taintKey string) error { - start := time.Now() -outerLoop: - for { - if time.Since(start) > timeout { - return fmt.Errorf("timeout exceeded waiting for %s to not have %s", name, taintKey) - } - - client, err := c.GetClientset() - if err != nil { - return err - } - node, err := client.CoreV1().Nodes().Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil { - return err - } - - for _, taint := range node.Spec.Taints { - if taint.Key == taintKey { - time.Sleep(2 * time.Second) - continue outerLoop - } - } - // taint not found - return nil - } -} - -// WaitForPodCommand waits for a command executed in pod to succeed with an exit code of 9 -// error if the timeout is exceeded -func (c *Client) WaitForPodCommand(ns, name string, container string, timeout time.Duration, command ...string) error { - start := time.Now() - for { - stdout, stderr, err := c.ExecutePodf(ns, name, container, command...) - if err == nil { - return nil - } - if start.Add(timeout).Before(time.Now()) { - return fmt.Errorf("timeout exceeded waiting for %s stdout: %s, stderr: %s", name, stdout, stderr) - } - time.Sleep(5 * time.Second) - } -} - -// ExecutePodf runs the specified shell command inside a container of the specified pod -func (c *Client) ExecutePodf(namespace, pod, container string, command ...string) (string, string, error) { - client, err := c.GetClientset() - if err != nil { - return "", "", fmt.Errorf("executePodf: Failed to get clientset: %v", err) - } - c.Debugf("[%s/%s/%s] %s", namespace, pod, container, command) - const tty = false - req := client.CoreV1().RESTClient().Post(). - Resource("pods"). - Name(pod). - Namespace(namespace). - SubResource("exec"). - Param("container", container) - req.VersionedParams(&v1.PodExecOptions{ - Container: container, - Command: command, - Stdin: false, - Stdout: true, - Stderr: true, - TTY: tty, - }, scheme.ParameterCodec) - - rc, err := c.GetRESTConfig() - if err != nil { - return "", "", fmt.Errorf("ExecutePodf: Failed to get REST config: %v", err) - } - - exec, err := remotecommand.NewSPDYExecutor(rc, "POST", req.URL()) - if err != nil { - return "", "", fmt.Errorf("ExecutePodf: Failed to get SPDY Executor: %v", err) - } - var stdout, stderr bytes.Buffer - err = exec.Stream(remotecommand.StreamOptions{ - Stdin: nil, - Stdout: &stdout, - Stderr: &stderr, - Tty: tty, - }) - - _stdout := safeString(&stdout) - _stderr := safeString(&stderr) - if err != nil { - return _stdout, _stderr, fmt.Errorf("exec returned an error: %+v", err) - } - - c.Tracef("[%s/%s/%s] %s => %s %s ", namespace, pod, container, command, _stdout, _stderr) - return _stdout, _stderr, nil -} - -func safeString(buf *bytes.Buffer) string { - if buf == nil || buf.Len() == 0 { - return "" - } - return buf.String() -} - -// Executef runs the specified shell command on a node by creating -// a pre-scheduled pod that runs in the host namespace -func (c *Client) Executef(node string, timeout time.Duration, command string, args ...interface{}) (string, error) { - client, err := c.GetClientset() - if err != nil { - return "", fmt.Errorf("executef: Failed to get clientset: %v", err) - } - pods := client.CoreV1().Pods("kube-system") - command = fmt.Sprintf(command, args...) - pod, err := pods.Create(context.TODO(), &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("command-%s-%s", node, utils.ShortTimestamp()), - }, - Spec: NewCommandJob(node, command), - }, metav1.CreateOptions{}) - c.Tracef("[%s] executing '%s' in pod %s", node, command, pod.Name) - if err != nil { - return "", fmt.Errorf("executef: Failed to create pod: %v", err) - } - defer pods.Delete(context.TODO(), pod.ObjectMeta.Name, metav1.DeleteOptions{}) // nolint: errcheck - - logs := pods.GetLogs(pod.Name, &v1.PodLogOptions{ - Container: pod.Spec.Containers[0].Name, - }) - - err = c.WaitForPod("kube-system", pod.ObjectMeta.Name, timeout, v1.PodSucceeded) - logString := read(logs) - if err != nil { - return logString, fmt.Errorf("failed to execute command, pod did not complete: %v", err) - } - c.Tracef("[%s] stdout: %s", node, logString) - return logString, nil -} - -func read(req *rest.Request) string { - stream, err := req.Stream(context.TODO()) - if err != nil { - return fmt.Sprintf("Failed to stream logs %v", err) - } - data, err := ioutil.ReadAll(stream) - if err != nil { - return fmt.Sprintf("Failed to stream logs %v", err) - } - return string(data) -} - -func NewCommandJob(node, command string) v1.PodSpec { - yes := true - return v1.PodSpec{ - RestartPolicy: v1.RestartPolicyNever, - NodeName: node, - Volumes: []v1.Volume{{ - Name: "root", - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{ - Path: "/", - }, - }, - }}, - Containers: []v1.Container{{ - Name: "shell", - Image: "docker.io/ubuntu:18.04", - Command: []string{ - "sh", - "-c", - "chroot /chroot bash -c \"" + command + "\"", - }, - VolumeMounts: []v1.VolumeMount{{ - Name: "root", - MountPath: "/chroot", - }}, - SecurityContext: &v1.SecurityContext{ - Privileged: &yes, - }, - }}, - Tolerations: []v1.Toleration{ - { - // tolerate all values - Operator: "Exists", - }, - }, - HostNetwork: true, - HostPID: true, - HostIPC: true, - } -} - -// GetMasterNode returns the name of the first node found labelled as a master -func (c *Client) GetMasterNode() (string, error) { - client, err := c.GetClientset() - if err != nil { - return "", fmt.Errorf("GetMasterNode: Failed to get clientset: %v", err) - } - - nodes, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return "", err - } - - for _, node := range nodes.Items { - if IsMasterNode(node) { - return node.Name, nil - } - } - return "", fmt.Errorf("no master nodes found") -} - -// GetMasterNode returns a list of all master nodes -func (c *Client) GetMasterNodes() ([]string, error) { - client, err := c.GetClientset() - if err != nil { - return nil, nil - } - - nodes, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return nil, nil - } - - var nodeNames []string - for _, node := range nodes.Items { - if IsMasterNode(node) { - nodeNames = append(nodeNames, node.Name) - } - } - return nodeNames, nil -} - -// Returns the first pod found by label -func (c *Client) GetFirstPodByLabelSelector(namespace string, labelSelector string) (*v1.Pod, error) { - client, err := c.GetClientset() - if err != nil { - return nil, fmt.Errorf("GetFirstPodByLabelSelector: Failed to get clientset: %v", err) - } - - pods, err := client.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: labelSelector, - }) - if err != nil { - return nil, fmt.Errorf("GetFirstPodByLabelSelector: Failed to query for %v in namespace %v: %v", labelSelector, namespace, err) - } - - if (pods != nil && len(pods.Items) < 1) || pods == nil { - return nil, fmt.Errorf("GetFirstPodByLabelSelector: No pods found for query for %v in namespace %v: %v", labelSelector, namespace, err) - } - - return &pods.Items[0], nil -} - -func (c *Client) GetEventsFor(kind string, object metav1.Object) ([]v1.Event, error) { - client, err := c.GetClientset() - if err != nil { - return nil, err - } - selector := client.CoreV1().Events(object.GetNamespace()).GetFieldSelector( - pointer.ToString(object.GetName()), - pointer.ToString(object.GetNamespace()), - &kind, - pointer.ToString(string(object.GetUID()))) - events, err := client.CoreV1().Events(object.GetNamespace()).List(context.TODO(), metav1.ListOptions{ - FieldSelector: selector.String(), - }) - if err != nil { - return nil, err - } - return events.Items, nil -} - -func (c *Client) GetHealth() Health { - health := Health{} - client, err := c.GetClientset() - if err != nil { - return Health{Error: err} - } - pods, err := client.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return Health{Error: err} - } - - for _, pod := range pods.Items { - if IsDeleted(&pod) { - continue - } - if pod.Spec.Priority != nil && *pod.Spec.Priority < 0 { - continue - } - - if IsPodCrashLoopBackoff(pod) { - health.CrashLoopBackOff++ - } else if IsPodHealthy(pod) { - health.RunningPods++ - } else if IsPodPending(pod) { - health.PendingPods++ - } else { - health.ErrorPods++ - } - } - return health -} diff --git a/k8s/kustomize/json6902.go b/k8s/kustomize/json6902.go deleted file mode 100644 index 36806fd..0000000 --- a/k8s/kustomize/json6902.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2019 The Kubernetes Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package kustomize contains helpers for working with embedded kustomize commands -package kustomize - -import ( - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/kustomize/pkg/ifc" - "sigs.k8s.io/kustomize/pkg/patch" -) - -// json6902 represents a json6902 patch -type json6902 struct { - // Target refers to a Kubernetes object that the json patch will be applied to - *patch.Target - - // Patch contain the json patch as a string - Patch string -} - -// json6902Slice is a slice of json6902 patches. -type json6902Slice []*json6902 - -// newJSON6902FromFile returns a json6902 patch from a file -func newJSON6902FromFile(f patch.Json6902, ldr ifc.Loader, file string) (*json6902, error) { - patch, err := ldr.Load(file) - if err != nil { - return nil, err - } - - return &json6902{ - Target: f.Target, - Patch: string(patch), - }, nil -} - -// filterByResource returns all the json6902 patches in the json6902Slice corresponding to a given resource -func (s *json6902Slice) filterByResource(namespace string, r *unstructured.Unstructured) json6902Slice { - var result json6902Slice - for _, p := range *s { - if p.Group == r.GroupVersionKind().Group && - p.Version == r.GroupVersionKind().Version && - p.Kind == r.GroupVersionKind().Kind && - (p.Namespace == r.GetNamespace() || p.Namespace == namespace) && - p.Name == r.GetName() { - result = append(result, p) - } - } - return result -} diff --git a/k8s/kustomize/kustomize.go b/k8s/kustomize/kustomize.go deleted file mode 100644 index 26f2257..0000000 --- a/k8s/kustomize/kustomize.go +++ /dev/null @@ -1,284 +0,0 @@ -/* -Copyright 2019 The Kubernetes Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package kustomize contains helpers for working with embedded kustomize commands -package kustomize - -import ( - "bytes" - "fmt" - "io/ioutil" - "path/filepath" - osruntime "runtime" - "strings" - "sync" - - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - yamlutil "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/cli-runtime/pkg/kustomize" - "sigs.k8s.io/kustomize/pkg/constants" - "sigs.k8s.io/kustomize/pkg/fs" - "sigs.k8s.io/kustomize/pkg/ifc" - "sigs.k8s.io/kustomize/pkg/loader" - "sigs.k8s.io/kustomize/pkg/patch" - "sigs.k8s.io/kustomize/pkg/types" - "sigs.k8s.io/yaml" -) - -// Manager define a manager that allow access to kustomize capabilities -type Manager struct { - kustomizeDir string - kustomizationFile *types.Kustomization - strategicMergePatches strategicMergeSlice - json6902Patches json6902Slice -} - -var ( - lock = &sync.Mutex{} - instances = map[string]*Manager{} -) - -// GetManager return the KustomizeManager singleton instance -// NB. this is done at singleton instance level because kubeadm has a unique pool -// of patches that are applied to different content, at different time -func GetManager(kustomizeDir string) (*Manager, error) { - lock.Lock() - defer lock.Unlock() - - // if the instance does not exists, create it - if _, ok := instances[kustomizeDir]; !ok { - km := &Manager{ - kustomizeDir: kustomizeDir, - } - - // Create a loader that mimics the behavior of kubectl kustomize, including support for reading from - // a local folder or git repository like git@github.com:someOrg/someRepo.git or https://github.com/someOrg/someRepo?ref=someHash - // in order to do so you must use ldr.Root() instead of km.kustomizeDir and ldr.Load instead of other ways to read files - fSys := fs.MakeRealFS() - ldr, err := loader.NewLoader(km.kustomizeDir, fSys) - if err != nil { - return nil, err - } - defer ldr.Cleanup() // nolint: errcheck - - // read the Kustomization file and all the patches it is - // referencing (either stategicMerge or json6902 patches) - if err := km.loadFromKustomizationFile(ldr); err != nil { - return nil, err - } - - // if a Kustomization file was not found, kubeadm creates - // one using all the patches in the folder; however in this - // case only stategicMerge patches are supported - if km.kustomizationFile == nil { - km.kustomizationFile = &types.Kustomization{} - if err := km.loadFromFolder(ldr); err != nil { - return nil, err - } - } - - instances[kustomizeDir] = km - } - - return instances[kustomizeDir], nil -} - -// loadFromKustomizationFile reads a Kustomization file and all the patches it is -// referencing (either stategicMerge or json6902 patches) -func (km *Manager) loadFromKustomizationFile(ldr ifc.Loader) error { - // Kustomize support different KustomizationFileNames, so we try to read all - var content []byte - match := 0 - for _, kf := range constants.KustomizationFileNames { - c, err := ldr.Load(kf) - if err == nil { - match++ - content = c - } - } - - // if no kustomization file is found return - if match == 0 { - return nil - } - - // if more that one kustomization file is found, return error - if match > 1 { - return errors.Errorf("Found multiple kustomization files under: %s\n", ldr.Root()) - } - - // Decode the kustomization file - decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader(content), 1024) - var k = &types.Kustomization{} - if err := decoder.Decode(k); err != nil { - return errors.Wrap(err, "Error decoding kustomization file") - } - km.kustomizationFile = k - - // gets all the strategic merge patches - for _, f := range km.kustomizationFile.PatchesStrategicMerge { - smp, err := newStrategicMergeSliceFromFile(ldr, string(f)) - if err != nil { - return err - } - log.Tracef("Applying patch %s", f) - km.strategicMergePatches = append(km.strategicMergePatches, smp...) - } - - // gets all the json6902 patches - for _, f := range km.kustomizationFile.PatchesJson6902 { - jp, err := newJSON6902FromFile(f, ldr, f.Path) - if err != nil { - return err - } - km.json6902Patches = append(km.json6902Patches, jp) - } - - return nil -} - -// loadFromFolder returns all the stategicMerge patches in a folder -func (km *Manager) loadFromFolder(ldr ifc.Loader) error { - files, err := ioutil.ReadDir(ldr.Root()) - if err != nil { - return err - } - for _, fileInfo := range files { - if fileInfo.IsDir() { - continue - } - - smp, err := newStrategicMergeSliceFromFile(ldr, fileInfo.Name()) - if err != nil { - return err - } - km.strategicMergePatches = append(km.strategicMergePatches, smp...) - } - return nil -} - -// Kustomize apply a set of patches to a resource. -// Portions of the kustomize logic in this function are taken from the kubernetes-sigs/kind project -func (km *Manager) Kustomize(namespace string, data []byte) ([]runtime.Object, error) { - raw, err := getUnstructuredObjects(data) - var kustomized []runtime.Object - if err != nil { - return nil, err - } - - for _, _resource := range raw { - resource := _resource.(*unstructured.Unstructured) - - if resource == nil { - continue - } - - // get patches corresponding to this resource - strategicMerge := km.strategicMergePatches.filterByResource(namespace, resource) - json6902 := km.json6902Patches.filterByResource(namespace, resource) - - // if there are no patches, for the target resources, exit - patchesCnt := len(strategicMerge) + len(json6902) - - if patchesCnt == 0 { - kustomized = append(kustomized, resource) - continue - } - log.Infof("[kustomize] Applying %d patches to %s Resource=%s/%s", patchesCnt, resource.GroupVersionKind(), resource.GetNamespace(), resource.GetName()) - - // create an in memory fs to use for the kustomization - memFS := fs.MakeFakeFS() - - fakeDir := "/" - // for Windows we need this to be a drive because kustomize uses filepath.Abs() - // which will add a drive letter if there is none. which drive letter is - // unimportant as the path is on the fake filesystem anyhow - if osruntime.GOOS == "windows" { - fakeDir = `C:\` - } - - // writes the resource to a file in the temp file system - b, err := yaml.Marshal(resource) - if err != nil { - return nil, err - } - name := "resource.yaml" - memFS.WriteFile(filepath.Join(fakeDir, name), b) // nolint: errcheck - - km.kustomizationFile.Resources = []string{name} - - // writes strategic merge patches to files in the temp file system - km.kustomizationFile.PatchesStrategicMerge = []patch.StrategicMerge{} - for i, p := range strategicMerge { - b, err := yaml.Marshal(p) - if err != nil { - return nil, err - } - name := fmt.Sprintf("patch-%d.yaml", i) - memFS.WriteFile(filepath.Join(fakeDir, name), b) // nolint: errcheck - - km.kustomizationFile.PatchesStrategicMerge = append(km.kustomizationFile.PatchesStrategicMerge, patch.StrategicMerge(name)) - } - - // writes json6902 patches to files in the temp file system - km.kustomizationFile.PatchesJson6902 = []patch.Json6902{} - for i, p := range json6902 { - name := fmt.Sprintf("patchjson-%d.yaml", i) - memFS.WriteFile(filepath.Join(fakeDir, name), []byte(p.Patch)) // nolint: errcheck - - km.kustomizationFile.PatchesJson6902 = append(km.kustomizationFile.PatchesJson6902, patch.Json6902{Target: p.Target, Path: name}) - } - - // writes the kustomization file to the temp file system - kbytes, err := yaml.Marshal(km.kustomizationFile) - if err != nil { - return nil, err - } - memFS.WriteFile(filepath.Join(fakeDir, "kustomization.yaml"), kbytes) // nolint: errcheck - - // Finally customize the target resource - var out bytes.Buffer - if err := kustomize.RunKustomizeBuild(&out, memFS, fakeDir); err != nil { - return nil, err - } - - objects, err := getUnstructuredObjects(out.Bytes()) - if err != nil { - return nil, err - } - kustomized = append(kustomized, objects...) - } - return kustomized, nil -} - -func getUnstructuredObjects(data []byte) ([]runtime.Object, error) { - var items []runtime.Object - - for _, chunk := range strings.Split(string(data), "---\n") { - if strings.TrimSpace(chunk) == "" { - continue - } - decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(chunk)), 1024) - var resource *unstructured.Unstructured - - if err := decoder.Decode(&resource); err != nil { - return nil, fmt.Errorf("error decoding %s: %s", chunk, err) - } - items = append(items, resource) - } - - return items, nil -} diff --git a/k8s/kustomize/strategicmerge.go b/k8s/kustomize/strategicmerge.go deleted file mode 100644 index b8b0dbd..0000000 --- a/k8s/kustomize/strategicmerge.go +++ /dev/null @@ -1,136 +0,0 @@ -/* -Copyright 2019 The Kubernetes Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package kustomize - -import ( - "bytes" - "encoding/json" - "io" - "strings" - - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/yaml" - "sigs.k8s.io/kustomize/pkg/ifc" -) - -// strategicMergeSlice is a slice of strategic merge patches. -// Unstructured objects are used to represent strategic merge patches of any group/version/kind. -type strategicMergeSlice []*unstructured.Unstructured - -// newStrategicMergeSliceFromFile returns a slice of strategic merge patches from a file -func newStrategicMergeSliceFromFile(loader ifc.Loader, path string) (strategicMergeSlice, error) { - content, err := loader.Load(path) - if err != nil { - return nil, errors.Wrapf(err, "load from path %q failed", path) - } - res, err := newStrategicMergeSliceFromBytes(content) - if err != nil { - return nil, errors.Wrapf(err, "convert %q to Unstructured failed", path) - } - return res, nil -} - -// newStrategicMergeSliceFromBytes returns a strategic merge patches contained in a []byte. -// This functions handles all the nuances of Kubernetes yaml (e.g. many yaml -// documents in one file, List of objects) -func newStrategicMergeSliceFromBytes(in []byte) (strategicMergeSlice, error) { - decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024) - var result strategicMergeSlice - var err error - // Parse all the yaml documents in the file - for err == nil || isEmptyYamlError(err) { - var u unstructured.Unstructured - err = decoder.Decode(&u) - // if the yaml document is a valid unstructured object - if err == nil { - // it the unstructured object is empty, move to the next - if len(u.Object) == 0 { - continue - } - - // validate the object has kind, metadata.name as required by Kustomize - if err := validate(u); err != nil { - return nil, err - } - - // if the document is a list of objects - if strings.HasSuffix(u.GetKind(), "List") { - // for each item in the list of objects - if err := u.EachListItem(func(item runtime.Object) error { - // Marshal the object - itemJSON, err := json.Marshal(item) - if err != nil { - return err - } - - // Get the strategicMergeSlice for the item - itemU, err := newStrategicMergeSliceFromBytes(itemJSON) - if err != nil { - return err - } - - // append the strategicMergeSlice for the item to the strategicMergeSlice - result = append(result, itemU...) - - return nil - }); err != nil { - return nil, err - } - - continue - } - - // append the object to the stategicMergeSlice - result = append(result, &u) - } - } - if err != io.EOF { - return nil, err - } - return result, nil -} - -// filterByResource returns all the strategic merge patches in the strategicMergeSlice corresponding to a given resource -func (s *strategicMergeSlice) filterByResource(namespace string, r *unstructured.Unstructured) strategicMergeSlice { - var result strategicMergeSlice - for _, p := range *s { - if p.GroupVersionKind() == r.GroupVersionKind() && - (p.GetNamespace() == r.GetNamespace() || p.GetNamespace() == namespace) && - p.GetName() == r.GetName() { - result = append(result, p) - } - } - return result -} - -// validate validates that u has kind and name -// except for kind `List`, which doesn't require a name -func validate(u unstructured.Unstructured) error { - kind := u.GetKind() - if kind == "" { - return errors.New("missing kind in object") - } else if strings.HasSuffix(kind, "List") { - return nil - } - if u.GetName() == "" { - return errors.New("missing metadata.name in object") - } - return nil -} - -func isEmptyYamlError(err error) bool { - return strings.Contains(err.Error(), "is missing in 'null'") -} diff --git a/k8s/template_manager.go b/k8s/template_manager.go index 2059eb1..18ed828 100644 --- a/k8s/template_manager.go +++ b/k8s/template_manager.go @@ -6,21 +6,19 @@ import ( "fmt" "regexp" "strings" + "text/template" + "github.com/flanksource/kommons" templatev1 "github.com/flanksource/template-operator/api/v1" - "github.com/ghodss/yaml" "github.com/go-logr/logr" - - "text/template" - "github.com/hairyhenderson/gomplate/v3" - "github.com/pkg/errors" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" + "sigs.k8s.io/yaml" ) var ( @@ -29,7 +27,7 @@ var ( ) type TemplateManager struct { - Client *Client + Client *kommons.Client kubernetes.Interface Log logr.Logger PatchApplier *PatchApplier @@ -43,7 +41,7 @@ type ResourcePatch struct { PatchType PatchType } -func NewTemplateManager(c *Client, log logr.Logger) *TemplateManager { +func NewTemplateManager(c *kommons.Client, log logr.Logger) *TemplateManager { clientset, _ := c.GetClientset() tm := &TemplateManager{ Client: c, @@ -143,7 +141,7 @@ func (tm *TemplateManager) Run(ctx context.Context, template *templatev1.Templat return err } - objs, err := GetUnstructuredObjects(data) + objs, err := kommons.GetUnstructuredObjects(data) if err != nil { return nil } diff --git a/k8s/types.go b/k8s/types.go deleted file mode 100644 index 444e441..0000000 --- a/k8s/types.go +++ /dev/null @@ -1,29 +0,0 @@ -package k8s - -import ( - "k8s.io/apimachinery/pkg/runtime/schema" -) - -type CRD struct { - Kind string `yaml:"kind,omitempty"` - APIVersion string `yaml:"apiVersion,omitempty"` - Metadata Metadata `yaml:"metadata,omitempty"` - Spec map[string]interface{} `yaml:"spec,omitempty"` -} - -type Metadata struct { - Name string `yaml:"name,omitempty"` - Namespace string `yaml:"namespace,omitempty"` - Labels map[string]string `yaml:"labels,omitempty"` - Annotations map[string]string `yaml:"annotations,omitempty"` -} - -type DynamicKind struct { - APIVersion, Kind string -} - -func (dk DynamicKind) SetGroupVersionKind(gvk schema.GroupVersionKind) {} - -func (dk DynamicKind) GroupVersionKind() schema.GroupVersionKind { - return schema.FromAPIVersionAndKind(dk.APIVersion, dk.Kind) -} diff --git a/k8s/utils.go b/k8s/utils.go deleted file mode 100644 index 9b9a2e0..0000000 --- a/k8s/utils.go +++ /dev/null @@ -1,340 +0,0 @@ -package k8s - -import ( - "bytes" - "context" - "fmt" - "strings" - "time" - - "github.com/flanksource/commons/console" - log "github.com/sirupsen/logrus" - apps "k8s.io/api/apps/v1" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - yamlutil "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/clientcmd" -) - -func GetValidName(name string) string { - return strings.ReplaceAll(name, "_", "-") -} - -func WaitForNamespace(client kubernetes.Interface, ns string, timeout time.Duration) { - pods := client.CoreV1().Pods(ns) - start := time.Now() - for { - ready := 0 - pending := 0 - list, _ := pods.List(context.TODO(), metav1.ListOptions{}) - for _, pod := range list.Items { - conditions := true - for _, condition := range pod.Status.Conditions { - if condition.Status == v1.ConditionFalse { - conditions = false - } - } - if conditions && (pod.Status.Phase == v1.PodRunning || pod.Status.Phase == v1.PodSucceeded) { - ready++ - } else { - pending++ - } - } - if ready > 0 && pending == 0 { - return - } - log.Debugf("ns/%s: ready=%d, pending=%d", ns, ready, pending) - if start.Add(timeout).Before(time.Now()) { - log.Warnf("ns/%s: ready=%d, pending=%d", ns, ready, pending) - return - } - time.Sleep(10 * time.Second) - } -} - -func NewDeployment(ns, name, image string, labels map[string]string, port int32, args ...string) *apps.Deployment { - if labels == nil { - labels = make(map[string]string) - } - if len(labels) == 0 { - labels["app"] = name - } - replicas := int32(1) - - deployment := apps.Deployment{ - ObjectMeta: NewObjectMeta(ns, name), - Spec: apps.DeploymentSpec{ - Replicas: &replicas, - Selector: &metav1.LabelSelector{ - MatchLabels: labels, - }, - Template: v1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: labels, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: name, - Image: image, - ImagePullPolicy: "IfNotPresent", - Ports: []v1.ContainerPort{ - v1.ContainerPort{ - ContainerPort: port, - }, - }, - Args: args, - Resources: LowResourceRequirements(), - }, - }, - }, - }, - }, - } - deployment.Kind = "Deployment" - deployment.APIVersion = "apps/v1" - return &deployment -} - -func NewObjectMeta(ns, name string) metav1.ObjectMeta { - return metav1.ObjectMeta{ - Name: name, - Namespace: ns, - } -} - -func LowResourceRequirements() v1.ResourceRequirements { - return v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("512Mi"), - v1.ResourceCPU: resource.MustParse("500m"), - }, - Requests: v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("128Mi"), - v1.ResourceCPU: resource.MustParse("10m"), - }, - } -} - -func IsPodCrashLoopBackoff(pod v1.Pod) bool { - for _, status := range pod.Status.ContainerStatuses { - if status.State.Waiting != nil && status.State.Waiting.Reason == "CrashLoopBackOff" { - return true - } - } - return false -} - -func maxTime(t1 *time.Time, t2 time.Time) *time.Time { - if t1 == nil { - return &t2 - } - if t1.Before(t2) { - return &t2 - } - return t1 -} - -func GetPodStatus(pod v1.Pod) string { - if IsPodCrashLoopBackoff(pod) { - return "CrashLoopBackOff" - } - if pod.Status.Phase == v1.PodFailed { - return "Failed" - } - if pod.DeletionTimestamp != nil && !pod.DeletionTimestamp.IsZero() { - return "Terminating" - } - return string(pod.Status.Phase) -} - -func GetLastRestartTime(pod v1.Pod) *time.Time { - var max *time.Time - for _, status := range pod.Status.ContainerStatuses { - if status.LastTerminationState.Terminated != nil { - max = maxTime(max, status.LastTerminationState.Terminated.FinishedAt.Time) - } - } - return max -} - -func GetContainerStatus(pod v1.Pod) string { - if IsPodHealthy(pod) { - return "" - } - msg := "" - for _, status := range pod.Status.ContainerStatuses { - if status.State.Terminated != nil { - terminated := status.State.Terminated - msg += fmt.Sprintf("%s exit(%s):, %s %s", console.Bluef(status.Name), console.Redf("%d", terminated.ExitCode), terminated.Reason, console.DarkF(terminated.Message)) - } else if status.LastTerminationState.Terminated != nil { - terminated := status.LastTerminationState.Terminated - msg += fmt.Sprintf("%s exit(%s): %s %s", console.Bluef(status.Name), console.Redf("%d", terminated.ExitCode), terminated.Reason, console.DarkF(terminated.Message)) - } - } - return msg -} - -func IsPodHealthy(pod v1.Pod) bool { - if pod.Status.Phase == v1.PodSucceeded { - for _, status := range pod.Status.ContainerStatuses { - if status.State.Terminated != nil && status.State.Terminated.ExitCode != 0 { - return false - } - } - return true - } - - if pod.Status.Phase == v1.PodFailed || IsPodCrashLoopBackoff(pod) { - return false - } - - for _, condition := range pod.Status.Conditions { - if condition.Status == v1.ConditionFalse { - return false - } - } - - return pod.Status.Phase == v1.PodRunning -} - -func IsPodFinished(pod v1.Pod) bool { - return pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed -} - -func IsPodPending(pod v1.Pod) bool { - return pod.Status.Phase == v1.PodPending -} - -func IsPodReady(pod v1.Pod) bool { - for _, condition := range pod.Status.Conditions { - if condition.Type == v1.PodReady && condition.Status == v1.ConditionTrue { - return true - } - } - return false -} - -func IsMasterNode(node v1.Node) bool { - _, ok := node.Labels["node-role.kubernetes.io/master"] - return ok -} - -func IsDeleted(object metav1.Object) bool { - return object.GetDeletionTimestamp() != nil && !object.GetDeletionTimestamp().IsZero() -} - -func IsPodDaemonSet(pod v1.Pod) bool { - controllerRef := metav1.GetControllerOf(&pod) - return controllerRef != nil && controllerRef.Kind == apps.SchemeGroupVersion.WithKind("DaemonSet").Kind -} - -// IsStaticPod returns true if the pod is static i.e. declared in /etc/kubernetes/manifests and read directly by the kubelet -func IsStaticPod(pod v1.Pod) bool { - for _, owner := range pod.GetOwnerReferences() { - if owner.Kind == "Node" { - return true - } - } - return false -} - -func GetNodeStatus(node v1.Node) string { - s := "" - for _, condition := range node.Status.Conditions { - if condition.Status == v1.ConditionFalse { - continue - } - if s != "" { - s += ", " - } - s += string(condition.Type) - } - return s -} - -type Health struct { - RunningPods, PendingPods, ErrorPods, CrashLoopBackOff int - ReadyNodes, UnreadyNodes int - Error error -} - -func (h Health) GetNonReadyPods() int { - return h.PendingPods + h.ErrorPods + h.CrashLoopBackOff -} - -func (h Health) IsDegradedComparedTo(h2 Health, tolerance int) bool { - if h.GetNonReadyPods()-h2.GetNonReadyPods() > tolerance { - return true - } - if h2.RunningPods-h.RunningPods > tolerance { - return true - } - if h.UnreadyNodes-h2.UnreadyNodes > 0 { - return true - } - - return false -} - -func (h Health) String() string { - return fmt.Sprintf("pods(running=%d, pending=%s, crashloop=%s, error=%s) nodes(ready=%d, notready=%s)", - h.RunningPods, console.Yellowf("%d", h.PendingPods), console.Redf("%d", h.CrashLoopBackOff), console.Redf("%d", h.ErrorPods), h.ReadyNodes, console.Redf("%d", h.UnreadyNodes)) -} - -func GetUnstructuredObjects(data []byte) ([]unstructured.Unstructured, error) { - var items []unstructured.Unstructured - for _, chunk := range strings.Split(string(data), "---\n") { - if strings.TrimSpace(chunk) == "" { - continue - } - - decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(chunk)), 1024) - var resource *unstructured.Unstructured - - if err := decoder.Decode(&resource); err != nil { - return nil, fmt.Errorf("error decoding %s: %s", chunk, err) - } - if resource != nil { - items = append(items, *resource) - } - } - return items, nil -} - -// GetCurrentClusterNameFrom returns the name of the cluster associated with the currentContext of the -// specified kubeconfig file -func GetCurrentClusterNameFrom(kubeConfigPath string) string { - config, err := clientcmd.LoadFromFile(kubeConfigPath) - if err != nil { - return err.Error() - } - ctx, ok := config.Contexts[config.CurrentContext] - if !ok { - return fmt.Sprintf("invalid context name: %s", config.CurrentContext) - } - // we strip the prefix that kind automatically adds to cluster names - return strings.Replace(ctx.Cluster, "kind-", "", 1) -} - -func RemoveTaint(taints []v1.Taint, name string) []v1.Taint { - list := []v1.Taint{} - for _, taint := range taints { - if taint.Key != name { - list = append(list, taint) - } - } - return list -} - -func HasTaint(node v1.Node, name string) bool { - for _, taint := range node.Spec.Taints { - if taint.Key == name { - return true - } - } - return false -} diff --git a/k8s/walk.go b/k8s/walk.go deleted file mode 100644 index 2fe050a..0000000 --- a/k8s/walk.go +++ /dev/null @@ -1,64 +0,0 @@ -package k8s - -import ( - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/flanksource/commons/logger" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" -) - -type Specs []Spec -type Spec struct { - Path string - Items []unstructured.Unstructured -} - -// Walk iterates recursively over each file in path and -// returns all of the objects contained -func Walk(path string) (Specs, error) { - specs := Specs{} - err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - if strings.HasSuffix(path, "kustomization.yaml") || strings.HasSuffix(path, "kustomization.yml") { - return nil - } - if !strings.HasSuffix(path, ".yml") && !strings.HasSuffix(path, ".yaml") { - return nil - } - - data, err := ioutil.ReadFile(path) - if err != nil { - return err - } - items, err := GetUnstructuredObjects(data) - if err != nil { - logger.Errorf("Error decoding %s: %v", path, err) - return nil - } - specs = append(specs, Spec{ - Path: path, - Items: items, - }) - return nil - }) - - return specs, err -} - -func (specs Specs) FilterBy(kind string) []unstructured.Unstructured { - items := []unstructured.Unstructured{} - for _, spec := range specs { - for _, item := range spec.Items { - if strings.EqualFold(item.GetKind(), kind) { - items = append(items, item) - } - } - } - return items -} diff --git a/main.go b/main.go index 537f01d..6e44440 100644 --- a/main.go +++ b/main.go @@ -28,9 +28,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log/zap" "github.com/flanksource/commons/logger" + "github.com/flanksource/kommons" templatingflanksourcecomv1 "github.com/flanksource/template-operator/api/v1" "github.com/flanksource/template-operator/controllers" - "github.com/flanksource/template-operator/k8s" // +kubebuilder:scaffold:imports ) @@ -74,7 +74,7 @@ func main() { os.Exit(1) } - client := k8s.NewClient(mgr.GetConfig(), logger.NewLogger("client", "k8")) + client := kommons.NewClient(mgr.GetConfig(), logger.StandardLogger()) if err = (&controllers.TemplateReconciler{ Client: client, Log: ctrl.Log.WithName("controllers").WithName("Template"), From afa0789a8af3f41c285c19cca9ee0c85340f643d Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Thu, 19 Nov 2020 14:55:52 +0200 Subject: [PATCH 02/16] Add schema manager --- go.mod | 4 +- go.sum | 129 +++++++++++++++++++++++++++++++++ k8s/patches.go | 2 +- k8s/patches_test.go | 13 ++-- k8s/schema_manager.go | 144 +++++++++++++++++++++++++++++++++++++ k8s/schema_manager_test.go | 106 +++++++++++++++++++++++++++ main.go | 10 +-- 7 files changed, 394 insertions(+), 14 deletions(-) create mode 100644 k8s/schema_manager.go create mode 100644 k8s/schema_manager_test.go diff --git a/go.mod b/go.mod index 2c9f083..a489c42 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,11 @@ go 1.13 require ( github.com/flanksource/commons v1.4.3 - github.com/flanksource/kommons v0.1.5 + github.com/flanksource/kommons v0.1.6 github.com/go-logr/logr v0.3.0 github.com/go-logr/zapr v0.3.0 // indirect + github.com/go-openapi/jsonpointer v0.19.3 + github.com/go-openapi/spec v0.19.3 github.com/hairyhenderson/gomplate/v3 v3.6.0 github.com/onsi/ginkgo v1.12.1 github.com/onsi/gomega v1.10.1 diff --git a/go.sum b/go.sum index eba77c5..953f36b 100644 --- a/go.sum +++ b/go.sum @@ -29,6 +29,7 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= @@ -70,6 +71,8 @@ github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RP github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= +github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= @@ -79,6 +82,7 @@ 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/Shopify/ejson v1.2.1 h1:Dx0Ipn0mUgrZlzIa5oIUrH0rdSmBOyod/UJmQQK1KHo= github.com/Shopify/ejson v1.2.1/go.mod h1:J8cw5GOA0l/aMOPp+uDfwNYVbeqIaBhzRkv1+76UCvk= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= @@ -89,6 +93,7 @@ github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/g github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -118,6 +123,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/brancz/gojsontoyaml v0.0.0-20191212081931-bf2969bbd742/go.mod h1:IyUJYN1gvWjtLF5ZuygmxbnsAyP3aJS6cHzIuZY50B0= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -149,6 +155,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -170,6 +177,8 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKBAG3Klr9cn7N+LcYc82AZ2S7+cA= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad/go.mod h1:mPKfmRa823oBIgl2r20LeMSpTAteW5j7FLkc0vjmzyQ= +github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -193,6 +202,8 @@ github.com/flanksource/commons v1.4.3 h1:arEom5vkh5RrEWNy+kj32PmCbZ8d3OdZ0K7X7wQ github.com/flanksource/commons v1.4.3/go.mod h1:cGrz4qFi4NrP04vjMxv6DQk0SD0u6nnYppKpgFShj0c= github.com/flanksource/kommons v0.1.5 h1:1o8PyBNngemau4Q14NOkvXVqddqheOtDDELoVcRQtoc= github.com/flanksource/kommons v0.1.5/go.mod h1:Dc/oeDDXgybBm1LFr1iSAgARLCja8ep9K42Qouu+yPM= +github.com/flanksource/kommons v0.1.6 h1:VmYd/XjuqzQb3ICisTqOUpjzU4Gc08RZafJzFLXtFdA= +github.com/flanksource/kommons v0.1.6/go.mod h1:Dc/oeDDXgybBm1LFr1iSAgARLCja8ep9K42Qouu+yPM= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= @@ -204,6 +215,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/getkin/kin-openapi v0.30.0 h1:RAaggqVsRxj2t5vKDrOPcLxA9x8TBDDzYrStzFEHxt4= +github.com/getkin/kin-openapi v0.30.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -212,10 +225,13 @@ github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= @@ -230,6 +246,7 @@ github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-logr/zapr v0.3.0 h1:iyiCRZ29uPmbO7mWIjOEiYMXrTxZWTyK4tCatLyGpUY= github.com/go-logr/zapr v0.3.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= 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.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -250,6 +267,8 @@ github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg= +github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= @@ -264,19 +283,26 @@ github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsd github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/spec v0.19.14 h1:r4fbYFo6N4ZelmSX8G6p+cv/hZRXzcuqQIADGT1iNKM= +github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.11 h1:RFTu/dlFySpyVvJDfp/7674JY4SDglYWKztbiIGFpmc= +github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -284,8 +310,24 @@ github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 h1:28FVBuwkwowZMjbA github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -315,6 +357,21 @@ github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk= +github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= 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= @@ -331,6 +388,7 @@ github.com/google/go-replayers/grpcreplay v0.1.0 h1:eNb1y9rZFmY4ax45uEEECSa8fsxG github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= github.com/google/go-replayers/httpreplay v0.1.0 h1:AX7FUb4BjrrzNvblr/OlgwrmFiep6soj5K2QSDW7BGk= github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= @@ -343,6 +401,7 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= @@ -369,6 +428,7 @@ github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gosimple/slug v1.9.0 h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs= github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4vDJbg= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -412,6 +472,7 @@ github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqk github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= @@ -476,6 +537,7 @@ github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= @@ -493,6 +555,10 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT 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/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -506,7 +572,9 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -515,6 +583,7 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -532,6 +601,7 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= @@ -542,6 +612,7 @@ github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFW github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 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= @@ -557,13 +628,18 @@ github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= @@ -573,6 +649,7 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= @@ -587,6 +664,7 @@ github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTm github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -600,6 +678,7 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -631,6 +710,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA= +github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ= github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -645,10 +726,14 @@ github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shabbyrobe/gocovmerge v0.0.0-20180507124511-f6ea450bfb63 h1:J6qvD6rbmOil46orKqJaRPG+zTpoGlBTUdyv8ki63L0= github.com/shabbyrobe/gocovmerge v0.0.0-20180507124511-f6ea450bfb63/go.mod h1:n+VKSARF5y/tS9XFSP7vWDfS+GUC5vs/YT7M5XDTUEM= +github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= @@ -687,6 +772,7 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -712,10 +798,13 @@ github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jW 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.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws= github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= @@ -724,6 +813,7 @@ github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -736,7 +826,14 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok= github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= +github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vbauerster/mpb/v5 v5.0.3 h1:Ldt/azOkbThTk2loi6FrBd/3fhxGFQ24MxFAS88PoNY= github.com/vbauerster/mpb/v5 v5.0.3/go.mod h1:h3YxU5CSr8rZP4Q3xZPVB3jJLhWPou63lHEdr9ytH4Y= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= @@ -744,8 +841,10 @@ github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70 github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc= github.com/zealic/xignore v0.3.3 h1:EpLXUgZY/JEzFkTc+Y/VYypzXtNz+MSOMVCGW5Q4CKQ= github.com/zealic/xignore v0.3.3/go.mod h1:lhS8V7fuSOtJOKsvKI7WfsZE276/7AYEqokv3UiqEAU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -763,6 +862,8 @@ go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg= +go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= @@ -796,6 +897,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -829,9 +931,11 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -854,6 +958,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -910,6 +1015,8 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU= @@ -942,31 +1049,41 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190308174544-00c44ba9c14f/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/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-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/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-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh338oozWyiFsBRHtrflcws= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/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/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1060,6 +1177,7 @@ gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20190924164351-c8b7dadae555 h1:4Yrwvx9yMvZx+vK3wdX7aX2UCNZJJn0TDc+BNOJTE00= gopkg.in/yaml.v3 v3.0.0-20190924164351-c8b7dadae555/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.0 h1:d+tVGRu6X0ZBQ+kyAR8JKi6AXhTP2gmQaoIYaGFz634= @@ -1070,6 +1188,7 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= k8s.io/api v0.19.3 h1:GN6ntFnv44Vptj/b+OnMW7FmzkpDoIDLZRvKX3XH9aU= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= @@ -1077,6 +1196,7 @@ k8s.io/api v0.19.4 h1:I+1I4cgJYuCDgiLNjKx7SLmIbwgj9w7N7Zr5vSIdwpo= k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk= k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrqOzaMo= k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M= +k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= k8s.io/apimachinery v0.19.3 h1:bpIQXlKjB4cB/oNpnNnV+BybGPR7iP5oYpsOTEJ4hgc= k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= @@ -1099,6 +1219,7 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= @@ -1108,13 +1229,21 @@ k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE= sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= +sigs.k8s.io/kustomize v1.0.11 h1:Yb+6DDt9+aR2AvQApvUaKS/ugteeG4MPyoFeUHiPOjk= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= +sigs.k8s.io/kustomize/api v0.6.5 h1:xaAWZamIhpt9Y5Kn/vuBcBhZH8/m0zwew1d4HepIgXg= +sigs.k8s.io/kustomize/api v0.6.5/go.mod h1:Z96Z48h3nOWgVAmd4JGABszi5znhEnz7xoWHy+Bl7L4= +sigs.k8s.io/kustomize/kyaml v0.9.4/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw= +sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= diff --git a/k8s/patches.go b/k8s/patches.go index cdb4d09..6d7a475 100644 --- a/k8s/patches.go +++ b/k8s/patches.go @@ -52,7 +52,7 @@ func NewPatchApplier(clientset *kubernetes.Clientset, log logr.Logger) *PatchApp } func (p *PatchApplier) Apply(resource *unstructured.Unstructured, patchStr string, patchType PatchType) (*unstructured.Unstructured, error) { - fmt.Printf("Template patch:\n%s\n====\n", patchStr) + // fmt.Printf("Template patch:\n%s\n====\n", patchStr) t, err := template.New("patch").Funcs(p.FuncMap).Parse(patchStr) if err != nil { return nil, errors.Wrap(err, "failed to create template from patch") diff --git a/k8s/patches_test.go b/k8s/patches_test.go index 91b87a9..1bca71b 100644 --- a/k8s/patches_test.go +++ b/k8s/patches_test.go @@ -1,7 +1,6 @@ package k8s_test import ( - "fmt" "strings" "github.com/flanksource/template-operator/k8s" @@ -98,8 +97,8 @@ spec: - pod-info.1.2.3.4.nip.io secretName: podinfo-tls `) - fmt.Printf("Found:\n%s\n", foundYaml) - fmt.Printf("Expected:\n%s\n", expectedYaml) + // fmt.Printf("Found:\n%s\n", foundYaml) + // fmt.Printf("Expected:\n%s\n", expectedYaml) Expect(foundYaml).To(Equal(expectedYaml)) }) @@ -160,8 +159,8 @@ spec: protocol: TCP targetPort: "9376" `) - fmt.Printf("Found:\n%s\n", foundYaml) - fmt.Printf("Expected:\n%s\n", expectedYaml) + // fmt.Printf("Found:\n%s\n", foundYaml) + // fmt.Printf("Expected:\n%s\n", expectedYaml) Expect(foundYaml).To(Equal(expectedYaml)) }) @@ -227,8 +226,8 @@ metadata: namespace: example spec: {} `) - fmt.Printf("Found:\n%s\n", foundYaml) - fmt.Printf("Expected:\n%s\n", expectedYaml) + // fmt.Printf("Found:\n%s\n", foundYaml) + // fmt.Printf("Expected:\n%s\n", expectedYaml) Expect(foundYaml).To(Equal(expectedYaml)) }) }) diff --git a/k8s/schema_manager.go b/k8s/schema_manager.go new file mode 100644 index 0000000..0003594 --- /dev/null +++ b/k8s/schema_manager.go @@ -0,0 +1,144 @@ +package k8s + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/go-openapi/jsonpointer" + "github.com/go-openapi/spec" + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes" +) + +type SchemaManager struct { + swagger *spec.Swagger +} + +type TypedField struct { + Types []string + Format string +} + +func NewSchemaManager(clientset *kubernetes.Clientset) (*SchemaManager, error) { + bs, err := clientset.RESTClient().Get().AbsPath("openapi", "v2").DoRaw(context.TODO()) + if err != nil { + return nil, err + } + s := &spec.Swagger{} + if err := json.Unmarshal(bs, &s); err != nil { + return nil, err + } + + mgr := &SchemaManager{swagger: s} + return mgr, nil +} + +func (m *SchemaManager) FindTypeForKey(gvk schema.GroupVersionKind, key string) (*TypedField, error) { + schema, found, err := m.findSchemaForKind(gvk) + if err != nil { + return nil, errors.Wrapf(err, "error finding kind %v", gvk) + } + if !found { + return nil, errors.Errorf("kind %v not found", gvk) + } + + fieldType, err := m.findTypeForKey(schema, key) + if err != nil { + return nil, errors.Wrap(err, "failed to find type") + } + + typedField := &TypedField{Types: fieldType.Type, Format: fieldType.Format} + + return typedField, nil +} + +func (m *SchemaManager) findTypeForKey(schema *spec.Schema, key string) (*spec.Schema, error) { + parts := strings.SplitN(key, ".", 2) + fieldName := parts[0] + + fmt.Printf("key: %s\n", key) + fmt.Printf("type: %s\n", schema.Type) + + for k, _ := range schema.Properties { + fmt.Printf("Property: %s\n", k) + } + fmt.Println("=====") + + fieldSchema, found := schema.Properties[fieldName] + if !found { + return nil, errors.Errorf("failed to find property %s", fieldName) + } + + if len(parts) == 1 { + pointer := fieldSchema.Ref.GetPointer() + if pointer != nil && len(pointer.DecodedTokens()) > 0 { + f, err := m.resolvePointer(pointer) + if err != nil { + return nil, errors.Wrapf(err, "failed to resolve pointer %s", pointer) + } + return f, nil + } + return &fieldSchema, nil + } + + nextKey := parts[1] + var pointer *jsonpointer.Pointer + + // For array we need to remove index. Also schema is different. + if fieldSchema.Type.Contains("array") { + pointer = fieldSchema.Items.Schema.Ref.GetPointer() + parts := strings.SplitN(nextKey, ".", 2) + if len(parts) == 1 { + return nil, errors.Errorf("found array index as last element of key") + } + nextKey = parts[1] + } else { + pointer = fieldSchema.Ref.GetPointer() + } + if pointer != nil && len(pointer.DecodedTokens()) > 0 { + f, err := m.resolvePointer(pointer) + if err != nil { + return nil, errors.Wrapf(err, "failed to resolve pointer %s", pointer) + } + fieldSchema = *f + } + + return m.findTypeForKey(&fieldSchema, nextKey) +} + +func (m *SchemaManager) findSchemaForKind(gvk schema.GroupVersionKind) (*spec.Schema, bool, error) { + group := gvk.Group + version := gvk.Version + kind := gvk.Kind + if group == "" { + group = "core" + } + + definition := fmt.Sprintf("io.k8s.api.%s.%s.%s", group, version, kind) + if m.swagger.SwaggerProps.Definitions == nil { + return nil, false, fmt.Errorf("unexpected empty definitions") + } + value, ok := m.swagger.SwaggerProps.Definitions[definition] + return &value, ok, nil +} + +func (m *SchemaManager) resolvePointer(pointer *jsonpointer.Pointer) (*spec.Schema, error) { + tokens := pointer.DecodedTokens() + if len(tokens) != 2 { + return nil, errors.Errorf("could not resolve pointer: %v", tokens) + } + + if tokens[0] != "definitions" { + return nil, errors.Errorf("resolving pointer %v not supported", tokens) + } + + def, found := m.swagger.Definitions[tokens[1]] + if !found { + return nil, errors.Errorf("definition %s not found", tokens[1]) + } + + return &def, nil +} diff --git a/k8s/schema_manager_test.go b/k8s/schema_manager_test.go new file mode 100644 index 0000000..c887930 --- /dev/null +++ b/k8s/schema_manager_test.go @@ -0,0 +1,106 @@ +package k8s_test + +import ( + "io/ioutil" + "os" + "path" + + "github.com/flanksource/commons/logger" + "github.com/flanksource/kommons" + "github.com/flanksource/template-operator/k8s" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/util/homedir" +) + +var _ = Describe("SchemaManager", func() { + It("Returns int32 for Deployment. pec.replicas", func() { + schemaManager, err := k8s.NewSchemaManager(clientset()) + Expect(err).To(BeNil()) + gvk := schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "Deployment"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.replicas") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int32"})) + }) + + It("Returns string for Pod spec.dnsPolicy", func() { + schemaManager, err := k8s.NewSchemaManager(clientset()) + Expect(err).To(BeNil()) + gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.dnsPolicy") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) + }) + + It("Returns boolean for Pod spec.enableServiceLinks", func() { + schemaManager, err := k8s.NewSchemaManager(clientset()) + Expect(err).To(BeNil()) + gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.enableServiceLinks") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"boolean"}, Format: ""})) + }) + + It("Returns string for Ingress spec.rules.0.host", func() { + schemaManager, err := k8s.NewSchemaManager(clientset()) + Expect(err).To(BeNil()) + gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.host") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) + }) + + It("Returns string for Ingress spec.rules.0.http.paths.0.backend.serviceName", func() { + schemaManager, err := k8s.NewSchemaManager(clientset()) + Expect(err).To(BeNil()) + gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.http.paths.0.backend.serviceName") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) + }) + + It("Returns int32 for Ingress spec.rules.0.http.paths.0.backend.servicePort", func() { + schemaManager, err := k8s.NewSchemaManager(clientset()) + Expect(err).To(BeNil()) + gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.http.paths.0.backend.servicePort") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: "int-or-string"})) + }) +}) + +func clientset() *kubernetes.Clientset { + client := kommonsClient() + clientset, err := client.GetClientset() + if err != nil { + logger.Fatalf("failed to get clientset: %v", err) + } + return clientset +} + +func kommonsClient() *kommons.Client { + bytes, err := getKubeConfig() + if err != nil { + logger.Fatalf("failed to get kubeconfig: %v", err) + } + client, err := kommons.NewClientFromBytes(bytes) + if err != nil { + logger.Fatalf("failed to create kommons.Client: %v", err) + } + return client +} + +func getKubeConfig() ([]byte, error) { + if env := os.Getenv("KUBECONFIG"); env != "" { + return ioutil.ReadFile(env) + } + + if home := homedir.HomeDir(); home != "" { + return ioutil.ReadFile(path.Join(home, ".kube", "config")) + } + + return nil, errors.Errorf("failed to find kube config") +} diff --git a/main.go b/main.go index 6e44440..9c595d3 100644 --- a/main.go +++ b/main.go @@ -21,16 +21,15 @@ import ( "os" "time" + "github.com/flanksource/commons/logger" + "github.com/flanksource/kommons" + templatingflanksourcecomv1 "github.com/flanksource/template-operator/api/v1" + "github.com/flanksource/template-operator/controllers" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/log/zap" - - "github.com/flanksource/commons/logger" - "github.com/flanksource/kommons" - templatingflanksourcecomv1 "github.com/flanksource/template-operator/api/v1" - "github.com/flanksource/template-operator/controllers" // +kubebuilder:scaffold:imports ) @@ -75,6 +74,7 @@ func main() { } client := kommons.NewClient(mgr.GetConfig(), logger.StandardLogger()) + if err = (&controllers.TemplateReconciler{ Client: client, Log: ctrl.Log.WithName("controllers").WithName("Template"), From bdc2bb07fa963b6ad67d834ba87250ca071f9668 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Fri, 20 Nov 2020 13:31:22 +0200 Subject: [PATCH 03/16] Implement schema type getter for crds --- go.mod | 1 + go.sum | 54 +++++++++++++++++++ k8s/schema_manager.go | 104 ++++++++++++++++++++++++++++++------- k8s/schema_manager_test.go | 64 ++++++++++++++++++----- 4 files changed, 192 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index a489c42..a8f9afe 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5 // indirect gopkg.in/flanksource/yaml.v3 v3.1.1 k8s.io/api v0.19.4 + k8s.io/apiextensions-apiserver v0.19.4 k8s.io/apimachinery v0.19.4 k8s.io/cli-runtime v0.19.3 k8s.io/client-go v12.0.0+incompatible diff --git a/go.sum b/go.sum index 953f36b..c77222b 100644 --- a/go.sum +++ b/go.sum @@ -69,6 +69,7 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190605020000-c4ba1fdf4d36/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= @@ -91,7 +92,9 @@ github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4Rq github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= @@ -105,6 +108,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= 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/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= @@ -117,9 +121,12 @@ github.com/aws/aws-sdk-go v1.29.25/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTg 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= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= @@ -128,7 +135,10 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT github.com/brancz/gojsontoyaml v0.0.0-20191212081931-bf2969bbd742/go.mod h1:IyUJYN1gvWjtLF5ZuygmxbnsAyP3aJS6cHzIuZY50B0= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -230,6 +240,7 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 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-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -251,9 +262,11 @@ github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70t github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5 h1:8b2ZgKfKIUTVQpTb77MoRDIMEIwvDVw40o3aOXdfYzI= github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY= github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= @@ -273,9 +286,11 @@ github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.4 h1:5I4CCSqoWzT+82bBkNIvmLc0UOsoKKQ4Fz+3VxOB7SY= github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4 h1:csnOgcgAiuGoM/Po7PEpKDoNulCcF3FGbSnbHfxgjMI= github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= @@ -289,6 +304,7 @@ github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeE github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.3 h1:eRfyY5SkaNJCAwmmMcADjY31ow9+N7MCLW7oRkbsINA= github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= @@ -301,10 +317,12 @@ github.com/go-openapi/swag v0.19.11 h1:RFTu/dlFySpyVvJDfp/7674JY4SDglYWKztbiIGFp github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.5 h1:QhCBKRYqZR+SKo4gl1lPhPahope8/RLt6EVgY8X80w0= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 h1:28FVBuwkwowZMjbA7M0wXsI6t3PYulRTMio3SO+eKCM= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -560,6 +578,7 @@ github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= 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.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -604,6 +623,8 @@ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -625,6 +646,7 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -636,6 +658,7 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= @@ -689,6 +712,8 @@ github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4 github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -701,6 +726,8 @@ github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7q github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= 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= @@ -709,6 +736,8 @@ github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNG github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA= github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= @@ -760,6 +789,7 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= @@ -850,10 +880,14 @@ github.com/zealic/xignore v0.3.3/go.mod h1:lhS8V7fuSOtJOKsvKI7WfsZE276/7AYEqokv3 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5 h1:Gqga3zA9tdAcfqobUGjSoCob5L3f8Dt5EuOp3ihNZko= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= @@ -918,6 +952,7 @@ golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMx golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 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/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -930,6 +965,7 @@ 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/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1030,8 +1066,10 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1069,6 +1107,7 @@ golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +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-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -1090,6 +1129,7 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/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-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5 h1:UaoXseXAWUJUcuJ2E2oczJdLxAJXL0lOmVaBl7kuk+I= golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= @@ -1149,6 +1189,7 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -1171,6 +1212,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= @@ -1182,10 +1224,12 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.0 h1:d+tVGRu6X0ZBQ+kyAR8JKi6AXhTP2gmQaoIYaGFz634= gotest.tools/v3 v3.0.0/go.mod h1:TUP+/YtXl/dp++T+SZ5v2zUmLVBHmptSb/ajDLCJ+3c= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-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.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= @@ -1196,6 +1240,8 @@ k8s.io/api v0.19.4 h1:I+1I4cgJYuCDgiLNjKx7SLmIbwgj9w7N7Zr5vSIdwpo= k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk= k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrqOzaMo= k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M= +k8s.io/apiextensions-apiserver v0.19.4 h1:D9ak9T012tb3vcGFWYmbQuj9SCC8YM4zhA4XZqsAQC4= +k8s.io/apiextensions-apiserver v0.19.4/go.mod h1:B9rpH/nu4JBCtuUp3zTTk8DEjZUupZTBEec7/2zNRYw= k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= k8s.io/apimachinery v0.19.3 h1:bpIQXlKjB4cB/oNpnNnV+BybGPR7iP5oYpsOTEJ4hgc= @@ -1203,15 +1249,21 @@ k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlm k8s.io/apimachinery v0.19.4 h1:+ZoddM7nbzrDCp0T3SWnyxqf8cbWPT2fkZImoyvHUG0= k8s.io/apimachinery v0.19.4/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg= +k8s.io/apiserver v0.19.4 h1:X40UuyVt6DcYWIh2olcePkyKO0LRJFvxWC0kLxYvkZU= +k8s.io/apiserver v0.19.4/go.mod h1:X8WRHCR1UGZDd7HpV0QDc1h/6VbbpAeAGyxSh8yzZXw= k8s.io/cli-runtime v0.19.3 h1:vZUTphJIvlh7+867cXiLmyzoCAuQdukbPLIad6eEajQ= k8s.io/cli-runtime v0.19.3/go.mod h1:q+l845i5/uWzcUpCrl+L4f3XLaJi8ZeLVQ/decwty0A= k8s.io/client-go v0.19.4 h1:85D3mDNoLF+xqpyE9Dh/OtrJDyJrSRKkHmDXIbEzer8= k8s.io/client-go v0.19.4/go.mod h1:ZrEy7+wj9PjH5VMBCuu/BDlvtUAku0oVFk4MmnW9mWA= k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= +k8s.io/code-generator v0.19.4/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14= +k8s.io/component-base v0.19.4 h1:HobPRToQ8KJ9ubRju6PUAk9I5V1GNMJZ4PyWbiWA0uI= +k8s.io/component-base v0.19.4/go.mod h1:ZzuSLlsWhajIDEkKF73j64Gz/5o0AgON08FgRbEPI70= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= @@ -1235,6 +1287,8 @@ mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZI pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9 h1:rusRLrDhjBp6aYtl9sGEvQJr6faoHoDLd0YcUBTZguI= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE= sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= sigs.k8s.io/kustomize v1.0.11 h1:Yb+6DDt9+aR2AvQApvUaKS/ugteeG4MPyoFeUHiPOjk= diff --git a/k8s/schema_manager.go b/k8s/schema_manager.go index 0003594..d10e7ae 100644 --- a/k8s/schema_manager.go +++ b/k8s/schema_manager.go @@ -9,12 +9,18 @@ import ( "github.com/go-openapi/jsonpointer" "github.com/go-openapi/spec" "github.com/pkg/errors" + extv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + extapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" ) type SchemaManager struct { - swagger *spec.Swagger + swagger *spec.Swagger + serverResources []*metav1.APIResourceList + clientset *kubernetes.Clientset + crdClient extapi.ApiextensionsV1beta1Interface } type TypedField struct { @@ -22,17 +28,28 @@ type TypedField struct { Format string } -func NewSchemaManager(clientset *kubernetes.Clientset) (*SchemaManager, error) { +func NewSchemaManager(clientset *kubernetes.Clientset, crdClient extapi.ApiextensionsV1beta1Interface) (*SchemaManager, error) { bs, err := clientset.RESTClient().Get().AbsPath("openapi", "v2").DoRaw(context.TODO()) if err != nil { return nil, err } s := &spec.Swagger{} + if err := json.Unmarshal(bs, &s); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to unmarshal openapi") + } + + serverResources, err := clientset.ServerResources() + if err != nil { + return nil, errors.Wrap(err, "failed to list server resources") } - mgr := &SchemaManager{swagger: s} + mgr := &SchemaManager{ + swagger: s, + serverResources: serverResources, + clientset: clientset, + crdClient: crdClient, + } return mgr, nil } @@ -59,13 +76,14 @@ func (m *SchemaManager) findTypeForKey(schema *spec.Schema, key string) (*spec.S parts := strings.SplitN(key, ".", 2) fieldName := parts[0] - fmt.Printf("key: %s\n", key) - fmt.Printf("type: %s\n", schema.Type) + // fmt.Printf("Schema: %v\n", schema) + // fmt.Printf("key: %s\n", key) + // fmt.Printf("type: %s\n", schema.Type) - for k, _ := range schema.Properties { - fmt.Printf("Property: %s\n", k) - } - fmt.Println("=====") + // for k, _ := range schema.Properties { + // fmt.Printf("Property: %s\n", k) + // } + // fmt.Println("=====") fieldSchema, found := schema.Properties[fieldName] if !found { @@ -94,6 +112,9 @@ func (m *SchemaManager) findTypeForKey(schema *spec.Schema, key string) (*spec.S if len(parts) == 1 { return nil, errors.Errorf("found array index as last element of key") } + if fieldSchema.Items.Schema != nil { + fieldSchema = *fieldSchema.Items.Schema + } nextKey = parts[1] } else { pointer = fieldSchema.Ref.GetPointer() @@ -110,19 +131,53 @@ func (m *SchemaManager) findTypeForKey(schema *spec.Schema, key string) (*spec.S } func (m *SchemaManager) findSchemaForKind(gvk schema.GroupVersionKind) (*spec.Schema, bool, error) { - group := gvk.Group - version := gvk.Version - kind := gvk.Kind - if group == "" { - group = "core" - } + definition := m.getDefinitionName(gvk) - definition := fmt.Sprintf("io.k8s.api.%s.%s.%s", group, version, kind) if m.swagger.SwaggerProps.Definitions == nil { return nil, false, fmt.Errorf("unexpected empty definitions") } - value, ok := m.swagger.SwaggerProps.Definitions[definition] - return &value, ok, nil + value, found := m.swagger.SwaggerProps.Definitions[definition] + + // CRD Types are present in server resources but the schema is empty + if !found || value.Properties == nil || len(value.Properties) == 0 { + return m.findSchemaForCrd(gvk) + } + + return &value, found, nil +} + +func (m *SchemaManager) findSchemaForCrd(gvk schema.GroupVersionKind) (*spec.Schema, bool, error) { + crds, err := m.crdClient.CustomResourceDefinitions().List(context.Background(), metav1.ListOptions{}) + if err != nil { + fmt.Printf("ERROR: %v\n", err) + return nil, false, errors.Wrap(err, "failed to list customresourcedefinitions") + } + + for _, crd := range crds.Items { + if crd.Spec.Group == gvk.Group && crd.Spec.Names.Kind == gvk.Kind && crd.Spec.Version == gvk.Version { + schema, err := m.parseCrdSchema(crd) + if err != nil { + return nil, false, errors.Wrap(err, "failed to parse crd schema") + } + return schema, true, nil + } + } + + return nil, false, errors.Errorf("schema for group=%s version=%s kind=%s not found", gvk.Group, gvk.Version, gvk.Kind) +} + +func (m *SchemaManager) parseCrdSchema(crd extv1beta1.CustomResourceDefinition) (*spec.Schema, error) { + bytes, err := json.Marshal(crd.Spec.Validation.OpenAPIV3Schema) + if err != nil { + return nil, errors.Wrap(err, "failed to encode crd schema to json") + } + + schema := &spec.Schema{} + if err := json.Unmarshal(bytes, schema); err != nil { + return nil, errors.Wrap(err, "failed to decode json into spec.Schema") + } + + return schema, nil } func (m *SchemaManager) resolvePointer(pointer *jsonpointer.Pointer) (*spec.Schema, error) { @@ -142,3 +197,14 @@ func (m *SchemaManager) resolvePointer(pointer *jsonpointer.Pointer) (*spec.Sche return &def, nil } + +func (m *SchemaManager) getDefinitionName(gvk schema.GroupVersionKind) string { + group := gvk.Group + version := gvk.Version + kind := gvk.Kind + if group == "" { + group = "core" + } + + return fmt.Sprintf("io.k8s.api.%s.%s.%s", group, version, kind) +} diff --git a/k8s/schema_manager_test.go b/k8s/schema_manager_test.go index c887930..34c5aea 100644 --- a/k8s/schema_manager_test.go +++ b/k8s/schema_manager_test.go @@ -11,6 +11,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/pkg/errors" + extapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" "k8s.io/client-go/util/homedir" @@ -18,8 +19,7 @@ import ( var _ = Describe("SchemaManager", func() { It("Returns int32 for Deployment. pec.replicas", func() { - schemaManager, err := k8s.NewSchemaManager(clientset()) - Expect(err).To(BeNil()) + schemaManager := newSchemaManager() gvk := schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "Deployment"} kind, err := schemaManager.FindTypeForKey(gvk, "spec.replicas") Expect(err).To(BeNil()) @@ -27,8 +27,7 @@ var _ = Describe("SchemaManager", func() { }) It("Returns string for Pod spec.dnsPolicy", func() { - schemaManager, err := k8s.NewSchemaManager(clientset()) - Expect(err).To(BeNil()) + schemaManager := newSchemaManager() gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} kind, err := schemaManager.FindTypeForKey(gvk, "spec.dnsPolicy") Expect(err).To(BeNil()) @@ -36,8 +35,7 @@ var _ = Describe("SchemaManager", func() { }) It("Returns boolean for Pod spec.enableServiceLinks", func() { - schemaManager, err := k8s.NewSchemaManager(clientset()) - Expect(err).To(BeNil()) + schemaManager := newSchemaManager() gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} kind, err := schemaManager.FindTypeForKey(gvk, "spec.enableServiceLinks") Expect(err).To(BeNil()) @@ -45,8 +43,7 @@ var _ = Describe("SchemaManager", func() { }) It("Returns string for Ingress spec.rules.0.host", func() { - schemaManager, err := k8s.NewSchemaManager(clientset()) - Expect(err).To(BeNil()) + schemaManager := newSchemaManager() gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.host") Expect(err).To(BeNil()) @@ -54,8 +51,7 @@ var _ = Describe("SchemaManager", func() { }) It("Returns string for Ingress spec.rules.0.http.paths.0.backend.serviceName", func() { - schemaManager, err := k8s.NewSchemaManager(clientset()) - Expect(err).To(BeNil()) + schemaManager := newSchemaManager() gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.http.paths.0.backend.serviceName") Expect(err).To(BeNil()) @@ -63,15 +59,46 @@ var _ = Describe("SchemaManager", func() { }) It("Returns int32 for Ingress spec.rules.0.http.paths.0.backend.servicePort", func() { - schemaManager, err := k8s.NewSchemaManager(clientset()) - Expect(err).To(BeNil()) + schemaManager := newSchemaManager() gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.http.paths.0.backend.servicePort") Expect(err).To(BeNil()) Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: "int-or-string"})) }) + + It("Returns integer for PostgresqlDB spec.replicas", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "db.flanksource.com", Version: "v1", Kind: "PostgresqlDB"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.replicas") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: ""})) + }) + + It("Returns integer/int64 for Canary spec.interval", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "canaries.flanksource.com", Version: "v1", Kind: "Canary"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.interval") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int64"})) + }) + + It("Returns integer/int64 for Canary spec.docker.0.expectedSize", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "canaries.flanksource.com", Version: "v1", Kind: "Canary"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.docker.0.expectedSize") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int64"})) + }) }) +func newSchemaManager() *k8s.SchemaManager { + sm, err := k8s.NewSchemaManager(clientset(), crdClient()) + if err != nil { + logger.Fatalf("failed to get schema manager: %v", err) + } + return sm +} + func clientset() *kubernetes.Clientset { client := kommonsClient() clientset, err := client.GetClientset() @@ -81,6 +108,19 @@ func clientset() *kubernetes.Clientset { return clientset } +func crdClient() extapi.ApiextensionsV1beta1Interface { + client := kommonsClient() + restConfig, err := client.GetRESTConfig() + if err != nil { + logger.Fatalf("failed to get rest config: %v", err) + } + crdClient, err := extapi.NewForConfig(restConfig) + if err != nil { + logger.Fatalf("failed to get extapi client: %v", err) + } + return crdClient +} + func kommonsClient() *kommons.Client { bytes, err := getKubeConfig() if err != nil { From d3440625489a28c0c3b20ecd48e6af655b5d9290 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Fri, 20 Nov 2020 14:12:55 +0200 Subject: [PATCH 04/16] Change API to allow for querying same schema multiple times --- k8s/schema_manager.go | 60 ++++++++++++++++++-------------------- k8s/schema_manager_test.go | 16 ++++++++++ 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/k8s/schema_manager.go b/k8s/schema_manager.go index d10e7ae..cea14d7 100644 --- a/k8s/schema_manager.go +++ b/k8s/schema_manager.go @@ -54,7 +54,7 @@ func NewSchemaManager(clientset *kubernetes.Clientset, crdClient extapi.Apiexten } func (m *SchemaManager) FindTypeForKey(gvk schema.GroupVersionKind, key string) (*TypedField, error) { - schema, found, err := m.findSchemaForKind(gvk) + schema, found, err := m.FindSchemaForKind(gvk) if err != nil { return nil, errors.Wrapf(err, "error finding kind %v", gvk) } @@ -62,13 +62,32 @@ func (m *SchemaManager) FindTypeForKey(gvk schema.GroupVersionKind, key string) return nil, errors.Errorf("kind %v not found", gvk) } - fieldType, err := m.findTypeForKey(schema, key) - if err != nil { - return nil, errors.Wrap(err, "failed to find type") + return m.FindTypeForKeyFromSchema(schema, key) +} + +func (m *SchemaManager) FindSchemaForKind(gvk schema.GroupVersionKind) (*spec.Schema, bool, error) { + definition := m.getDefinitionName(gvk) + + if m.swagger.SwaggerProps.Definitions == nil { + return nil, false, fmt.Errorf("unexpected empty definitions") + } + value, found := m.swagger.SwaggerProps.Definitions[definition] + + // CRD Types are present in server resources but the schema is empty + if !found || value.Properties == nil || len(value.Properties) == 0 { + return m.findSchemaForCrd(gvk) } - typedField := &TypedField{Types: fieldType.Type, Format: fieldType.Format} + return &value, found, nil +} + +func (m *SchemaManager) FindTypeForKeyFromSchema(schema *spec.Schema, key string) (*TypedField, error) { + fieldSchema, err := m.findTypeForKey(schema, key) + if err != nil { + return nil, errors.Wrapf(err, "failed to find type for key %s", key) + } + typedField := &TypedField{Types: fieldSchema.Type, Format: fieldSchema.Format} return typedField, nil } @@ -76,18 +95,13 @@ func (m *SchemaManager) findTypeForKey(schema *spec.Schema, key string) (*spec.S parts := strings.SplitN(key, ".", 2) fieldName := parts[0] - // fmt.Printf("Schema: %v\n", schema) - // fmt.Printf("key: %s\n", key) - // fmt.Printf("type: %s\n", schema.Type) - - // for k, _ := range schema.Properties { - // fmt.Printf("Property: %s\n", k) - // } - // fmt.Println("=====") - fieldSchema, found := schema.Properties[fieldName] if !found { - return nil, errors.Errorf("failed to find property %s", fieldName) + if schema.Type.Contains("object") && schema.AdditionalProperties.Schema != nil { + fieldSchema = *schema.AdditionalProperties.Schema + } else { + return nil, errors.Errorf("failed to find property %s", fieldName) + } } if len(parts) == 1 { @@ -130,22 +144,6 @@ func (m *SchemaManager) findTypeForKey(schema *spec.Schema, key string) (*spec.S return m.findTypeForKey(&fieldSchema, nextKey) } -func (m *SchemaManager) findSchemaForKind(gvk schema.GroupVersionKind) (*spec.Schema, bool, error) { - definition := m.getDefinitionName(gvk) - - if m.swagger.SwaggerProps.Definitions == nil { - return nil, false, fmt.Errorf("unexpected empty definitions") - } - value, found := m.swagger.SwaggerProps.Definitions[definition] - - // CRD Types are present in server resources but the schema is empty - if !found || value.Properties == nil || len(value.Properties) == 0 { - return m.findSchemaForCrd(gvk) - } - - return &value, found, nil -} - func (m *SchemaManager) findSchemaForCrd(gvk schema.GroupVersionKind) (*spec.Schema, bool, error) { crds, err := m.crdClient.CustomResourceDefinitions().List(context.Background(), metav1.ListOptions{}) if err != nil { diff --git a/k8s/schema_manager_test.go b/k8s/schema_manager_test.go index 34c5aea..bcd3142 100644 --- a/k8s/schema_manager_test.go +++ b/k8s/schema_manager_test.go @@ -89,6 +89,22 @@ var _ = Describe("SchemaManager", func() { Expect(err).To(BeNil()) Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int64"})) }) + + It("Returns string for Secret stringData.DATABASE_PORT", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"} + kind, err := schemaManager.FindTypeForKey(gvk, "stringData.DATABASE_PORT") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) + }) + + It("Returns string/byte for Secret data.PASSWORD", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"} + kind, err := schemaManager.FindTypeForKey(gvk, "data.PASSWORD") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: "byte"})) + }) }) func newSchemaManager() *k8s.SchemaManager { From 0873e4255b3f0a8dc12dc73d858de618dd23ec02 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Fri, 20 Nov 2020 18:28:32 +0200 Subject: [PATCH 05/16] Integrate schema manager into patch applier --- controllers/template_controller.go | 5 +- k8s/patches.go | 49 ++++-- k8s/patches_test.go | 26 +-- k8s/schema_manager.go | 274 ++++++++++++++++++++++++++++- k8s/schema_manager_test.go | 247 +++++++++++++++++--------- k8s/template_manager.go | 22 ++- 6 files changed, 508 insertions(+), 115 deletions(-) diff --git a/controllers/template_controller.go b/controllers/template_controller.go index 1df20db..6918230 100644 --- a/controllers/template_controller.go +++ b/controllers/template_controller.go @@ -58,7 +58,10 @@ func (r *TemplateReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { return reconcile.Result{}, err } - tm := k8s.NewTemplateManager(r.Client, log) + tm, err := k8s.NewTemplateManager(r.Client, log) + if err != nil { + return reconcile.Result{}, err + } if err := tm.Run(ctx, template); err != nil { return reconcile.Result{}, err } diff --git a/k8s/patches.go b/k8s/patches.go index 6d7a475..c530c4a 100644 --- a/k8s/patches.go +++ b/k8s/patches.go @@ -14,8 +14,10 @@ import ( "github.com/pkg/errors" "github.com/tidwall/gjson" fyaml "gopkg.in/flanksource/yaml.v3" + extapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/cli-runtime/pkg/kustomize" "k8s.io/client-go/kubernetes" "sigs.k8s.io/kustomize/pkg/fs" @@ -33,22 +35,29 @@ var ( ) type PatchApplier struct { - Clientset *kubernetes.Clientset - Log logr.Logger - FuncMap template.FuncMap + Clientset *kubernetes.Clientset + Log logr.Logger + FuncMap template.FuncMap + SchemaManager *SchemaManager } -func NewPatchApplier(clientset *kubernetes.Clientset, log logr.Logger) *PatchApplier { +func NewPatchApplier(clientset *kubernetes.Clientset, crdClient extapi.ApiextensionsV1beta1Interface, log logr.Logger) (*PatchApplier, error) { + schemaManager, err := NewSchemaManager(clientset, crdClient) + if err != nil { + return nil, errors.Wrap(err, "failed to create schema manager") + } + p := &PatchApplier{ - Clientset: clientset, - Log: log, + Clientset: clientset, + Log: log, + SchemaManager: schemaManager, } p.FuncMap = template.FuncMap{ "kget": p.KGet, "jsonPath": p.JSONPath, } - return p + return p, nil } func (p *PatchApplier) Apply(resource *unstructured.Unstructured, patchStr string, patchType PatchType) (*unstructured.Unstructured, error) { @@ -87,6 +96,18 @@ func (p *PatchApplier) Apply(resource *unstructured.Unstructured, patchStr strin kustomizationFile := &types.Kustomization{Resources: []string{name}} + version := resource.GetAPIVersion() + parts := strings.Split(version, "/") + var apiVersion, apiGroup string + if len(parts) == 1 { + apiGroup = "" + apiVersion = parts[0] + } else { + apiGroup = parts[0] + apiVersion = parts[1] + } + groupVersionKind := schema.GroupVersionKind{Group: apiGroup, Version: apiVersion, Kind: resource.GetKind()} + if patchType == PatchTypeYaml { finalPatch := map[string]interface{}{} templateBytes := tpl.Bytes() @@ -101,6 +122,10 @@ func (p *PatchApplier) Apply(resource *unstructured.Unstructured, patchStr strin patchObject.SetNamespace(resource.GetNamespace()) } + if err := p.SchemaManager.DuckType(groupVersionKind, patchObject); err != nil { + return nil, errors.Wrap(err, "failed to duck type object") + } + // writes strategic merge patches to files in the temp file system kustomizationFile.PatchesStrategicMerge = []patch.StrategicMerge{} b, err = yaml.Marshal(patchObject.Object) @@ -118,16 +143,6 @@ func (p *PatchApplier) Apply(resource *unstructured.Unstructured, patchStr strin memFS.WriteFile(filepath.Join(fakeDir, name), templateBytes) // nolint: errcheck // writes json patches to files in the temp file system - version := resource.GetAPIVersion() - parts := strings.Split(version, "/") - var apiVersion, apiGroup string - if len(parts) == 1 { - apiGroup = "" - apiVersion = parts[0] - } else { - apiGroup = parts[0] - apiVersion = parts[1] - } kustomizationFile.PatchesJson6902 = []patch.Json6902{ { Target: &patch.Target{ diff --git a/k8s/patches_test.go b/k8s/patches_test.go index 1bca71b..5c0a88d 100644 --- a/k8s/patches_test.go +++ b/k8s/patches_test.go @@ -1,6 +1,7 @@ package k8s_test import ( + "fmt" "strings" "github.com/flanksource/template-operator/k8s" @@ -63,9 +64,9 @@ var _ = Describe("Patches", func() { } ] ` - log := ctrl.Log.WithName("test") - patchApplier := k8s.NewPatchApplier(nil, log) + patchApplier, err := k8s.NewPatchApplier(clientset(), crdClient(), log) + Expect(err).ToNot(HaveOccurred()) patchApplier.FuncMap["kget"] = func(path, jsonPath string) string { return "1.2.3.4.nip.io" } @@ -132,18 +133,18 @@ spec: } ] ` - log := ctrl.Log.WithName("test") - patchApplier := k8s.NewPatchApplier(nil, log) + patchApplier, err := k8s.NewPatchApplier(clientset(), crdClient(), log) + Expect(err).ToNot(HaveOccurred()) patchApplier.FuncMap["kget"] = func(path, jsonPath string) string { return "1.2.3.4.nip.io" } newResource, err := patchApplier.Apply(resource, patch, k8s.PatchTypeJSON) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) specYaml, err := yaml.Marshal(newResource.Object) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) foundYaml := strings.TrimSpace(string(specYaml)) @@ -164,7 +165,7 @@ spec: Expect(foundYaml).To(Equal(expectedYaml)) }) - It("Merges annotations and labels", func() { + FIt("Merges annotations and labels", func() { resource := &unstructured.Unstructured{ Object: map[string]interface{}{ "kind": "Ingress", @@ -198,16 +199,17 @@ metadata: ` log := ctrl.Log.WithName("test") - patchApplier := k8s.NewPatchApplier(nil, log) + patchApplier, err := k8s.NewPatchApplier(clientset(), crdClient(), log) + Expect(err).ToNot(HaveOccurred()) patchApplier.FuncMap["kget"] = func(path, jsonPath string) string { return "1.2.3.4.nip.io" } newResource, err := patchApplier.Apply(resource, patch, k8s.PatchTypeYaml) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) specYaml, err := yaml.Marshal(newResource.Object) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) foundYaml := strings.TrimSpace(string(specYaml)) expectedYaml := strings.TrimSpace(` @@ -226,8 +228,8 @@ metadata: namespace: example spec: {} `) - // fmt.Printf("Found:\n%s\n", foundYaml) - // fmt.Printf("Expected:\n%s\n", expectedYaml) + fmt.Printf("Found:\n%s\n", foundYaml) + fmt.Printf("Expected:\n%s\n", expectedYaml) Expect(foundYaml).To(Equal(expectedYaml)) }) }) diff --git a/k8s/schema_manager.go b/k8s/schema_manager.go index cea14d7..f1386a7 100644 --- a/k8s/schema_manager.go +++ b/k8s/schema_manager.go @@ -4,6 +4,8 @@ import ( "context" "encoding/json" "fmt" + "reflect" + "strconv" "strings" "github.com/go-openapi/jsonpointer" @@ -12,6 +14,7 @@ import ( extv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" extapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" ) @@ -28,6 +31,8 @@ type TypedField struct { Format string } +type MapInterface map[string]interface{} + func NewSchemaManager(clientset *kubernetes.Clientset, crdClient extapi.ApiextensionsV1beta1Interface) (*SchemaManager, error) { bs, err := clientset.RESTClient().Get().AbsPath("openapi", "v2").DoRaw(context.TODO()) if err != nil { @@ -53,13 +58,127 @@ func NewSchemaManager(clientset *kubernetes.Clientset, crdClient extapi.Apiexten return mgr, nil } +func (m *SchemaManager) DuckType(gvk schema.GroupVersionKind, object *unstructured.Unstructured) error { + schema, found, err := m.FindSchemaForKind(gvk) + if err != nil { + return errors.Wrapf(err, "error finding kind %v", gvk) + } + if !found { + return errors.Errorf("kind %v does not exist", gvk) + } + + newObject, err := m.duckType(schema, object.Object, "") + if err != nil { + return errors.Wrap(err, "failed to duck type object") + } + object.Object = newObject.(map[string]interface{}) + return nil +} + +func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix string) (interface{}, error) { + fmt.Printf("Prefix: %s\n", prefix) + + v := reflect.ValueOf(object) + switch v.Kind() { + case reflect.Slice: + fmt.Println("Type is slice") + bytes, ok := object.([]byte) + if ok { + fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) + if err != nil { + return errors.Wrapf(err, "failed to find type for key %s", prefix), nil + } + return transformBytesToType(bytes, fieldType) + } + + array := object.([]interface{}) + newArray := make([]interface{}, len(array)) + for i, e := range array { + newPrefix := prefix + "." + strconv.Itoa(i) + res, err := m.duckType(schema, e, newPrefix) + if err != nil { + return nil, err + } + newArray[i] = res + } + return newArray, nil + case reflect.Map: + fmt.Println("Type is map") + oldMap := object.(map[string]interface{}) + newMap := make(map[string]interface{}) + for k, v := range oldMap { + newPrefix := prefix + "." + escapeDot(k) + if prefix == "" { + newPrefix = escapeDot(k) + } + res, err := m.duckType(schema, v, newPrefix) + if err != nil { + return nil, err + } + newMap[k] = res + } + return newMap, nil + case reflect.String: + fmt.Println("Type is string") + value := object.(string) + fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) + if err != nil { + return nil, errors.Wrapf(err, "failed to find type for key %s", prefix) + } + newValue, err := transformStringToType(value, fieldType) + fmt.Printf("New value for field %s is %s\n", prefix, newValue) + if err != nil { + return nil, errors.Wrapf(err, "failed to transform string to type %v", fieldType) + } + return newValue, nil + case reflect.Int, reflect.Int8, reflect.Int32, reflect.Int64: + fmt.Println("Type is int") + value := v.Int() + fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) + if err != nil { + return nil, errors.Wrapf(err, "failed to find type for key %s", prefix) + } + newValue, err := transformInt64ToType(value, fieldType) + if err != nil { + return nil, errors.Wrapf(err, "failed to transform string to type %v", fieldType) + } + return newValue, nil + case reflect.Uint, reflect.Uint8, reflect.Uint32, reflect.Uint64: + fmt.Println("Type is uint") + value := v.Uint() + fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) + if err != nil { + return nil, errors.Wrapf(err, "failed to find type for key %s", prefix) + } + newValue, err := transformUint64ToType(value, fieldType) + if err != nil { + return nil, errors.Wrapf(err, "failed to transform string to type %v", fieldType) + } + return newValue, nil + case reflect.Float32, reflect.Float64: + fmt.Println("Type is float") + value := int64(v.Float()) + fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) + if err != nil { + return nil, errors.Wrapf(err, "failed to find type for key %s", prefix) + } + newValue, err := transformInt64ToType(value, fieldType) + if err != nil { + return nil, errors.Wrapf(err, "failed to transform string to type %v", fieldType) + } + return newValue, nil + default: + return nil, errors.Errorf("Value for field %s for type %T could not be transformed: %d", prefix, v, v.Kind()) + } +} + func (m *SchemaManager) FindTypeForKey(gvk schema.GroupVersionKind, key string) (*TypedField, error) { schema, found, err := m.FindSchemaForKind(gvk) if err != nil { return nil, errors.Wrapf(err, "error finding kind %v", gvk) } if !found { - return nil, errors.Errorf("kind %v not found", gvk) + return nil, errors.Errorf("kind %v does not exiting", gvk) } return m.FindTypeForKeyFromSchema(schema, key) @@ -206,3 +325,156 @@ func (m *SchemaManager) getDefinitionName(gvk schema.GroupVersionKind) string { return fmt.Sprintf("io.k8s.api.%s.%s.%s", group, version, kind) } + +func transformStringToType(value string, fieldType *TypedField) (interface{}, error) { + switch fieldType.Format { + case "int8": + return strconv.ParseInt(value, 10, 8) + case "int32": + return strconv.Atoi(value) + case "int64": + return strconv.ParseInt(value, 10, 64) + case "uint8": + return strconv.ParseUint(value, 10, 8) + case "uint32": + return strconv.ParseUint(value, 10, 32) + case "uint64": + return strconv.ParseUint(value, 10, 64) + case "double": + return strconv.ParseFloat(value, 64) + case "byte": + return []byte(value), nil + } + + if contains(fieldType.Types, "string") { + return value, nil + } + + if contains(fieldType.Types, "integer") { + return strconv.Atoi(value) + } + + if contains(fieldType.Types, "boolean") { + return strconv.ParseBool(value) + } + + return nil, errors.Errorf("could not transform string value to types %v format %s", fieldType.Types, fieldType.Format) +} + +func transformFloatToType(value float64, fieldType *TypedField) (interface{}, error) { + switch fieldType.Format { + case "int8": + return strconv.ParseInt(strconv.FormatInt(int64(value), 10), 10, 8) + case "int32": + return strconv.ParseInt(strconv.FormatInt(int64(value), 10), 10, 32) + case "int64": + return value, nil + case "uint8": + return strconv.ParseUint(strconv.FormatInt(int64(value), 10), 10, 8) + case "uint32": + return strconv.ParseUint(strconv.FormatInt(int64(value), 10), 10, 32) + case "uint64": + return strconv.ParseUint(strconv.FormatInt(int64(value), 10), 10, 64) + } + + if contains(fieldType.Types, "integer") { + return strconv.Atoi(strconv.FormatInt(int64(value), 10)) + } + + if contains(fieldType.Types, "string") { + return strconv.FormatFloat(value, 'f', 6, 64), nil + } + + if contains(fieldType.Types, "boolean") { + return value != 0, nil + } + + return nil, errors.Errorf("could not transform float64 value to types %v format %s", fieldType.Types, fieldType.Format) +} + +func transformInt64ToType(value int64, fieldType *TypedField) (interface{}, error) { + switch fieldType.Format { + case "int8": + return strconv.ParseInt(strconv.FormatInt(value, 10), 10, 8) + case "int32": + return strconv.ParseInt(strconv.FormatInt(value, 10), 10, 32) + case "int64": + return value, nil + case "uint8": + return strconv.ParseUint(strconv.FormatInt(value, 10), 10, 8) + case "uint32": + return strconv.ParseUint(strconv.FormatInt(value, 10), 10, 32) + case "uint64": + return strconv.ParseUint(strconv.FormatInt(value, 10), 10, 64) + } + + if contains(fieldType.Types, "integer") { + return strconv.Atoi(strconv.FormatInt(value, 10)) + } + + if contains(fieldType.Types, "string") { + return strconv.FormatInt(value, 10), nil + } + + if contains(fieldType.Types, "boolean") { + return value != 0, nil + } + + return nil, errors.Errorf("could not transform int64 value to types %v format %s", fieldType.Types, fieldType.Format) +} + +func transformUint64ToType(value uint64, fieldType *TypedField) (interface{}, error) { + switch fieldType.Format { + case "int8": + return strconv.ParseInt(strconv.FormatUint(value, 10), 10, 8) + case "int32": + return strconv.ParseInt(strconv.FormatUint(value, 10), 10, 32) + case "int64": + return strconv.ParseUint(strconv.FormatUint(value, 10), 10, 64) + case "uint8": + return strconv.ParseUint(strconv.FormatUint(value, 10), 10, 8) + case "uint32": + return strconv.ParseUint(strconv.FormatUint(value, 10), 10, 32) + case "uint64": + return value, nil + } + + if contains(fieldType.Types, "integer") { + return strconv.Atoi(strconv.FormatUint(value, 10)) + } + + if contains(fieldType.Types, "string") { + return strconv.FormatUint(value, 10), nil + } + + if contains(fieldType.Types, "boolean") { + return value != 0, nil + } + + return nil, errors.Errorf("could not transform uint64 value to types %v format %s", fieldType.Types, fieldType.Format) +} + +func transformBytesToType(value []byte, fieldType *TypedField) (interface{}, error) { + if fieldType.Format == "byte" { + return value, nil + } + + if contains(fieldType.Types, "string") { + return string(value), nil + } + + return nil, errors.Errorf("could not transform []byte value to types %v format %s", fieldType.Types, fieldType.Format) +} + +func contains(slice []string, value string) bool { + for _, k := range slice { + if k == value { + return true + } + } + return false +} + +func escapeDot(s string) string { + return strings.ReplaceAll(s, ".", "_") +} diff --git a/k8s/schema_manager_test.go b/k8s/schema_manager_test.go index bcd3142..81c1f18 100644 --- a/k8s/schema_manager_test.go +++ b/k8s/schema_manager_test.go @@ -1,9 +1,12 @@ package k8s_test import ( + "fmt" "io/ioutil" "os" "path" + "reflect" + "strings" "github.com/flanksource/commons/logger" "github.com/flanksource/kommons" @@ -12,100 +15,182 @@ import ( . "github.com/onsi/gomega" "github.com/pkg/errors" extapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" "k8s.io/client-go/util/homedir" + "sigs.k8s.io/yaml" ) var _ = Describe("SchemaManager", func() { - It("Returns int32 for Deployment. pec.replicas", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "Deployment"} - kind, err := schemaManager.FindTypeForKey(gvk, "spec.replicas") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int32"})) + Describe("FindTypeForKey", func() { + It("Returns int32 for Deployment. pec.replicas", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "Deployment"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.replicas") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int32"})) + }) + + It("Returns string for Pod spec.dnsPolicy", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.dnsPolicy") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) + }) + + It("Returns boolean for Pod spec.enableServiceLinks", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.enableServiceLinks") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"boolean"}, Format: ""})) + }) + + It("Returns string for Ingress spec.rules.0.host", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.host") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) + }) + + It("Returns string for Ingress spec.rules.0.http.paths.0.backend.serviceName", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.http.paths.0.backend.serviceName") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) + }) + + It("Returns int32 for Ingress spec.rules.0.http.paths.0.backend.servicePort", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.http.paths.0.backend.servicePort") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: "int-or-string"})) + }) + + It("Returns integer for PostgresqlDB spec.replicas", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "db.flanksource.com", Version: "v1", Kind: "PostgresqlDB"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.replicas") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: ""})) + }) + + It("Returns integer/int64 for Canary spec.interval", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "canaries.flanksource.com", Version: "v1", Kind: "Canary"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.interval") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int64"})) + }) + + It("Returns integer/int64 for Canary spec.docker.0.expectedSize", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "canaries.flanksource.com", Version: "v1", Kind: "Canary"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.docker.0.expectedSize") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int64"})) + }) + + It("Returns string for Secret stringData.DATABASE_PORT", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"} + kind, err := schemaManager.FindTypeForKey(gvk, "stringData.DATABASE_PORT") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) + }) + + It("Returns string/byte for Secret data.PASSWORD", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"} + kind, err := schemaManager.FindTypeForKey(gvk, "data.PASSWORD") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: "byte"})) + }) }) - It("Returns string for Pod spec.dnsPolicy", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} - kind, err := schemaManager.FindTypeForKey(gvk, "spec.dnsPolicy") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) - }) - - It("Returns boolean for Pod spec.enableServiceLinks", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} - kind, err := schemaManager.FindTypeForKey(gvk, "spec.enableServiceLinks") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"boolean"}, Format: ""})) - }) - - It("Returns string for Ingress spec.rules.0.host", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} - kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.host") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) - }) - - It("Returns string for Ingress spec.rules.0.http.paths.0.backend.serviceName", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} - kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.http.paths.0.backend.serviceName") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) - }) - - It("Returns int32 for Ingress spec.rules.0.http.paths.0.backend.servicePort", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"} - kind, err := schemaManager.FindTypeForKey(gvk, "spec.rules.0.http.paths.0.backend.servicePort") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: "int-or-string"})) - }) - - It("Returns integer for PostgresqlDB spec.replicas", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "db.flanksource.com", Version: "v1", Kind: "PostgresqlDB"} - kind, err := schemaManager.FindTypeForKey(gvk, "spec.replicas") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: ""})) + Describe("DuckType", func() { + It("Encodes secret data if int correctly", func() { + value := ` +apiVersion: v1 +kind: Secret +metadata: + name: foo + namespace: bar +stringData: + Host: "localhost" + Port: 8080 +` + resource, err := duckTypeWithValue(value) + Expect(err).To(BeNil()) + + data, ok := resource.Object["stringData"].(map[string]interface{}) + Expect(ok).To(Equal(true)) + + Expect(reflect.TypeOf(data["Host"]).Kind()).To(Equal(reflect.String)) + Expect(reflect.TypeOf(data["Port"]).Kind()).To(Equal(reflect.String)) + }) + + It("Encodes Deployment replicas to int correctly", func() { + value := ` +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: foo + namespace: bar +spec: + replicas: "3" +` + resource, err := duckTypeWithValue(value) + Expect(err).ToNot(HaveOccurred()) + + expectedYaml := ` +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: foo + namespace: bar +spec: + replicas: 3 +` + yml, err := yaml.Marshal(resource.Object) + Expect(err).ToNot(HaveOccurred()) + + fmt.Printf("Expected:\n%v\n=======Actual:\n%v\n==========", expectedYaml, string(yml)) + Expect(strings.TrimSpace(string(yml))).To(Equal(strings.TrimSpace(expectedYaml))) + }) }) +}) - It("Returns integer/int64 for Canary spec.interval", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "canaries.flanksource.com", Version: "v1", Kind: "Canary"} - kind, err := schemaManager.FindTypeForKey(gvk, "spec.interval") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int64"})) - }) +func duckTypeWithValue(template string) (*unstructured.Unstructured, error) { + resource := &unstructured.Unstructured{} + if err := yaml.Unmarshal([]byte(template), &resource.Object); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal yaml") + } - It("Returns integer/int64 for Canary spec.docker.0.expectedSize", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "canaries.flanksource.com", Version: "v1", Kind: "Canary"} - kind, err := schemaManager.FindTypeForKey(gvk, "spec.docker.0.expectedSize") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"integer"}, Format: "int64"})) - }) + fmt.Printf("object:\n%v\n", resource.Object) + + version := resource.GetAPIVersion() + parts := strings.Split(version, "/") + var apiVersion, apiGroup string + if len(parts) == 1 { + apiGroup = "" + apiVersion = parts[0] + } else { + apiGroup = parts[0] + apiVersion = parts[1] + } - It("Returns string for Secret stringData.DATABASE_PORT", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"} - kind, err := schemaManager.FindTypeForKey(gvk, "stringData.DATABASE_PORT") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: ""})) - }) + groupVersionKind := schema.GroupVersionKind{Group: apiGroup, Version: apiVersion, Kind: resource.GetKind()} - It("Returns string/byte for Secret data.PASSWORD", func() { - schemaManager := newSchemaManager() - gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"} - kind, err := schemaManager.FindTypeForKey(gvk, "data.PASSWORD") - Expect(err).To(BeNil()) - Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: "byte"})) - }) -}) + mgr := newSchemaManager() + err := mgr.DuckType(groupVersionKind, resource) + return resource, err +} func newSchemaManager() *k8s.SchemaManager { sm, err := k8s.NewSchemaManager(clientset(), crdClient()) diff --git a/k8s/template_manager.go b/k8s/template_manager.go index 18ed828..36d8306 100644 --- a/k8s/template_manager.go +++ b/k8s/template_manager.go @@ -14,6 +14,7 @@ import ( "github.com/hairyhenderson/gomplate/v3" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" + extapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" @@ -41,14 +42,29 @@ type ResourcePatch struct { PatchType PatchType } -func NewTemplateManager(c *kommons.Client, log logr.Logger) *TemplateManager { +func NewTemplateManager(c *kommons.Client, log logr.Logger) (*TemplateManager, error) { clientset, _ := c.GetClientset() + + restConfig, err := c.GetRESTConfig() + if err != nil { + return nil, errors.Wrap(err, "failed to get rest config") + } + crdClient, err := extapi.NewForConfig(restConfig) + if err != nil { + return nil, errors.Wrap(err, "failed to create crd client") + } + + patchApplier, err := NewPatchApplier(clientset, crdClient, log) + if err != nil { + return nil, errors.Wrap(err, "faile to create patch applier") + } + tm := &TemplateManager{ Client: c, Log: log, - PatchApplier: NewPatchApplier(clientset, log), + PatchApplier: patchApplier, } - return tm + return tm, nil } func (tm *TemplateManager) selectResources(ctx context.Context, selector *templatev1.ResourceSelector) ([]unstructured.Unstructured, error) { From 0461b1c495d77b1d7a2eca719bb02f1a10591cf7 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Tue, 24 Nov 2020 10:36:01 +0200 Subject: [PATCH 06/16] Add rbac permissions for every object --- .../templating.flanksource.com_templates.yaml | 553 +++++++++--------- config/rbac/role.yaml | 46 +- controllers/template_controller.go | 6 +- 3 files changed, 280 insertions(+), 325 deletions(-) diff --git a/config/crd/bases/templating.flanksource.com_templates.yaml b/config/crd/bases/templating.flanksource.com_templates.yaml index dd2cdb3..4315dca 100644 --- a/config/crd/bases/templating.flanksource.com_templates.yaml +++ b/config/crd/bases/templating.flanksource.com_templates.yaml @@ -1,10 +1,10 @@ --- -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.2.5 + controller-gen.kubebuilder.io/version: v0.4.0 creationTimestamp: null name: templates.templating.flanksource.com spec: @@ -14,295 +14,294 @@ spec: listKind: TemplateList plural: templates singular: template - scope: Namespaced - validation: - openAPIV3Schema: - description: Template is the Schema for the templates API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: TemplateSpec defines the desired state of Template - properties: - jsonPatches: - items: + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Template is the Schema for the templates API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: TemplateSpec defines the desired state of Template + properties: + jsonPatches: + items: + properties: + object: + description: TypeMeta describes an individual object in an API + response or request with strings representing the type of + the object and its API schema version. Structures that are + versioned or persisted should inline TypeMeta. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of + this representation of an object. Servers should convert + recognized schemas to the latest internal value, and may + reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + type: object + patch: + type: string + type: object + type: array + onceoff: + description: Onceoff will not apply templating more than once (usually + at admission stage) + type: boolean + patchTarget: + description: Target optionally allows to lookup related resources + to patch, defaults to the source object selected properties: - object: - description: TypeMeta describes an individual object in an API - response or request with strings representing the type of the - object and its API schema version. Structures that are versioned - or persisted should inline TypeMeta. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this - representation of an object. Servers should convert recognized - schemas to the latest internal value, and may reject unrecognized - values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST - resource this object represents. Servers may infer this - from the endpoint the client submits requests to. Cannot - be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string + annotationSelector: + additionalProperties: + type: string type: object - patch: + apiVersion: type: string - type: object - type: array - onceoff: - description: Onceoff will not apply templating more than once (usually - at admission stage) - type: boolean - patchTarget: - description: Target optionally allows to lookup related resources to - patch, defaults to the source object selected - properties: - annotationSelector: - additionalProperties: + fieldSelector: type: string - type: object - apiVersion: - type: string - fieldSelector: - type: string - kind: - type: string - labelSelector: - description: A label selector is a label query over a set of resources. - The result of matchLabels and matchExpressions are ANDed. An empty - label selector matches all objects. A null label selector matches - no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: A label selector requirement is a selector that - contains values, a key, and an operator that relates the - key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of string values. If the - operator is In or NotIn, the values array must be non-empty. - If the operator is Exists or DoesNotExist, the values - array must be empty. This array is replaced during a - strategic merge patch. - items: + kind: + type: string + labelSelector: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An + empty label selector matches all objects. A null label selector + matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. type: string - type: array - required: - - key - - operator + values: + description: values is an array of string values. If + the operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A + single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is "key", + the operator is "In", and the values array contains only + "value". The requirements are ANDed. type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. A single - {key,value} in the matchLabels map is equivalent to an element - of matchExpressions, whose key field is "key", the operator - is "In", and the values array contains only "value". The requirements - are ANDed. - type: object - type: object - namespaceSelector: - description: A label selector is a label query over a set of resources. - The result of matchLabels and matchExpressions are ANDed. An empty - label selector matches all objects. A null label selector matches - no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: A label selector requirement is a selector that - contains values, a key, and an operator that relates the - key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of string values. If the - operator is In or NotIn, the values array must be non-empty. - If the operator is Exists or DoesNotExist, the values - array must be empty. This array is replaced during a - strategic merge patch. - items: + type: object + namespaceSelector: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An + empty label selector matches all objects. A null label selector + matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. type: string - type: array - required: - - key - - operator + values: + description: values is an array of string values. If + the operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A + single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is "key", + the operator is "In", and the values array contains only + "value". The requirements are ANDed. type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. A single - {key,value} in the matchLabels map is equivalent to an element - of matchExpressions, whose key field is "key", the operator - is "In", and the values array contains only "value". The requirements - are ANDed. - type: object - type: object - type: object - patches: - description: Patches is list of strategic merge patches to apply to - to the targets Must specify at least resources or patches or both - items: - type: string - type: array - resources: - description: Resources is a list of new resources to create for each - source object found Must specify at least resources or patches or - both - items: + type: object type: object - type: array - source: - description: Source selects objects on which to use as a templating - object - properties: - annotationSelector: - additionalProperties: - type: string - type: object - apiVersion: - type: string - fieldSelector: - type: string - kind: + patches: + description: Patches is list of strategic merge patches to apply to + to the targets Must specify at least resources or patches or both + items: type: string - labelSelector: - description: A label selector is a label query over a set of resources. - The result of matchLabels and matchExpressions are ANDed. An empty - label selector matches all objects. A null label selector matches - no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: A label selector requirement is a selector that - contains values, a key, and an operator that relates the - key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of string values. If the - operator is In or NotIn, the values array must be non-empty. - If the operator is Exists or DoesNotExist, the values - array must be empty. This array is replaced during a - strategic merge patch. - items: + type: array + resources: + description: Resources is a list of new resources to create for each + source object found Must specify at least resources or patches or + both + items: + type: object + type: array + source: + description: Source selects objects on which to use as a templating + object + properties: + annotationSelector: + additionalProperties: + type: string + type: object + apiVersion: + type: string + fieldSelector: + type: string + kind: + type: string + labelSelector: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An + empty label selector matches all objects. A null label selector + matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. type: string - type: array - required: - - key - - operator + values: + description: values is an array of string values. If + the operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A + single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is "key", + the operator is "In", and the values array contains only + "value". The requirements are ANDed. type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. A single - {key,value} in the matchLabels map is equivalent to an element - of matchExpressions, whose key field is "key", the operator - is "In", and the values array contains only "value". The requirements - are ANDed. - type: object - type: object - namespaceSelector: - description: A label selector is a label query over a set of resources. - The result of matchLabels and matchExpressions are ANDed. An empty - label selector matches all objects. A null label selector matches - no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: A label selector requirement is a selector that - contains values, a key, and an operator that relates the - key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of string values. If the - operator is In or NotIn, the values array must be non-empty. - If the operator is Exists or DoesNotExist, the values - array must be empty. This array is replaced during a - strategic merge patch. - items: + type: object + namespaceSelector: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An + empty label selector matches all objects. A null label selector + matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. type: string - type: array - required: - - key - - operator + values: + description: values is an array of string values. If + the operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A + single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is "key", + the operator is "In", and the values array contains only + "value". The requirements are ANDed. type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. A single - {key,value} in the matchLabels map is equivalent to an element - of matchExpressions, whose key field is "key", the operator - is "In", and the values array contains only "value". The requirements - are ANDed. - type: object - type: object - type: object - type: object - status: - description: TemplateStatus defines the observed state of Template - type: object - type: object - version: v1 - versions: - - name: v1 + type: object + type: object + type: object + status: + description: TemplateStatus defines the observed state of Template + type: object + type: object served: true storage: true status: diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index ef625f3..d34978e 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -7,48 +7,8 @@ metadata: name: manager-role rules: - apiGroups: - - "" + - '*' resources: - - configmaps + - '*' verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list - - watch -- apiGroups: - - extensions - resources: - - ingresses - verbs: - - get - - list - - patch - - update - - watch -- apiGroups: - - templating.flanksource.com - resources: - - templates - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - templating.flanksource.com - resources: - - templates/status - verbs: - - get - - patch - - update + - '*' diff --git a/controllers/template_controller.go b/controllers/template_controller.go index 6918230..58f2d6f 100644 --- a/controllers/template_controller.go +++ b/controllers/template_controller.go @@ -38,11 +38,7 @@ type TemplateReconciler struct { Scheme *runtime.Scheme } -// +kubebuilder:rbac:groups=templating.flanksource.com,resources=templates,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=templating.flanksource.com,resources=templates/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=extensions,resources=ingresses,verbs=get;list;watch;update;patch -// +kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch -// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch +// +kubebuilder:rbac:groups="*",resources="*",verbs="*" func (r *TemplateReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { ctx := context.Background() From 5ae5733acc06009d48079dae3be4b047cdbccd21 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Tue, 24 Nov 2020 11:40:23 +0200 Subject: [PATCH 07/16] Remove debug lines --- k8s/schema_manager.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/k8s/schema_manager.go b/k8s/schema_manager.go index f1386a7..a9222c4 100644 --- a/k8s/schema_manager.go +++ b/k8s/schema_manager.go @@ -76,12 +76,11 @@ func (m *SchemaManager) DuckType(gvk schema.GroupVersionKind, object *unstructur } func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix string) (interface{}, error) { - fmt.Printf("Prefix: %s\n", prefix) + // fmt.Printf("Prefix: %s\n", prefix) v := reflect.ValueOf(object) switch v.Kind() { case reflect.Slice: - fmt.Println("Type is slice") bytes, ok := object.([]byte) if ok { fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) @@ -103,7 +102,6 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix } return newArray, nil case reflect.Map: - fmt.Println("Type is map") oldMap := object.(map[string]interface{}) newMap := make(map[string]interface{}) for k, v := range oldMap { @@ -119,20 +117,17 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix } return newMap, nil case reflect.String: - fmt.Println("Type is string") value := object.(string) fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) if err != nil { return nil, errors.Wrapf(err, "failed to find type for key %s", prefix) } newValue, err := transformStringToType(value, fieldType) - fmt.Printf("New value for field %s is %s\n", prefix, newValue) if err != nil { return nil, errors.Wrapf(err, "failed to transform string to type %v", fieldType) } return newValue, nil case reflect.Int, reflect.Int8, reflect.Int32, reflect.Int64: - fmt.Println("Type is int") value := v.Int() fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) if err != nil { @@ -144,7 +139,6 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix } return newValue, nil case reflect.Uint, reflect.Uint8, reflect.Uint32, reflect.Uint64: - fmt.Println("Type is uint") value := v.Uint() fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) if err != nil { @@ -156,7 +150,6 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix } return newValue, nil case reflect.Float32, reflect.Float64: - fmt.Println("Type is float") value := int64(v.Float()) fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) if err != nil { From c88f86f923cfb4147ee30b9805ff4b774afb1ea3 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Tue, 24 Nov 2020 13:33:05 +0200 Subject: [PATCH 08/16] Add e2e tests --- .gitignore | 3 + go.mod | 1 + go.sum | 132 +---------------------- test/config.yaml | 48 +++++++++ test/e2e.go | 276 +++++++++++++++++++++++++++++++++++++++++++++++ test/e2e.sh | 48 +++++++++ test/patch1.yaml | 48 +++++++++ 7 files changed, 427 insertions(+), 129 deletions(-) create mode 100644 test/config.yaml create mode 100644 test/e2e.go create mode 100755 test/e2e.sh create mode 100644 test/patch1.yaml diff --git a/.gitignore b/.gitignore index 6411e65..90d9d28 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ bin/ cover.out .env +/.bin +/.certs +/karina* diff --git a/go.mod b/go.mod index a8f9afe..1464c43 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/onsi/ginkgo v1.12.1 github.com/onsi/gomega v1.10.1 github.com/pkg/errors v0.9.1 + github.com/sirupsen/logrus v1.7.0 github.com/tidwall/gjson v1.6.1 golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5 // indirect gopkg.in/flanksource/yaml.v3 v3.1.1 diff --git a/go.sum b/go.sum index c77222b..b17a270 100644 --- a/go.sum +++ b/go.sum @@ -29,7 +29,6 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= @@ -72,8 +71,6 @@ github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy86 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= -github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= @@ -83,7 +80,6 @@ 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/Shopify/ejson v1.2.1 h1:Dx0Ipn0mUgrZlzIa5oIUrH0rdSmBOyod/UJmQQK1KHo= github.com/Shopify/ejson v1.2.1/go.mod h1:J8cw5GOA0l/aMOPp+uDfwNYVbeqIaBhzRkv1+76UCvk= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= @@ -96,7 +92,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -130,7 +125,6 @@ github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17 github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/brancz/gojsontoyaml v0.0.0-20191212081931-bf2969bbd742/go.mod h1:IyUJYN1gvWjtLF5ZuygmxbnsAyP3aJS6cHzIuZY50B0= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -165,7 +159,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -187,8 +180,6 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKBAG3Klr9cn7N+LcYc82AZ2S7+cA= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad/go.mod h1:mPKfmRa823oBIgl2r20LeMSpTAteW5j7FLkc0vjmzyQ= -github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -210,8 +201,6 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flanksource/commons v1.4.3 h1:arEom5vkh5RrEWNy+kj32PmCbZ8d3OdZ0K7X7wQAi9k= github.com/flanksource/commons v1.4.3/go.mod h1:cGrz4qFi4NrP04vjMxv6DQk0SD0u6nnYppKpgFShj0c= -github.com/flanksource/kommons v0.1.5 h1:1o8PyBNngemau4Q14NOkvXVqddqheOtDDELoVcRQtoc= -github.com/flanksource/kommons v0.1.5/go.mod h1:Dc/oeDDXgybBm1LFr1iSAgARLCja8ep9K42Qouu+yPM= github.com/flanksource/kommons v0.1.6 h1:VmYd/XjuqzQb3ICisTqOUpjzU4Gc08RZafJzFLXtFdA= github.com/flanksource/kommons v0.1.6/go.mod h1:Dc/oeDDXgybBm1LFr1iSAgARLCja8ep9K42Qouu+yPM= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= @@ -225,8 +214,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/getkin/kin-openapi v0.30.0 h1:RAaggqVsRxj2t5vKDrOPcLxA9x8TBDDzYrStzFEHxt4= -github.com/getkin/kin-openapi v0.30.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -235,14 +222,11 @@ github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 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-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= -github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= @@ -257,7 +241,6 @@ github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-logr/zapr v0.3.0 h1:iyiCRZ29uPmbO7mWIjOEiYMXrTxZWTyK4tCatLyGpUY= github.com/go-logr/zapr v0.3.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= 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.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -280,8 +263,6 @@ github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg= -github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= @@ -298,28 +279,21 @@ github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsd github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= -github.com/go-openapi/spec v0.19.14 h1:r4fbYFo6N4ZelmSX8G6p+cv/hZRXzcuqQIADGT1iNKM= -github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= github.com/go-openapi/strfmt v0.19.3 h1:eRfyY5SkaNJCAwmmMcADjY31ow9+N7MCLW7oRkbsINA= github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= -github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.11 h1:RFTu/dlFySpyVvJDfp/7674JY4SDglYWKztbiIGFpmc= -github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5 h1:QhCBKRYqZR+SKo4gl1lPhPahope8/RLt6EVgY8X80w0= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= -github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= @@ -328,24 +302,8 @@ github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 h1:28FVBuwkwowZMjbA github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= -github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= -github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= -github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= -github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= -github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= -github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= -github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= -github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= -github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= -github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -375,21 +333,6 @@ github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= -github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= -github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= -github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= -github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk= -github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= -github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= -github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= 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= @@ -406,7 +349,6 @@ github.com/google/go-replayers/grpcreplay v0.1.0 h1:eNb1y9rZFmY4ax45uEEECSa8fsxG github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= github.com/google/go-replayers/httpreplay v0.1.0 h1:AX7FUb4BjrrzNvblr/OlgwrmFiep6soj5K2QSDW7BGk= github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= -github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= @@ -419,7 +361,6 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= @@ -446,7 +387,6 @@ github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gosimple/slug v1.9.0 h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs= github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4vDJbg= -github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -490,7 +430,6 @@ github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqk github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= @@ -555,7 +494,6 @@ github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= @@ -573,10 +511,6 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT 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/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= 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.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -591,9 +525,7 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -602,7 +534,6 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -620,7 +551,6 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= @@ -633,7 +563,6 @@ github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFW github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 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= @@ -650,19 +579,14 @@ github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/f github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= @@ -672,7 +596,6 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= @@ -687,7 +610,6 @@ github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTm github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -701,7 +623,6 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -739,8 +660,6 @@ github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4 github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA= -github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ= github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -755,14 +674,10 @@ github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shabbyrobe/gocovmerge v0.0.0-20180507124511-f6ea450bfb63 h1:J6qvD6rbmOil46orKqJaRPG+zTpoGlBTUdyv8ki63L0= github.com/shabbyrobe/gocovmerge v0.0.0-20180507124511-f6ea450bfb63/go.mod h1:n+VKSARF5y/tS9XFSP7vWDfS+GUC5vs/YT7M5XDTUEM= -github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= -github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= @@ -802,7 +717,6 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -828,13 +742,10 @@ github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jW 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.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws= github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= @@ -843,7 +754,6 @@ github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -856,14 +766,7 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok= github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= -github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= -github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= -github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vbauerster/mpb/v5 v5.0.3 h1:Ldt/azOkbThTk2loi6FrBd/3fhxGFQ24MxFAS88PoNY= github.com/vbauerster/mpb/v5 v5.0.3/go.mod h1:h3YxU5CSr8rZP4Q3xZPVB3jJLhWPou63lHEdr9ytH4Y= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= @@ -871,15 +774,14 @@ github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70 github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc= github.com/zealic/xignore v0.3.3 h1:EpLXUgZY/JEzFkTc+Y/VYypzXtNz+MSOMVCGW5Q4CKQ= github.com/zealic/xignore v0.3.3/go.mod h1:lhS8V7fuSOtJOKsvKI7WfsZE276/7AYEqokv3UiqEAU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= @@ -896,8 +798,6 @@ go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg= -go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= @@ -931,7 +831,6 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -965,13 +864,12 @@ 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/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -994,7 +892,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1051,8 +948,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU= @@ -1087,26 +982,20 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190308174544-00c44ba9c14f/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 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-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -1114,15 +1003,11 @@ golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/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-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/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-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh338oozWyiFsBRHtrflcws= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/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/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1219,11 +1104,11 @@ gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20190924164351-c8b7dadae555 h1:4Yrwvx9yMvZx+vK3wdX7aX2UCNZJJn0TDc+BNOJTE00= gopkg.in/yaml.v3 v3.0.0-20190924164351-c8b7dadae555/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.0 h1:d+tVGRu6X0ZBQ+kyAR8JKi6AXhTP2gmQaoIYaGFz634= gotest.tools/v3 v3.0.0/go.mod h1:TUP+/YtXl/dp++T+SZ5v2zUmLVBHmptSb/ajDLCJ+3c= +gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1232,7 +1117,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= k8s.io/api v0.19.3 h1:GN6ntFnv44Vptj/b+OnMW7FmzkpDoIDLZRvKX3XH9aU= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= @@ -1242,7 +1126,6 @@ k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrq k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M= k8s.io/apiextensions-apiserver v0.19.4 h1:D9ak9T012tb3vcGFWYmbQuj9SCC8YM4zhA4XZqsAQC4= k8s.io/apiextensions-apiserver v0.19.4/go.mod h1:B9rpH/nu4JBCtuUp3zTTk8DEjZUupZTBEec7/2zNRYw= -k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= k8s.io/apimachinery v0.19.3 h1:bpIQXlKjB4cB/oNpnNnV+BybGPR7iP5oYpsOTEJ4hgc= k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= @@ -1271,7 +1154,6 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= @@ -1281,9 +1163,6 @@ k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= @@ -1291,13 +1170,8 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9 h1:rusRLrDhjBp6aY sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE= sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= -sigs.k8s.io/kustomize v1.0.11 h1:Yb+6DDt9+aR2AvQApvUaKS/ugteeG4MPyoFeUHiPOjk= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= -sigs.k8s.io/kustomize/api v0.6.5 h1:xaAWZamIhpt9Y5Kn/vuBcBhZH8/m0zwew1d4HepIgXg= -sigs.k8s.io/kustomize/api v0.6.5/go.mod h1:Z96Z48h3nOWgVAmd4JGABszi5znhEnz7xoWHy+Bl7L4= -sigs.k8s.io/kustomize/kyaml v0.9.4/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw= -sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= diff --git a/test/config.yaml b/test/config.yaml new file mode 100644 index 0000000..148181c --- /dev/null +++ b/test/config.yaml @@ -0,0 +1,48 @@ +name: kind-kind +patches: + - ./test/patch1.yaml +domain: 127.0.0.1.nip.io +dex: + disabled: true +ldap: + disabled: true +kubernetes: + version: !!env KUBERNETES_VERSION + kubeletExtraArgs: + node-labels: "ingress-ready=true" + authorization-mode: "AlwaysAllow" + containerRuntime: containerd +versions: + sonobuoy: 0.16.4 + ketall: v1.3.0 + apacheds: 0.7.0 +podSubnet: 100.200.0.0/16 +serviceSubnet: 100.100.0.0/16 +calico: + version: v3.8.2 +s3: + endpoint: http://minio.minio.svc:9000 + externalEndpoint: minio.127.0.0.1.nip.io + bucket: harbor + access_key: minio + secret_key: minio123 + region: us-east1 + kmsMasterKey: minio-demo-key:6368616e676520746869732070617373776f726420746f206120736563726574 + usePathStyle: true + skipTLSVerify: true + e2e: + minio: true +ca: + cert: .certs/root-ca.crt + privateKey: .certs/root-ca.key + password: foobar +ingressCA: + cert: .certs/ingress-ca.crt + privateKey: .certs/ingress-ca.key + password: foobar +test: + exclude: + - configmap-reloader + - dex + - audit + - encryption \ No newline at end of file diff --git a/test/e2e.go b/test/e2e.go new file mode 100644 index 0000000..963a449 --- /dev/null +++ b/test/e2e.go @@ -0,0 +1,276 @@ +package main + +import ( + "context" + "flag" + "fmt" + "os" + "path/filepath" + "time" + + "github.com/flanksource/commons/console" + "github.com/flanksource/commons/logger" + "github.com/flanksource/commons/utils" + "github.com/flanksource/kommons" + templatev1 "github.com/flanksource/template-operator/api/v1" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" + v1 "k8s.io/api/core/v1" + extv1beta1 "k8s.io/api/extensions/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + crdclient "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/apiutil" + "sigs.k8s.io/yaml" +) + +const ( + namespace = "platform-system" + deployment = "template-operator-controller-manager" +) + +var ( + k8s *kubernetes.Clientset + crdK8s crdclient.Client + client *kommons.Client + tests = map[string]Test{ + "template-operator-is-running": TestTemplateOperatorIsRunning, + "deployment-replicas": TestDeploymentReplicas, + } + scheme = runtime.NewScheme() + restConfig *rest.Config + pullRequestUsername string +) + +type Test func(context.Context, *console.TestResults) error +type DeferFunc func() +type deploymentFn func(*extv1beta1.Deployment) bool + +func main() { + var kubeconfig *string + var timeout *time.Duration + var err error + if home := homeDir(); home != "" { + kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file") + } else { + kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file") + } + timeout = flag.Duration("timeout", 10*time.Minute, "Global timeout for all tests") + flag.Parse() + + _ = clientgoscheme.AddToScheme(scheme) + + _ = templatev1.AddToScheme(scheme) + + // use the current context in kubeconfig + restConfig, err = clientcmd.BuildConfigFromFlags("", *kubeconfig) + if err != nil { + log.Fatalf("failed to create k8s config: %v", err) + } + + k8s, err = kubernetes.NewForConfig(restConfig) + if err != nil { + log.Fatalf("failed to create clientset: %v", err) + } + + mapper, err := apiutil.NewDynamicRESTMapper(restConfig) + if err != nil { + log.Fatalf("failed to create mapper: %v", err) + } + + client = kommons.NewClient(restConfig, logger.StandardLogger()) + + crdK8s, err = crdclient.New(restConfig, crdclient.Options{Scheme: scheme, Mapper: mapper}) + if err != nil { + log.Fatalf("failed to create crd client: %v", err) + } + + test := &console.TestResults{ + Writer: os.Stdout, + } + + errors := map[string]error{} + deadline, cancelFunc := context.WithTimeout(context.Background(), *timeout) + defer cancelFunc() + + for name, t := range tests { + err := t(deadline, test) + if err != nil { + errors[name] = err + } + } + + if len(errors) > 0 { + for name, err := range errors { + log.Errorf("test %s failed: %v", name, err) + } + os.Exit(1) + } + + log.Infof("All tests passed !!!") +} + +func TestTemplateOperatorIsRunning(ctx context.Context, test *console.TestResults) error { + pods, err := k8s.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{LabelSelector: "control-plane=template-operator"}) + if err != nil { + test.Failf("TestTemplateOperatorIsRunning", "failed to list template-operator pods: %v", err) + return err + } + if len(pods.Items) != 1 { + test.Failf("TestTemplateOperatorIsRunning", "expected 1 pod got %d", len(pods.Items)) + return errors.Errorf("Expected 1 pod got %d", len(pods.Items)) + } + test.Passf("TestTemplateOperatorIsRunning", "%s pod is running", pods.Items[0].Name) + return nil +} + +func TestDeploymentReplicas(ctx context.Context, test *console.TestResults) error { + ns := fmt.Sprintf("template-operator-e2e-%s", utils.RandomString(6)) + if err := client.CreateOrUpdateNamespace(ns, nil, nil); err != nil { + test.Failf("TestDeploymentReplicas", "failed to create namespace %s", ns) + return err + } + + defer func() { + if err := k8s.CoreV1().Namespaces().Delete(context.Background(), ns, metav1.DeleteOptions{}); err != nil { + log.Errorf("failed to delete namespace %s: %v", ns, err) + } + }() + + if err := client.CreateOrUpdateConfigMap("nginx-config", ns, map[string]string{"replicas": "3"}); err != nil { + test.Failf("TestDeploymentReplicas", "failed to create nginx config") + return err + } + + deployment := &extv1beta1.Deployment{ + TypeMeta: metav1.TypeMeta{APIVersion: "extensions/v1beta1", Kind: "Deployment"}, + ObjectMeta: metav1.ObjectMeta{ + Name: "nginx-deployment", + Namespace: ns, + Labels: map[string]string{"app": "nginx"}, + }, + Spec: extv1beta1.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "nginx"}, + }, + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{"app": "nginx"}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "nginx", + Image: "nginx:1.14.2", + Ports: []v1.ContainerPort{{ContainerPort: 80}}, + }, + }, + }, + }, + }, + } + + deployment, err := k8s.ExtensionsV1beta1().Deployments(ns).Create(ctx, deployment, metav1.CreateOptions{}) + if err != nil { + test.Failf("TestDeploymentReplicas", "failed to create deployment") + return err + } + + patchTemplate := ` +apiVersion: extensions/v1beta1 +kind: Deployment +spec: + replicas: "{{ kget "cm/%s/nginx-config" "data.replicas" }}" +` + patch := fmt.Sprintf(patchTemplate, ns) + + template := &templatev1.Template{ + TypeMeta: metav1.TypeMeta{APIVersion: "templating.flanksource.com/v1", Kind: "Template"}, + ObjectMeta: metav1.ObjectMeta{Name: ns}, + Spec: templatev1.TemplateSpec{ + Source: templatev1.ResourceSelector{ + APIVersion: "extensions/v1beta1", + Kind: "Deployment", + LabelSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "nginx"}, + }, + }, + Patches: []string{patch}, + }, + } + if err := client.Apply("", template); err != nil { + test.Failf("TestDeploymentReplicas", "failed to create template: %v", err) + return err + } + defer func() { + if err := crdK8s.Delete(context.Background(), template); err != nil { + log.Errorf("failed to delete template: %v", err) + } + }() + + _, err = waitForDeploymentChanged(ctx, deployment, func(d *extv1beta1.Deployment) bool { + return d.Spec.Replicas != nil && *d.Spec.Replicas == 3 + }) + if err != nil { + test.Failf("TestDeploymentReplicas", "deployment was not updated by template: %v", err) + return err + } + + test.Passf("TestDeploymentReplicas", "Deployment updated by template to 3 replicas") + + return nil +} + +func waitForDeploymentChanged(ctx context.Context, deployment *extv1beta1.Deployment, fn deploymentFn) (*extv1beta1.Deployment, error) { + for { + d, err := k8s.ExtensionsV1beta1().Deployments(deployment.Namespace).Get(ctx, deployment.Name, metav1.GetOptions{}) + if err != nil { + return nil, errors.Wrapf(err, "failed to get deployment %s", deployment.Name) + } + + if fn(d) { + return d, nil + } + + log.Debugf("Deployment %s not changed", deployment.Name) + time.Sleep(2 * time.Second) + } +} + +func assertEquals(test *console.TestResults, name, actual, expected string) error { + if actual != expected { + test.Failf(name, "expected %s to equal %s", actual, expected) + return errors.Errorf("Test %s expected %s to equal %s", name, actual, expected) + } + return nil +} + +func assertInterfaceEquals(test *console.TestResults, name string, actual, expected interface{}) error { + actualYml, err := yaml.Marshal(actual) + if err != nil { + return errors.Wrap(err, "failed to marshal actual") + } + + expectedYml, err := yaml.Marshal(expected) + if err != nil { + return errors.Wrap(err, "failed to marshal expected") + } + + if string(actualYml) != string(expectedYml) { + test.Failf("Test %s expected: %s\n\nTo Equal:\n%s\n", name, string(actualYml), string(expectedYml)) + return errors.Errorf("Test %s expected:\n%s\nTo Match:\n%s\n", name, actualYml, expectedYml) + } + + return nil +} + +func homeDir() string { + if h := os.Getenv("HOME"); h != "" { + return h + } + return os.Getenv("USERPROFILE") // windows +} diff --git a/test/e2e.sh b/test/e2e.sh new file mode 100755 index 0000000..2fb4677 --- /dev/null +++ b/test/e2e.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -ex + +export KARINA_VERSION=v0.20.4 +export KARINA="./karina -c test/config.yaml" +export KUBECONFIG=~/.kube/config +export DOCKER_API_VERSION=1.39 + +if [[ "$OSTYPE" == "linux-gnu" ]]; then + wget -q https://github.com/flanksource/karina/releases/download/$KARINA_VERSION/karina + chmod +x karina +elif [[ "$OSTYPE" == "darwin"* ]]; then + wget -q https://github.com/flanksource/karina/releases/download/$KARINA_VERSION/karina_osx + cp karina_osx karina + chmod +x karina +else + echo "OS $OSTYPE not supported" + exit 1 +fi + +mkdir -p .bin + +KUSTOMIZE=./bin/kustomize +if [ ! -f "$KUSTOMIZE" ]; then + curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash + mv kustomize .bin +fi +export PATH=$(pwd)/.bin:$PATH + +$KARINA ca generate --name root-ca --cert-path .certs/root-ca.crt --private-key-path .certs/root-ca.key --password foobar --expiry 1 +$KARINA ca generate --name ingress-ca --cert-path .certs/ingress-ca.crt --private-key-path .certs/ingress-ca.key --password foobar --expiry 1 +$KARINA provision kind-cluster + +$KARINA deploy crds +$KARINA deploy calico +kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true + +$KARINA deploy base +$KARINA deploy stubs + +export IMG=flanksource/template-operator:v1 +make docker-build +kind load docker-image $IMG --name kind-kind + +make deploy + +go run test/e2e.go diff --git a/test/patch1.yaml b/test/patch1.yaml new file mode 100644 index 0000000..e048c87 --- /dev/null +++ b/test/patch1.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: minio + namespace: minio +spec: + template: + spec: + containers: + - name: minio + image: minio/minio:RELEASE.2020-03-06T22-23-56Z +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: vault + namespace: vault +spec: + replicas: 1 +--- +apiVersion: monitoring.coreos.com/v1 +kind: Alertmanager +metadata: + name: main + namespace: monitoring +spec: + replicas: 1 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dex + namespace: dex +spec: + replicas: 1 +--- +apiVersion: monitoring.coreos.com/v1 +kind: Prometheus +metadata: + name: k8s + namespace: monitoring +spec: + replicas: 1 + resources: + requests: + memory: 256Mi + cpu: 100m + retention: 10h \ No newline at end of file From 416ea89707c2dbb509f644f43b223516e6cdeafd Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Tue, 24 Nov 2020 13:41:30 +0200 Subject: [PATCH 09/16] Add github workflow --- .github/workflows/test.yml | 24 ++++++++++++++++++++++++ test/e2e.sh | 4 +++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..8d7517a --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,24 @@ +on: [push] +name: Test +jobs: + test: + strategy: + matrix: + go-version: [1.13.x] + platform: [ubuntu-latest] + k8s: + - v1.16.9 + runs-on: ${{ matrix.platform }} + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v2 + - name: Test + env: + KUBERNETES_VERSION: ${{matrix.k8s}} + GITHUB_TOKEN: ${{secrets.E2E_TOKEN}} + GITHUB_USERNAME: flankbot + run: ./test/e2e.sh diff --git a/test/e2e.sh b/test/e2e.sh index 2fb4677..31f3c9e 100755 --- a/test/e2e.sh +++ b/test/e2e.sh @@ -1,6 +1,6 @@ #!/bin/bash -set -ex +set -e export KARINA_VERSION=v0.20.4 export KARINA="./karina -c test/config.yaml" @@ -46,3 +46,5 @@ kind load docker-image $IMG --name kind-kind make deploy go run test/e2e.go + +go test ./k8s \ No newline at end of file From 4888eb43141f007d69188f1fbe8abc3ed80b5c6b Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Tue, 24 Nov 2020 14:05:33 +0200 Subject: [PATCH 10/16] Fix e2e tests --- k8s/patches_test.go | 2 +- test/config.yaml | 4 ++++ test/e2e.sh | 4 +++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/k8s/patches_test.go b/k8s/patches_test.go index 5c0a88d..9786712 100644 --- a/k8s/patches_test.go +++ b/k8s/patches_test.go @@ -165,7 +165,7 @@ spec: Expect(foundYaml).To(Equal(expectedYaml)) }) - FIt("Merges annotations and labels", func() { + It("Merges annotations and labels", func() { resource := &unstructured.Unstructured{ Object: map[string]interface{}{ "kind": "Ingress", diff --git a/test/config.yaml b/test/config.yaml index 148181c..b555bc4 100644 --- a/test/config.yaml +++ b/test/config.yaml @@ -40,6 +40,10 @@ ingressCA: cert: .certs/ingress-ca.crt privateKey: .certs/ingress-ca.key password: foobar +canaryChecker: + version: v0.11.2 +postgresOperator: + version: v1.3.4.flanksource.1 test: exclude: - configmap-reloader diff --git a/test/e2e.sh b/test/e2e.sh index 31f3c9e..b959f42 100755 --- a/test/e2e.sh +++ b/test/e2e.sh @@ -8,7 +8,9 @@ export KUBECONFIG=~/.kube/config export DOCKER_API_VERSION=1.39 if [[ "$OSTYPE" == "linux-gnu" ]]; then - wget -q https://github.com/flanksource/karina/releases/download/$KARINA_VERSION/karina + wget -q https://github.com/flanksource/karina/releases/download/$KARINA_VERSION/platform-cli + mv platform-cli karina + # wget -q https://github.com/flanksource/karina/releases/download/$KARINA_VERSION/karina chmod +x karina elif [[ "$OSTYPE" == "darwin"* ]]; then wget -q https://github.com/flanksource/karina/releases/download/$KARINA_VERSION/karina_osx From 9f5a78797c6a051681ba986abfff55cf46320658 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Tue, 24 Nov 2020 14:08:07 +0200 Subject: [PATCH 11/16] Github credentials from test workflow --- .github/workflows/test.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8d7517a..a95919a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,6 +19,4 @@ jobs: - name: Test env: KUBERNETES_VERSION: ${{matrix.k8s}} - GITHUB_TOKEN: ${{secrets.E2E_TOKEN}} - GITHUB_USERNAME: flankbot run: ./test/e2e.sh From bffea4fac2c58cde3148807b17ab567b23aa3ad5 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Tue, 24 Nov 2020 14:08:38 +0200 Subject: [PATCH 12/16] Use latest karina version for e2e --- test/e2e.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e.sh b/test/e2e.sh index b959f42..d661fa2 100755 --- a/test/e2e.sh +++ b/test/e2e.sh @@ -2,7 +2,7 @@ set -e -export KARINA_VERSION=v0.20.4 +export KARINA_VERSION=v0.21.0 export KARINA="./karina -c test/config.yaml" export KUBECONFIG=~/.kube/config export DOCKER_API_VERSION=1.39 From 4b5c37f46e4941be629cffd1d8fa36821243cada Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Thu, 26 Nov 2020 16:04:35 +0200 Subject: [PATCH 13/16] Add map duck typing. Add duck typing for resource objects --- k8s/patches.go | 8 +--- k8s/patches_test.go | 67 +++++++++++++++++++++++++++--- k8s/schema_manager.go | 27 +++++++++--- k8s/schema_manager_test.go | 47 ++++++++++++++++++++- k8s/template_manager.go | 54 +++++++++++++++++++----- k8s/template_manager_test.go | 80 ++++++++++++++++++++++++++++++++++++ 6 files changed, 253 insertions(+), 30 deletions(-) create mode 100644 k8s/template_manager_test.go diff --git a/k8s/patches.go b/k8s/patches.go index c530c4a..5a60587 100644 --- a/k8s/patches.go +++ b/k8s/patches.go @@ -14,7 +14,6 @@ import ( "github.com/pkg/errors" "github.com/tidwall/gjson" fyaml "gopkg.in/flanksource/yaml.v3" - extapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" @@ -41,12 +40,7 @@ type PatchApplier struct { SchemaManager *SchemaManager } -func NewPatchApplier(clientset *kubernetes.Clientset, crdClient extapi.ApiextensionsV1beta1Interface, log logr.Logger) (*PatchApplier, error) { - schemaManager, err := NewSchemaManager(clientset, crdClient) - if err != nil { - return nil, errors.Wrap(err, "failed to create schema manager") - } - +func NewPatchApplier(clientset *kubernetes.Clientset, schemaManager *SchemaManager, log logr.Logger) (*PatchApplier, error) { p := &PatchApplier{ Clientset: clientset, Log: log, diff --git a/k8s/patches_test.go b/k8s/patches_test.go index 9786712..061a70c 100644 --- a/k8s/patches_test.go +++ b/k8s/patches_test.go @@ -1,7 +1,6 @@ package k8s_test import ( - "fmt" "strings" "github.com/flanksource/template-operator/k8s" @@ -65,7 +64,7 @@ var _ = Describe("Patches", func() { ] ` log := ctrl.Log.WithName("test") - patchApplier, err := k8s.NewPatchApplier(clientset(), crdClient(), log) + patchApplier, err := k8s.NewPatchApplier(clientset(), newSchemaManager(), log) Expect(err).ToNot(HaveOccurred()) patchApplier.FuncMap["kget"] = func(path, jsonPath string) string { return "1.2.3.4.nip.io" @@ -134,7 +133,7 @@ spec: ] ` log := ctrl.Log.WithName("test") - patchApplier, err := k8s.NewPatchApplier(clientset(), crdClient(), log) + patchApplier, err := k8s.NewPatchApplier(clientset(), newSchemaManager(), log) Expect(err).ToNot(HaveOccurred()) patchApplier.FuncMap["kget"] = func(path, jsonPath string) string { return "1.2.3.4.nip.io" @@ -199,7 +198,7 @@ metadata: ` log := ctrl.Log.WithName("test") - patchApplier, err := k8s.NewPatchApplier(clientset(), crdClient(), log) + patchApplier, err := k8s.NewPatchApplier(clientset(), newSchemaManager(), log) Expect(err).ToNot(HaveOccurred()) patchApplier.FuncMap["kget"] = func(path, jsonPath string) string { return "1.2.3.4.nip.io" @@ -228,8 +227,64 @@ metadata: namespace: example spec: {} `) - fmt.Printf("Found:\n%s\n", foundYaml) - fmt.Printf("Expected:\n%s\n", expectedYaml) + // fmt.Printf("Found:\n%s\n", foundYaml) + // fmt.Printf("Expected:\n%s\n", expectedYaml) + Expect(foundYaml).To(Equal(expectedYaml)) + }) + + It("Encodes as json", func() { + resource := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "kind": "postgresql", + "apiVersion": "acid.zalan.do/v1", + "metadata": map[string]interface{}{ + "name": "test", + "namespace": "example", + }, + "spec": map[string]interface{}{ + "replicas": 1, + }, + }, + } + + patch := ` +apiVersion: acid.zalan.do/v1 +kind: postgresql +spec: + postgresql: + parameters: "{{ kget "postgresqldb/postgres-operator/test" "spec.parameters" }}" +` + + log := ctrl.Log.WithName("test") + patchApplier, err := k8s.NewPatchApplier(clientset(), newSchemaManager(), log) + Expect(err).ToNot(HaveOccurred()) + patchApplier.FuncMap["kget"] = func(path, jsonPath string) string { + str := "{\"max_connections\":\"1024\",\"shared_buffers\":\"4759MB\",\"work_mem\":\"475MB\",\"maintenance_work_mem\":\"634M\"}" + return strings.ReplaceAll(str, "\"", "\\\"") + } + + newResource, err := patchApplier.Apply(resource, patch, k8s.PatchTypeYaml) + Expect(err).ToNot(HaveOccurred()) + + specYaml, err := yaml.Marshal(newResource.Object) + Expect(err).ToNot(HaveOccurred()) + foundYaml := strings.TrimSpace(string(specYaml)) + + expectedYaml := strings.TrimSpace(` +apiVersion: acid.zalan.do/v1 +kind: postgresql +metadata: + name: test + namespace: example +spec: + postgresql: + parameters: + maintenance_work_mem: 634M + max_connections: "1024" + shared_buffers: 4759MB + work_mem: 475MB + replicas: 1 +`) Expect(foundYaml).To(Equal(expectedYaml)) }) }) diff --git a/k8s/schema_manager.go b/k8s/schema_manager.go index a9222c4..f5442ad 100644 --- a/k8s/schema_manager.go +++ b/k8s/schema_manager.go @@ -8,6 +8,7 @@ import ( "strconv" "strings" + "github.com/flanksource/commons/logger" "github.com/go-openapi/jsonpointer" "github.com/go-openapi/spec" "github.com/pkg/errors" @@ -85,7 +86,8 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix if ok { fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) if err != nil { - return errors.Wrapf(err, "failed to find type for key %s", prefix), nil + logger.Errorf("failed to find type for key %s: %v", prefix, err) + return bytes, nil } return transformBytesToType(bytes, fieldType) } @@ -120,7 +122,8 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix value := object.(string) fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) if err != nil { - return nil, errors.Wrapf(err, "failed to find type for key %s", prefix) + logger.Errorf("failed to find type for key %s: %v", prefix, err) + return value, nil } newValue, err := transformStringToType(value, fieldType) if err != nil { @@ -131,7 +134,8 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix value := v.Int() fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) if err != nil { - return nil, errors.Wrapf(err, "failed to find type for key %s", prefix) + logger.Errorf("failed to find type for key %s: %v", prefix, err) + return value, nil } newValue, err := transformInt64ToType(value, fieldType) if err != nil { @@ -142,7 +146,8 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix value := v.Uint() fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) if err != nil { - return nil, errors.Wrapf(err, "failed to find type for key %s", prefix) + logger.Errorf("failed to find type for key %s: %v", prefix, err) + return value, nil } newValue, err := transformUint64ToType(value, fieldType) if err != nil { @@ -153,7 +158,8 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix value := int64(v.Float()) fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) if err != nil { - return nil, errors.Wrapf(err, "failed to find type for key %s", prefix) + logger.Errorf("failed to find type for key %s: %v", prefix, err) + return value, nil } newValue, err := transformInt64ToType(value, fieldType) if err != nil { @@ -209,7 +215,7 @@ func (m *SchemaManager) findTypeForKey(schema *spec.Schema, key string) (*spec.S fieldSchema, found := schema.Properties[fieldName] if !found { - if schema.Type.Contains("object") && schema.AdditionalProperties.Schema != nil { + if schema.Type.Contains("object") && schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil { fieldSchema = *schema.AdditionalProperties.Schema } else { return nil, errors.Errorf("failed to find property %s", fieldName) @@ -351,6 +357,15 @@ func transformStringToType(value string, fieldType *TypedField) (interface{}, er return strconv.ParseBool(value) } + if contains(fieldType.Types, "object") { + obj := map[string]interface{}{} + err := json.Unmarshal([]byte(value), &obj) + if err != nil { + return nil, errors.Wrapf(err, "failed to transform string value to object: %v", err) + } + return obj, err + } + return nil, errors.Errorf("could not transform string value to types %v format %s", fieldType.Types, fieldType.Format) } diff --git a/k8s/schema_manager_test.go b/k8s/schema_manager_test.go index 81c1f18..1408ed9 100644 --- a/k8s/schema_manager_test.go +++ b/k8s/schema_manager_test.go @@ -111,6 +111,14 @@ var _ = Describe("SchemaManager", func() { Expect(err).To(BeNil()) Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"string"}, Format: "byte"})) }) + + It("Returns map for PostgresqlDB spec.parameters", func() { + schemaManager := newSchemaManager() + gvk := schema.GroupVersionKind{Group: "db.flanksource.com", Version: "v1", Kind: "PostgresqlDB"} + kind, err := schemaManager.FindTypeForKey(gvk, "spec.parameters") + Expect(err).To(BeNil()) + Expect(*kind).To(Equal(k8s.TypedField{Types: []string{"object"}, Format: ""})) + }) }) Describe("DuckType", func() { @@ -160,7 +168,44 @@ spec: yml, err := yaml.Marshal(resource.Object) Expect(err).ToNot(HaveOccurred()) - fmt.Printf("Expected:\n%v\n=======Actual:\n%v\n==========", expectedYaml, string(yml)) + // fmt.Printf("Expected:\n%v\n=======Actual:\n%v\n==========", expectedYaml, string(yml)) + Expect(strings.TrimSpace(string(yml))).To(Equal(strings.TrimSpace(expectedYaml))) + }) + + It("Encodes PostgresqlDB spec.parameters to map[string]interface{} correctly", func() { + value := ` +apiVersion: acid.zalan.do/v1 +kind: postgresql +metadata: + name: test + namespace: postgres-operator +spec: + replicas: 2 + postgresql: + parameters: "{\"max_connections\":\"1024\",\"shared_buffers\":\"4759MB\",\"work_mem\":\"475MB\",\"maintenance_work_mem\":\"634M\"}" +` + resource, err := duckTypeWithValue(value) + Expect(err).ToNot(HaveOccurred()) + + expectedYaml := ` +apiVersion: acid.zalan.do/v1 +kind: postgresql +metadata: + name: test + namespace: postgres-operator +spec: + postgresql: + parameters: + maintenance_work_mem: 634M + max_connections: "1024" + shared_buffers: 4759MB + work_mem: 475MB + replicas: 2 +` + yml, err := yaml.Marshal(resource.Object) + Expect(err).ToNot(HaveOccurred()) + + // fmt.Printf("Expected:\n%v\n=======Actual:\n%v\n==========", expectedYaml, string(yml)) Expect(strings.TrimSpace(string(yml))).To(Equal(strings.TrimSpace(expectedYaml))) }) }) diff --git a/k8s/template_manager.go b/k8s/template_manager.go index 36d8306..8dc0af3 100644 --- a/k8s/template_manager.go +++ b/k8s/template_manager.go @@ -18,6 +18,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" "sigs.k8s.io/yaml" ) @@ -30,8 +31,9 @@ var ( type TemplateManager struct { Client *kommons.Client kubernetes.Interface - Log logr.Logger - PatchApplier *PatchApplier + Log logr.Logger + PatchApplier *PatchApplier + SchemaManager *SchemaManager } type ResourcePatch struct { @@ -54,15 +56,21 @@ func NewTemplateManager(c *kommons.Client, log logr.Logger) (*TemplateManager, e return nil, errors.Wrap(err, "failed to create crd client") } - patchApplier, err := NewPatchApplier(clientset, crdClient, log) + schemaManager, err := NewSchemaManager(clientset, crdClient) + if err != nil { + return nil, errors.Wrap(err, "failed to create schema manager") + } + + patchApplier, err := NewPatchApplier(clientset, schemaManager, log) if err != nil { return nil, errors.Wrap(err, "faile to create patch applier") } tm := &TemplateManager{ - Client: c, - Log: log, - PatchApplier: patchApplier, + Client: c, + Log: log, + PatchApplier: patchApplier, + SchemaManager: schemaManager, } return tm, nil } @@ -203,16 +211,42 @@ func (tm *TemplateManager) Template(data []byte, vars interface{}) ([]byte, erro } rawVars, _ := yaml.Marshal(vars) - unstructured := make(map[string]interface{}) - if err := yaml.Unmarshal(rawVars, &unstructured); err != nil { + source := make(map[string]interface{}) + if err := yaml.Unmarshal(rawVars, &source); err != nil { return nil, err } var buf bytes.Buffer - if err := tpl.Execute(&buf, unstructured); err != nil { + if err := tpl.Execute(&buf, source); err != nil { return nil, fmt.Errorf("error executing template %s: %v", strings.Split(string(data), "\n")[0], err) } - return buf.Bytes(), nil + + return tm.duckTypeTemplateResult(buf.Bytes()) +} + +func (tm *TemplateManager) duckTypeTemplateResult(objYaml []byte) ([]byte, error) { + obj := &unstructured.Unstructured{} + if err := yaml.Unmarshal(objYaml, &obj.Object); err != nil { + return nil, fmt.Errorf("error parsing template result: %v", err) + } + + version := obj.GetAPIVersion() + parts := strings.Split(version, "/") + var apiVersion, apiGroup string + if len(parts) == 1 { + apiGroup = "" + apiVersion = parts[0] + } else { + apiGroup = parts[0] + apiVersion = parts[1] + } + groupVersionKind := schema.GroupVersionKind{Group: apiGroup, Version: apiVersion, Kind: obj.GetKind()} + + if err := tm.SchemaManager.DuckType(groupVersionKind, obj); err != nil { + return nil, errors.Wrap(err, "failed to ducktype object") + } + + return yaml.Marshal(&obj.Object) } func labelSelectorToString(l metav1.LabelSelector) (string, error) { diff --git a/k8s/template_manager_test.go b/k8s/template_manager_test.go new file mode 100644 index 0000000..cced47d --- /dev/null +++ b/k8s/template_manager_test.go @@ -0,0 +1,80 @@ +package k8s_test + +import ( + "fmt" + "strings" + + "github.com/flanksource/template-operator/k8s" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/yaml" +) + +var testLog = ctrl.Log.WithName("test") + +var _ = Describe("TemplateManager", func() { + Describe("Template", func() { + It("converts PostgresqlDb to zalando Postgresql", func() { + + db := map[string]interface{}{ + "apiVersion": "db.flanksource.com/v1", + "kind": "PostgresqlDB", + "metadata": map[string]interface{}{ + "name": "test1", + "namespace": "postgres-operator", + }, + "spec": map[string]interface{}{ + "replicas": 2, + "parameters": map[string]interface{}{ + "max_connections": "1024", + "shared_buffers": "4759MB", + "work_mem": "475MB", + "maintenance_work_mem": "634MB", + }, + }, + } + + template := ` +apiVersion: acid.zalan.do/v1 +kind: postgresql +metadata: + name: postgres-{{.metadata.name}} + namespace: postgres-operator +spec: + numberOfInstances: "{{ .spec.replicas }}" + postgresql: + parameters: "{{ .spec.parameters | data.ToJSON }}" +` + templateJSON, err := yaml.YAMLToJSON([]byte(template)) + Expect(err).ToNot(HaveOccurred()) + + expectedYaml := ` +apiVersion: acid.zalan.do/v1 +kind: postgresql +metadata: + name: postgres-test1 + namespace: postgres-operator +spec: + numberOfInstances: 2 + postgresql: + parameters: + maintenance_work_mem: 634MB + max_connections: "1024" + shared_buffers: 4759MB + work_mem: 475MB +` + + templateManager, err := k8s.NewTemplateManager(kommonsClient(), testLog) + Expect(err).ToNot(HaveOccurred()) + + result, err := templateManager.Template([]byte(templateJSON), db) + Expect(err).ToNot(HaveOccurred()) + + yml := string(result) + + fmt.Printf("Expected:\n%v\n=======Actual:\n%v\n==========", expectedYaml, string(yml)) + Expect(strings.TrimSpace(string(yml))).To(Equal(strings.TrimSpace(expectedYaml))) + }) + }) +}) From b44378928d9075667a32dbcc1bf14788598ce675 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Thu, 26 Nov 2020 16:23:09 +0200 Subject: [PATCH 14/16] Add error message if crd is missing schema --- k8s/schema_manager.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/k8s/schema_manager.go b/k8s/schema_manager.go index f5442ad..2495637 100644 --- a/k8s/schema_manager.go +++ b/k8s/schema_manager.go @@ -283,6 +283,10 @@ func (m *SchemaManager) findSchemaForCrd(gvk schema.GroupVersionKind) (*spec.Sch } func (m *SchemaManager) parseCrdSchema(crd extv1beta1.CustomResourceDefinition) (*spec.Schema, error) { + if crd.Spec.Validation == nil || crd.Spec.Validation.OpenAPIV3Schema == nil { + return nil, errors.Errorf("crd %s is missing openapi schema validation", crd.Name) + } + bytes, err := json.Marshal(crd.Spec.Validation.OpenAPIV3Schema) if err != nil { return nil, errors.Wrap(err, "failed to encode crd schema to json") From a4750ee5e3d9a4d2c53a4ded83017b3bd065cbb0 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Thu, 26 Nov 2020 18:48:39 +0200 Subject: [PATCH 15/16] Add reflection for bool and nil fix postgresql template --- examples/postgres-operator.yml | 3 +-- examples/postgresqldb.yml | 16 +++++++++++++ k8s/schema_manager.go | 41 ++++++++++++++++++++++++++++++++++ k8s/template_manager_test.go | 4 ++++ 4 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 examples/postgresqldb.yml diff --git a/examples/postgres-operator.yml b/examples/postgres-operator.yml index ed38fe7..00fd8ed 100644 --- a/examples/postgres-operator.yml +++ b/examples/postgres-operator.yml @@ -98,7 +98,6 @@ spec: configMap: name: postgres-exporter-config allowedSourceRanges: null - clone: null dockerImage: docker.io/flanksource/spilo:1.6-p2.flanksource enableShmVolume: true env: @@ -133,6 +132,7 @@ spec: value: "{{.spec.backup.bucket}}" - name: CLONE_WAL_BUCKET_SCOPE_SUFFIX value: / + numberOfInstances: "{{ .spec.replicas }}" patroni: initdb: data-checksums: "true" @@ -192,7 +192,6 @@ spec: requests: cpu: 10m memory: 128Mi - standby: null teamId: postgres tls: null users: diff --git a/examples/postgresqldb.yml b/examples/postgresqldb.yml new file mode 100644 index 0000000..3d08486 --- /dev/null +++ b/examples/postgresqldb.yml @@ -0,0 +1,16 @@ +apiVersion: db.flanksource.com/v1 +kind: PostgresqlDB +metadata: + name: test1 + namespace: postgres-operator +spec: + replicas: 2 + parameters: + max_connections: "1024" + shared_buffers: 4759MB + work_mem: 475MB + maintenance_work_mem: 634MB + storage: + storageClass: vsan + backup: + bucket: foo \ No newline at end of file diff --git a/k8s/schema_manager.go b/k8s/schema_manager.go index 2495637..5f3d404 100644 --- a/k8s/schema_manager.go +++ b/k8s/schema_manager.go @@ -78,6 +78,9 @@ func (m *SchemaManager) DuckType(gvk schema.GroupVersionKind, object *unstructur func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix string) (interface{}, error) { // fmt.Printf("Prefix: %s\n", prefix) + if isNil(object) { + return nil, nil + } v := reflect.ValueOf(object) switch v.Kind() { @@ -166,6 +169,18 @@ func (m *SchemaManager) duckType(schema *spec.Schema, object interface{}, prefix return nil, errors.Wrapf(err, "failed to transform string to type %v", fieldType) } return newValue, nil + case reflect.Bool: + value := v.Bool() + fieldType, err := m.FindTypeForKeyFromSchema(schema, prefix) + if err != nil { + logger.Errorf("failed to find type for key %s: %v", prefix, err) + return value, nil + } + newValue, err := transformBoolToType(value, fieldType) + if err != nil { + return nil, errors.Wrapf(err, "failed to transform bool to type %v", fieldType) + } + return newValue, nil default: return nil, errors.Errorf("Value for field %s for type %T could not be transformed: %d", prefix, v, v.Kind()) } @@ -478,6 +493,21 @@ func transformBytesToType(value []byte, fieldType *TypedField) (interface{}, err return nil, errors.Errorf("could not transform []byte value to types %v format %s", fieldType.Types, fieldType.Format) } +func transformBoolToType(value bool, fieldType *TypedField) (interface{}, error) { + if contains(fieldType.Types, "boolean") { + return value, nil + } + + if contains(fieldType.Types, "string") { + if value { + return "true", nil + } + return "false", nil + } + + return nil, errors.Errorf("could not transform bool value to types %v format %s", fieldType.Types, fieldType.Format) +} + func contains(slice []string, value string) bool { for _, k := range slice { if k == value { @@ -490,3 +520,14 @@ func contains(slice []string, value string) bool { func escapeDot(s string) string { return strings.ReplaceAll(s, ".", "_") } + +func isNil(i interface{}) bool { + if i == nil { + return true + } + switch reflect.TypeOf(i).Kind() { + case reflect.Ptr, reflect.Map, reflect.Array, reflect.Chan, reflect.Slice: + return reflect.ValueOf(i).IsNil() + } + return false +} diff --git a/k8s/template_manager_test.go b/k8s/template_manager_test.go index cced47d..445667c 100644 --- a/k8s/template_manager_test.go +++ b/k8s/template_manager_test.go @@ -43,8 +43,10 @@ metadata: namespace: postgres-operator spec: numberOfInstances: "{{ .spec.replicas }}" + clone: null postgresql: parameters: "{{ .spec.parameters | data.ToJSON }}" + synchronous_mode: false ` templateJSON, err := yaml.YAMLToJSON([]byte(template)) Expect(err).ToNot(HaveOccurred()) @@ -56,6 +58,7 @@ metadata: name: postgres-test1 namespace: postgres-operator spec: + clone: null numberOfInstances: 2 postgresql: parameters: @@ -63,6 +66,7 @@ spec: max_connections: "1024" shared_buffers: 4759MB work_mem: 475MB + synchronous_mode: false ` templateManager, err := k8s.NewTemplateManager(kommonsClient(), testLog) From 2cf6d0208b17db3c3f4fd661fb62cc416bc241a4 Mon Sep 17 00:00:00 2001 From: Teodor Pripoae Date: Mon, 7 Dec 2020 15:18:04 +0200 Subject: [PATCH 16/16] Update karina to 0.21.3 --- test/e2e.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e.sh b/test/e2e.sh index d661fa2..d596e46 100755 --- a/test/e2e.sh +++ b/test/e2e.sh @@ -2,7 +2,7 @@ set -e -export KARINA_VERSION=v0.21.0 +export KARINA_VERSION=v0.21.3 export KARINA="./karina -c test/config.yaml" export KUBECONFIG=~/.kube/config export DOCKER_API_VERSION=1.39 @@ -49,4 +49,4 @@ make deploy go run test/e2e.go -go test ./k8s \ No newline at end of file +go test ./k8s