From bc9f97ff2e71f30679b828fa545b4f38a847b3f0 Mon Sep 17 00:00:00 2001 From: Ruslan Aliev Date: Mon, 3 May 2021 12:56:36 -0500 Subject: [PATCH] Embed validation cfg into phase and plan definition * validation config is now part of airshipctl api * additional CRD locations can be only kustomize entrypoints * changed mechanism to call document-validation executor to allow to pass validation config from phase or plan * kubeval version pinned to the latest 0.16.1 * default k8s version to validate against uplifted to 1.18.6 * default URL with k8s schemas changed to more updated and reliable Change-Id: Ifb24be224d5f0860d323a671b94e28a86debc65b Signed-off-by: Ruslan Aliev Closes: #563 --- krm-functions/kubeval-validator/Dockerfile | 4 +- krm-functions/kubeval-validator/README.md | 5 +- .../image/extract-openapi.py | 14 +- krm-functions/kubeval-validator/image/go.mod | 8 +- krm-functions/kubeval-validator/image/go.sum | 299 ++++++++++-------- krm-functions/kubeval-validator/image/main.go | 118 ++----- .../local-resource/example-use.yaml | 58 ++-- .../function/validator/kustomization.yaml | 2 - manifests/function/validator/template.yaml | 26 -- manifests/phases/executors.yaml | 15 +- .../site/test-site/phases/kustomization.yaml | 2 - .../test-site/phases/validation-config.yaml | 81 ----- manifests/type/gating/plan.yaml | 14 +- pkg/api/v1alpha1/genericcontainer_types.go | 2 - pkg/api/v1alpha1/phase_types.go | 27 +- pkg/api/v1alpha1/phaseplan_types.go | 5 +- pkg/api/v1alpha1/zz_generated.deepcopy.go | 37 +++ pkg/document/constants.go | 19 +- pkg/document/selectors.go | 13 +- pkg/phase/client.go | 49 +-- pkg/phase/client_test.go | 82 ++++- pkg/phase/command.go | 3 - pkg/phase/command_test.go | 2 + pkg/phase/printers_test.go | 2 + .../invalid_validation_site/metadata.yaml | 10 + .../phases/cluster_map.yaml | 12 + .../phases/kube_apply.yaml | 10 + .../phases/kubernetes_apply.yaml | 12 + .../phases/kustomization.yaml | 4 + .../valid_validation_site/metadata.yaml | 10 + .../phases/cluster_map.yaml | 12 + .../phases/kube_apply.yaml | 24 ++ .../phases/kubernetes_apply.yaml | 12 + .../phases/kustomization.yaml | 5 + .../phases/validation_exec.yaml | 9 + pkg/util/tableprinter_test.go | 1 + 36 files changed, 567 insertions(+), 441 deletions(-) delete mode 100755 manifests/function/validator/kustomization.yaml delete mode 100755 manifests/function/validator/template.yaml delete mode 100755 manifests/site/test-site/phases/validation-config.yaml create mode 100755 pkg/phase/testdata/invalid_validation_site/metadata.yaml create mode 100755 pkg/phase/testdata/invalid_validation_site/phases/cluster_map.yaml create mode 100755 pkg/phase/testdata/invalid_validation_site/phases/kube_apply.yaml create mode 100755 pkg/phase/testdata/invalid_validation_site/phases/kubernetes_apply.yaml create mode 100755 pkg/phase/testdata/invalid_validation_site/phases/kustomization.yaml create mode 100755 pkg/phase/testdata/valid_validation_site/metadata.yaml create mode 100755 pkg/phase/testdata/valid_validation_site/phases/cluster_map.yaml create mode 100755 pkg/phase/testdata/valid_validation_site/phases/kube_apply.yaml create mode 100755 pkg/phase/testdata/valid_validation_site/phases/kubernetes_apply.yaml create mode 100755 pkg/phase/testdata/valid_validation_site/phases/kustomization.yaml create mode 100755 pkg/phase/testdata/valid_validation_site/phases/validation_exec.yaml diff --git a/krm-functions/kubeval-validator/Dockerfile b/krm-functions/kubeval-validator/Dockerfile index f223337d7..c67532f50 100644 --- a/krm-functions/kubeval-validator/Dockerfile +++ b/krm-functions/kubeval-validator/Dockerfile @@ -35,10 +35,10 @@ RUN echo "**** install Python ****" && \ echo "**** install pip ****" && \ python3 -m ensurepip && \ rm -r /usr/lib/python*/ensurepip && \ - pip3 install --no-cache --upgrade pip setuptools wheel && \ + pip3 install --no-cache-dir --upgrade pip setuptools wheel && \ if [ ! -e /usr/bin/pip ]; then ln -s pip3 /usr/bin/pip ; fi -RUN pip3 install 'ruamel.yaml==0.16.13' 'openapi2jsonschema==0.9.0' openapi-spec-validator +RUN pip3 install --no-cache-dir 'ruamel.yaml==0.16.13' 'openapi2jsonschema==0.9.0' 'openapi-spec-validator==0.3.0' COPY --from=function /usr/local/bin/config-function /usr/local/bin/config-function COPY image/extract-openapi.py /usr/local/bin/ CMD ["config-function"] diff --git a/krm-functions/kubeval-validator/README.md b/krm-functions/kubeval-validator/README.md index 9edacccb5..d4c5e2992 100644 --- a/krm-functions/kubeval-validator/README.md +++ b/krm-functions/kubeval-validator/README.md @@ -10,12 +10,13 @@ The function is implemented as an [image](image), and built using `make image`. ### Function configuration A number of settings can be modified for `kubeval` in the struct `Spec`. See -the `Config` struct definition in [main.go](image/main.go) for documentation. +the `Spec` struct definition in [main.go](image/main.go) for the documentation. ## Function invocation -The function by running validate command via `airshipctl`: +The function invokes by running validate command via `airshipctl`: + airshipctl plan validate airshipctl phase validate This exists non-zero if kubeval detects an invalid Resource. diff --git a/krm-functions/kubeval-validator/image/extract-openapi.py b/krm-functions/kubeval-validator/image/extract-openapi.py index d9d730c22..207fe0aa8 100755 --- a/krm-functions/kubeval-validator/image/extract-openapi.py +++ b/krm-functions/kubeval-validator/image/extract-openapi.py @@ -13,9 +13,7 @@ # limitations under the License. from os import getenv -from os.path import basename, isfile, join -from urllib import request -from urllib.parse import urlparse +from os.path import isfile, join from openapi2jsonschema import command from openapi2jsonschema.command import debug, info, error @@ -34,7 +32,6 @@ components: """ crd_kind = "CustomResourceDefinition" crd_list = "/workdir/schemas-cache/crd-list" -phase_rendered = "phase-rendered.yaml" rewrite_env = "VALIDATOR_REWRITE_SCHEMAS" yaml = YAML() @@ -105,15 +102,14 @@ def run(): with open(crd_list, 'r') as crd_list_file: # read file with CRD locations crd_list_data = yaml.load(crd_list_file) - for crd_path in crd_list_data['crdList']: - crd_data = yaml.load_all(request.urlopen(crd_path).read().decode('utf-8')) # read CRD from URL + with open(crd_list_data['crdList'], 'r') as yaml_file: + crd_data = yaml.load_all(yaml_file) # read CRDs for crd in crd_data: try: if check_yaml_kind(crd): - process_crd(crd, schemas, crd_list_data["schemasLocation"], - basename(urlparse(crd_path).path) == phase_rendered and getenv(rewrite_env) is not None) + process_crd(crd, schemas, crd_list_data["schemasLocation"], getenv(rewrite_env) is not None) except Exception as exc: - error("An error occurred while processing CRD data from {}\n{}".format(crd_path, exc)) + error("An error occurred while processing CRD data from phase rendered docs\n{}".format(exc)) # Validate output V3 spec try: diff --git a/krm-functions/kubeval-validator/image/go.mod b/krm-functions/kubeval-validator/image/go.mod index 229cc79f1..371c7dee0 100644 --- a/krm-functions/kubeval-validator/image/go.mod +++ b/krm-functions/kubeval-validator/image/go.mod @@ -1,8 +1,8 @@ -module opendev.org/airship/airshipctl/functions/validator-kubeval/image +module opendev.org/airship/airshipctl/krm-functions/kubeval-validator/image -go 1.13 +go 1.15 require ( - github.com/instrumenta/kubeval v0.0.0-20190918223246-8d013ec9fc56 - sigs.k8s.io/kustomize/kyaml v0.7.1 + github.com/instrumenta/kubeval v0.16.1 + sigs.k8s.io/kustomize/kyaml v0.10.6 ) diff --git a/krm-functions/kubeval-validator/image/go.sum b/krm-functions/kubeval-validator/image/go.sum index d35ac646f..ff98f3ca7 100644 --- a/krm-functions/kubeval-validator/image/go.sum +++ b/krm-functions/kubeval-validator/image/go.sum @@ -1,7 +1,19 @@ cloud.google.com/go v0.26.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/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -14,12 +26,16 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy 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/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -27,7 +43,9 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -38,30 +56,20 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/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/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk= -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/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 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-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-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-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= @@ -108,118 +116,122 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+ github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= 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.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/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357 h1:Rem2+U35z1QtPQc6r+WolF7yXiefXqDKyk+lN2pE164= -github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0 h1:j30noezaCfvNLcdMYSvHLv81DxYRSt1grlpseG67vhU= -github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +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-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/instrumenta/kubeval v0.0.0-20190918223246-8d013ec9fc56 h1:kKOrEaxR9KvCDdnQqjiBxbaeJg/goLvJvW0lno6aWm4= -github.com/instrumenta/kubeval v0.0.0-20190918223246-8d013ec9fc56/go.mod h1:bpiMYvNpVxWjdJsS0hDRu9TrobT5GfWCZwJseGUstxE= +github.com/instrumenta/kubeval v0.16.1 h1:PticHzCrCqRjwfse1YmlgsN5313Du1PyJ2QnRGVNdVg= +github.com/instrumenta/kubeval v0.16.1/go.mod h1:K9fO5e4B/bznyi5cKzthudanzcPzPBP2OuB5uE9G1TU= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/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= -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.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o= -github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -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-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/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -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/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/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-toml v0.0.0-20180724185102-c2dbbc24a979/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -227,29 +239,29 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z 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/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/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 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/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.0-20180820174524-ff0d02e85550/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/jwalterweatherman v0.0.0-20180814060501-14d3d4c51834/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v0.0.0-20180821114517-d929dcbb1086/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.1.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -257,10 +269,10 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH 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.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -279,136 +291,161 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 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.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +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-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +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/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/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-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-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= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180821044426-4ea2f632f6e9/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-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c h1:Vco5b+cuG5NNfORVxZy6bYZQ7rsigisU1WQFkvQ0L5E= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/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-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.0.0-20180810153555-6e3c4e7365dd/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/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/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/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-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +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-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 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.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -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= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.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.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo= -gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/apimachinery v0.20.4 h1:vhxQ0PPUUU2Ns1b9r4/UFp13UPs8cw2iOoTjnY9faa0= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -sigs.k8s.io/kustomize/kyaml v0.7.1 h1:Ih6SJPvfKYfZaIFWUa2YAyg/0ZSTpA3LFjR/hv7+8ao= -sigs.k8s.io/kustomize/kyaml v0.7.1/go.mod h1:ne3F9JPhW2wrVaLslxBsEe6MQJQ9YK5rUutrdhBWXwI= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +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.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sigs.k8s.io/kustomize/kyaml v0.10.6 h1:xUJxc/k8JoWqHUahaB8DTqY0KwEPxTbTGStvW8TOcDc= +sigs.k8s.io/kustomize/kyaml v0.10.6/go.mod h1:K9yg1k/HB/6xNOf5VH3LhTo1DK9/5ykSZO5uIv+Y/1k= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/krm-functions/kubeval-validator/image/main.go b/krm-functions/kubeval-validator/image/main.go index 9de47272c..ba8751ee5 100644 --- a/krm-functions/kubeval-validator/image/main.go +++ b/krm-functions/kubeval-validator/image/main.go @@ -20,7 +20,6 @@ import ( "fmt" "io" "io/ioutil" - "net/url" "os" "os/exec" "path/filepath" @@ -32,20 +31,18 @@ import ( ) const ( - manifestsMountPoint = "/manifests" - schemaLocationDir = "/workdir/schemas-cache" - fileScheme = "file" - openAPISchemaFile = "openapischema" - crdKind = "CustomResourceDefinition" - kubevalOptsKind = "KubevalOptions" - phaseRenderedFile = "phase-rendered.yaml" - crdListFile = "crd-list" - cleanupEnv = "VALIDATOR_PREVENT_CLEANUP" - planEnv = "VALIDATOR_PLAN_VALIDATION" + schemaLocationDir = "/workdir/schemas-cache" + fileScheme = "file://" + openAPISchemaFile = "openapischema" + crdKind = "CustomResourceDefinition" + phaseRenderedFile = "phase-rendered.yaml" + crdListFile = "crd-list" + cleanupEnv = "VALIDATOR_PREVENT_CLEANUP" - defaultKubernetesVersion = "1.16.0" + defaultKubernetesVersion = "1.18.6" defaultStrict = true defaultIgnoreMissingSchemas = false + defaultSchemaLocation = "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/" ) func main() { @@ -73,49 +70,31 @@ type kubevalFilter struct { rw *kio.ByteReadWriter } -// CRDConfigMap is a map with appropriate validation configs for plans/phases -type CRDConfigMap map[string]*CRDSpec - -// Config defines the input config schema as a struct -type Config struct { - Spec *Spec `yaml:"siteConfig"` - PlanName string `yaml:"planName,omitempty"` - PlanConfigs CRDConfigMap `yaml:"planConfigs,omitempty"` - PhaseName string `yaml:"phaseName,omitempty"` - PhaseConfigs CRDConfigMap `yaml:"phaseConfigs,omitempty"` -} - // Spec holds main kubeval parameters type Spec struct { // Strict disallows additional properties not in schema if set - Strict bool `yaml:"strict,omitempty"` + Strict *bool `yaml:"strict,omitempty"` // IgnoreMissingSchemas skips validation for resource // definitions without a schema. - IgnoreMissingSchemas bool `yaml:"ignoreMissingSchemas,omitempty"` + IgnoreMissingSchemas *bool `yaml:"ignoreMissingSchemas,omitempty"` // KubernetesVersion is the version of Kubernetes to validate - // against (default "master"). + // against (default "1.18.6"). KubernetesVersion string `yaml:"kubernetesVersion,omitempty"` // SchemaLocation is the base URL from which to search for schemas. // It can be either a remote location or a local directory SchemaLocation string `yaml:"schemaLocation,omitempty"` -} -// CRDSpec holds special options for plan/phase which kinds to skip and which additional CRDs to include -type CRDSpec struct { // KindsToSkip defines Kinds which will be skipped during validation KindsToSkip []string `yaml:"kindsToSkip,omitempty"` - - // CRDList defines additional CRD locations - CRDList []string `yaml:"crdList,omitempty"` } // CrdConfig is a small struct to process CRD list type CrdConfig struct { - SchemasLocation string `yaml:"schemasLocation"` - CrdList []string `yaml:"crdList"` + SchemasLocation string `yaml:"schemasLocation"` + CrdList string `yaml:"crdList"` } // Filter checks each resource for validity, otherwise returning an error @@ -126,27 +105,12 @@ func (f kubevalFilter) Filter(in []*yaml.RNode) ([]*yaml.RNode, error) { } kubevalConfig := kubeval.NewDefaultConfig() - kubevalConfig.Strict = cfg.Spec.Strict - kubevalConfig.IgnoreMissingSchemas = cfg.Spec.IgnoreMissingSchemas - kubevalConfig.KubernetesVersion = cfg.Spec.KubernetesVersion - kubevalConfig.SchemaLocation = cfg.Spec.SchemaLocation - kubevalConfig.AdditionalSchemaLocations = []string{fileScheme + "://" + schemaLocationDir} - kubevalConfig.KindsToSkip = []string{crdKind, kubevalOptsKind} - var crdList []string - - if _, plan := os.LookupEnv(planEnv); plan { - // Setup plan specific options - if _, exists := cfg.PlanConfigs[cfg.PlanName]; exists { - kubevalConfig.KindsToSkip = append(kubevalConfig.KindsToSkip, cfg.PlanConfigs[cfg.PlanName].KindsToSkip...) - crdList = cfg.PlanConfigs[cfg.PlanName].CRDList - } - } else { - // Setup phase specific options - if _, exists := cfg.PhaseConfigs[cfg.PhaseName]; exists { - kubevalConfig.KindsToSkip = append(kubevalConfig.KindsToSkip, cfg.PhaseConfigs[cfg.PhaseName].KindsToSkip...) - crdList = cfg.PhaseConfigs[cfg.PhaseName].CRDList - } - } + kubevalConfig.Strict = *cfg.Strict + kubevalConfig.IgnoreMissingSchemas = *cfg.IgnoreMissingSchemas + kubevalConfig.KubernetesVersion = cfg.KubernetesVersion + kubevalConfig.SchemaLocation = cfg.SchemaLocation + kubevalConfig.AdditionalSchemaLocations = []string{fileScheme + schemaLocationDir} + kubevalConfig.KindsToSkip = append(cfg.KindsToSkip, crdKind) // Calculate schema location directory for kubeval and openapi2jsonschema based on options schemasLocation := filepath.Join(schemaLocationDir, @@ -177,13 +141,9 @@ func (f kubevalFilter) Filter(in []*yaml.RNode) ([]*yaml.RNode, error) { if err = ioutil.WriteFile(renderedCRDFile, buf.Bytes(), 0600); err != nil { return nil, err } - // Prepend rendered CRD to give them priority for processing - crdList = append([]string{renderedCRDFile}, crdList...) - } - if len(crdList) > 0 { // Process each additional CRD in the list (CRD -> OpenAPIV3 Schema -> Json Schema) - if err := processCRDList(crdList, schemasLocation); err != nil { + if err := processCRDList(renderedCRDFile, schemasLocation); err != nil { return nil, err } } @@ -259,15 +219,15 @@ func checkResults(results []kubeval.ValidationResult) error { return nil } -// parseConfig parses the functionConfig into an Config struct. -func (f *kubevalFilter) parseConfig() (*Config, error) { +// parseConfig parses the functionConfig into a Spec struct. +func (f *kubevalFilter) parseConfig() (*Spec, error) { // Initialize default values - cfg := &Config{ - Spec: &Spec{ - Strict: defaultStrict, - IgnoreMissingSchemas: defaultIgnoreMissingSchemas, - KubernetesVersion: defaultKubernetesVersion, - }, + boolPtr := func(b bool) *bool { return &b } + cfg := &Spec{ + Strict: boolPtr(defaultStrict), + IgnoreMissingSchemas: boolPtr(defaultIgnoreMissingSchemas), + KubernetesVersion: defaultKubernetesVersion, + SchemaLocation: defaultSchemaLocation, } if err := yaml.Unmarshal([]byte(f.rw.FunctionConfig.MustString()), &cfg); err != nil { @@ -278,26 +238,10 @@ func (f *kubevalFilter) parseConfig() (*Config, error) { // processCRDList takes each CRD from crdList, converts paths to URLs, // saves it to file and calls conversion script -func processCRDList(crdList []string, schemasLocation string) error { +func processCRDList(crdList string, schemasLocation string) error { configMap := CrdConfig{ SchemasLocation: schemasLocation, - CrdList: []string{}, - } - // Walk through all additional CRD - for _, crdPath := range crdList { - // Parse provided CRD path as URL - crdURL, err := url.Parse(crdPath) - if err != nil { - return err - } - // Add 'file' scheme if not specified and convert relative path to absolute - if crdURL.Scheme == "" { - crdURL.Scheme = fileScheme - if filepath.Base(crdPath) != phaseRenderedFile { - crdURL.Path = filepath.Join(manifestsMountPoint, crdPath) - } - } - configMap.CrdList = append(configMap.CrdList, crdURL.String()) + CrdList: crdList, } crdData, err := yaml.Marshal(configMap) diff --git a/krm-functions/kubeval-validator/local-resource/example-use.yaml b/krm-functions/kubeval-validator/local-resource/example-use.yaml index a2fdbfab1..81bd9355b 100644 --- a/krm-functions/kubeval-validator/local-resource/example-use.yaml +++ b/krm-functions/kubeval-validator/local-resource/example-use.yaml @@ -10,44 +10,24 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This kind is used as 'config' field in GenericContainer executor +# The validation config should be defined as part of appropriate "Phase" or "Plan" kind (config.validation field) apiVersion: airshipit.org/v1alpha1 -kind: KubevalOptions +kind: Phase metadata: - name: kubeval-options - labels: - airshipit.org/deploy-k8s: "false" # won't be deployed to k8s -# Main config for site -siteConfig: - # Disallow additional properties not in schema - default "true" - strict: true - # Version of Kubernetes to validate against - default "1.16.0" - kubernetesVersion: "1.16.0" - # Skip validation for resource definitions without a schema - default "false" - ignoreMissingSchemas: false -# Current plan to validate; validator searches for the appropriate planConfig in planConfigs map -# Uses only in case of plan validation; planName sets up automatically by templater using appropriate env variable -planName: AIRSHIPCTL_CURRENT_PLAN -# planConfigs is a map with validation configs for specified plans; has the following structure: -# : -# kindsToSkip: [] (optional) -# crdList: [] (optional) -planConfigs: - phasePlan: - kindsToSkip: # list of kinds to skip from validation - - KindToSkip - crdList: # list of URLs to additional CRDs; could be a file located in manifests/ or an external URL - - url/to/crd.yaml -# Current phase to validate; validator searches for the appropriate phaseConfig in phaseConfigs map -# Uses only in case of plan validation; phaseName sets up automatically by templater using appropriate env variable -phaseName: AIRSHIPCTL_CURRENT_PHASE -# phaseConfigs is a map with validation configs for specified phases; has the following structure: -# : -# kindsToSkip: [] (optional) -# crdList: [] (optional) -phaseConfigs: - initinfra-ephemeral: - kindsToSkip: # list of kinds to skip from validation - - KindToSkip - crdList: # list of URLs to additional CRDs; could be a file located in manifests/ or an external URL - - url/to/crd.yaml + name: phase-name +config: + validation: + # Disallow additional properties not in schema - default "true" + strict: true + # Version of Kubernetes to validate against - default "1.18.6" + kubernetesVersion: "1.18.6" + # Skip validation for resource definitions without a schema - default "false" + ignoreMissingSchemas: false + # List of kind names to skip from validation + kindsToSkip: + - Clusterctl + - VariableCatalogue + # list of kustomize entrypoints located in "TARGET_PATH" with additional CRDs + crdList: + - airshipctl/manifests/function/airshipctl-schemas + documentEntryPoint: ephemeral/initinfra diff --git a/manifests/function/validator/kustomization.yaml b/manifests/function/validator/kustomization.yaml deleted file mode 100755 index b1e944410..000000000 --- a/manifests/function/validator/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -generators: - - template.yaml diff --git a/manifests/function/validator/template.yaml b/manifests/function/validator/template.yaml deleted file mode 100755 index 5eb129337..000000000 --- a/manifests/function/validator/template.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: airshipit.org/v1alpha1 -kind: Templater -metadata: - name: validator-config-patch-template - annotations: - config.kubernetes.io/function: | - container: - image: localhost/templater - envs: - - AIRSHIPCTL_CURRENT_PHASE - - AIRSHIPCTL_CURRENT_PLAN -template: | - {{- $currentPhase := env "AIRSHIPCTL_CURRENT_PHASE" }} - {{- $currentPlan := env "AIRSHIPCTL_CURRENT_PLAN" }} - apiVersion: builtin - kind: PatchStrategicMergeTransformer - metadata: - name: smp - patches: |- - --- - apiVersion: airshipit.org/v1alpha1 - kind: KubevalOptions - metadata: - name: kubeval-options - phaseName: {{ $currentPhase }} - planName: {{ $currentPlan }} diff --git a/manifests/phases/executors.yaml b/manifests/phases/executors.yaml index fad22ad11..f2f3ee619 100644 --- a/manifests/phases/executors.yaml +++ b/manifests/phases/executors.yaml @@ -391,22 +391,13 @@ spec: image: localhost/kubeval-validator envVars: - VALIDATOR_PREVENT_CLEANUP # Validator won't cleanup its working directory after finish - - VALIDATOR_PLAN_VALIDATION # Validator will not use phase-specific settings for validation - VALIDATOR_REWRITE_SCHEMAS # Validator will rewrite schemas for kubeval if they already exist mounts: - - type: bind - src: airshipctl/manifests - dst: /manifests - rw: false - type: bind src: ~/.airship dst: /workdir rw: true hostNetwork: true -configRef: - apiVersion: airshipit.org/v1alpha1 - kind: KubevalOptions - name: kubeval-options --- apiVersion: airshipit.org/v1alpha1 kind: GenericContainer @@ -416,9 +407,9 @@ spec: image: localhost/toolbox hostNetwork: true envVars: - - RESOURCE_GROUP_FILTER=metal3.io - - RESOURCE_VERSION_FILTER=v1alpha1 - - RESOURCE_KIND_FILTER=BareMetalHost + - RESOURCE_GROUP_FILTER=metal3.io + - RESOURCE_VERSION_FILTER=v1alpha1 + - RESOURCE_KIND_FILTER=BareMetalHost configRef: kind: ConfigMap name: kubectl-pause-bmh diff --git a/manifests/site/test-site/phases/kustomization.yaml b/manifests/site/test-site/phases/kustomization.yaml index d1c88e771..a519d307a 100644 --- a/manifests/site/test-site/phases/kustomization.yaml +++ b/manifests/site/test-site/phases/kustomization.yaml @@ -3,8 +3,6 @@ resources: - ../../../phases - ../target/catalogues - catalogue.yaml - - validation-config.yaml transformers: - ../../../function/clusterctl/replacements - ../../../function/bootstrap/replacements - - ../../../function/validator diff --git a/manifests/site/test-site/phases/validation-config.yaml b/manifests/site/test-site/phases/validation-config.yaml deleted file mode 100755 index 01d60d52f..000000000 --- a/manifests/site/test-site/phases/validation-config.yaml +++ /dev/null @@ -1,81 +0,0 @@ -apiVersion: airshipit.org/v1alpha1 -kind: KubevalOptions -metadata: - name: kubeval-options - labels: - airshipit.org/deploy-k8s: "false" -siteConfig: - strict: true - kubernetesVersion: "1.16.0" - ignoreMissingSchemas: false -planName: AIRSHIPCTL_CURRENT_PLAN -planConfigs: - deploy-gating: - kindsToSkip: - - Clusterctl - - VariableCatalogue - crdList: - - function/airshipctl-schemas/airshipit.org_versionscatalogues.yaml - - function/airshipctl-schemas/airshipit.org_networkcatalogues.yaml - iso: - kindsToSkip: - - VariableCatalogue - - RemoteDirectConfiguration - crdList: - - function/airshipctl-schemas/airshipit.org_versionscatalogues.yaml - - function/airshipctl-schemas/airshipit.org_networkcatalogues.yaml - - global/crd/baremetal-operator/metal3.io_baremetalhosts_crd.yaml -phaseName: AIRSHIPCTL_CURRENT_PHASE -phaseConfigs: - initinfra-ephemeral: - kindsToSkip: - - Clusterctl - - VariableCatalogue - crdList: - - function/airshipctl-schemas/airshipit.org_versionscatalogues.yaml - - function/airshipctl-schemas/airshipit.org_networkcatalogues.yaml - clusterctl-init-ephemeral: - crdList: - - function/cert-manager/v1.1.0/upstream/cert-manager.yaml - controlplane-ephemeral: - kindsToSkip: - - VariableCatalogue - crdList: - - function/airshipctl-schemas/airshipit.org_versionscatalogues.yaml - - function/airshipctl-schemas/airshipit.org_networkcatalogues.yaml - - function/capi/v0.3.7/crd/bases/cluster.x-k8s.io_clusters.yaml - - function/cacpk/v0.3.7/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml - - function/capm3/v0.4.0/crd/bases/infrastructure.cluster.x-k8s.io_metal3clusters.yaml - - function/capm3/v0.4.0/crd/bases/infrastructure.cluster.x-k8s.io_metal3machinetemplates.yaml - - global/crd/baremetal-operator/metal3.io_baremetalhosts_crd.yaml - clusterctl-init-target: - crdList: - - function/cert-manager/v1.1.0/upstream/cert-manager.yaml - initinfra-target: - kindsToSkip: - - Clusterctl - - VariableCatalogue - crdList: - - function/airshipctl-schemas/airshipit.org_networkcatalogues.yaml - - function/airshipctl-schemas/airshipit.org_versionscatalogues.yaml - workers-target: - crdList: - - global/crd/baremetal-operator/metal3.io_baremetalhosts_crd.yaml - workers-classification: - kindsToSkip: - - VariableCatalogue - crdList: - - function/airshipctl-schemas/airshipit.org_networkcatalogues.yaml - - function/airshipctl-schemas/airshipit.org_versionscatalogues.yaml - - function/cabpk/v0.3.7/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml - - function/capi/v0.3.7/crd/bases/cluster.x-k8s.io_machinedeployments.yaml - - function/capm3/v0.4.0/crd/bases/infrastructure.cluster.x-k8s.io_metal3machinetemplates.yaml - - function/hwcc/crd/bases/metal3.io_hardwareclassifications.yaml - workload-target: - kindsToSkip: - - VariableCatalogue - crdList: - - function/airshipctl-schemas/airshipit.org_networkcatalogues.yaml - - function/airshipctl-schemas/airshipit.org_versionscatalogues.yaml - - function/flux/helm-controller/upstream/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml - - function/flux/source-controller/upstream/crd/bases/source.toolkit.fluxcd.io_helmrepositories.yaml diff --git a/manifests/type/gating/plan.yaml b/manifests/type/gating/plan.yaml index a7138d0d8..85981930f 100644 --- a/manifests/type/gating/plan.yaml +++ b/manifests/type/gating/plan.yaml @@ -131,6 +131,12 @@ phases: # To get ConfigMap for this phase, execute `airshipctl phase render --source config -k ConfigMap` # and find ConfigMap with name kubectl-check-ingress-ctrl - name: kubectl-check-ingress-ctrl-target +validation: + kindsToSkip: + - Clusterctl + - VariableCatalogue + crdList: + - airshipctl/manifests/function/airshipctl-schemas --- apiVersion: airshipit.org/v1alpha1 kind: PhasePlan @@ -140,4 +146,10 @@ description: "Runs phases to build iso image" phases: - name: iso-cloud-init-data - name: iso-build-image - +validation: + kindsToSkip: + - RemoteDirectConfiguration + - VariableCatalogue + crdList: + - airshipctl/manifests/function/airshipctl-schemas + - airshipctl/manifests/global/crd/baremetal-operator diff --git a/pkg/api/v1alpha1/genericcontainer_types.go b/pkg/api/v1alpha1/genericcontainer_types.go index 9e48f47e3..8d499ab79 100644 --- a/pkg/api/v1alpha1/genericcontainer_types.go +++ b/pkg/api/v1alpha1/genericcontainer_types.go @@ -38,8 +38,6 @@ const ( // ValidatorPreventCleanup is an env variable that prevents validator to clean up its working directory after finish ValidatorPreventCleanup = "VALIDATOR_PREVENT_CLEANUP" - // ValidatorPlanValidation is an env variable that tells validator not to use phase-specific config for validation - ValidatorPlanValidation = "VALIDATOR_PLAN_VALIDATION" ) // +kubebuilder:object:root=true diff --git a/pkg/api/v1alpha1/phase_types.go b/pkg/api/v1alpha1/phase_types.go index f2307806f..5d1795e78 100644 --- a/pkg/api/v1alpha1/phase_types.go +++ b/pkg/api/v1alpha1/phase_types.go @@ -29,13 +29,38 @@ type Phase struct { } // PhaseConfig represents configuration for a particular phase. It contains a reference to -// phase runner object which should contain runner configuration +// phase runner object which should contain runner configuration and validation configuration type PhaseConfig struct { ExecutorRef *corev1.ObjectReference `json:"executorRef"` SiteWideKubeconfig bool `json:"siteWideKubeconfig,omitempty"` + ValidationCfg ValidationConfig `json:"validation"` DocumentEntryPoint string `json:"documentEntryPoint"` } +// ValidationConfig represents configuration needed for static validation +type ValidationConfig struct { + // Strict disallows additional properties not in schema if set + Strict *bool `json:"strict,omitempty"` + + // IgnoreMissingSchemas skips validation for resource + // definitions without a schema. + IgnoreMissingSchemas *bool `json:"ignoreMissingSchemas,omitempty"` + + // KubernetesVersion is the version of Kubernetes to validate + // against (default "1.18.6"). + KubernetesVersion string `json:"kubernetesVersion,omitempty"` + + // SchemaLocation is the base URL from which to search for schemas. + // It can be either a remote location or a local directory + SchemaLocation string `json:"schemaLocation,omitempty"` + + // KindsToSkip defines Kinds which will be skipped during validation + KindsToSkip []string `json:"kindsToSkip,omitempty"` + + // CRDList defines list of kustomize entrypoints located in "TARGET_PATH" where to find additional CRD + CRDList []string `json:"crdList,omitempty"` +} + // DefaultPhase can be used to safely unmarshal phase object without nil pointers func DefaultPhase() *Phase { return &Phase{ diff --git a/pkg/api/v1alpha1/phaseplan_types.go b/pkg/api/v1alpha1/phaseplan_types.go index 0a641f5fe..466b8e66c 100644 --- a/pkg/api/v1alpha1/phaseplan_types.go +++ b/pkg/api/v1alpha1/phaseplan_types.go @@ -24,8 +24,9 @@ import ( type PhasePlan struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Description string `json:"description,omitempty"` - Phases []PhaseStep `json:"phases,omitempty"` + Description string `json:"description,omitempty"` + Phases []PhaseStep `json:"phases,omitempty"` + ValidationCfg ValidationConfig `json:"validation"` } // PhaseStep represents phase (or step) within a phase plan diff --git a/pkg/api/v1alpha1/zz_generated.deepcopy.go b/pkg/api/v1alpha1/zz_generated.deepcopy.go index 04f954c9c..7e26181d6 100644 --- a/pkg/api/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/api/v1alpha1/zz_generated.deepcopy.go @@ -1319,6 +1319,7 @@ func (in *PhaseConfig) DeepCopyInto(out *PhaseConfig) { *out = new(v1.ObjectReference) **out = **in } + in.ValidationCfg.DeepCopyInto(&out.ValidationCfg) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PhaseConfig. @@ -1341,6 +1342,7 @@ func (in *PhasePlan) DeepCopyInto(out *PhasePlan) { *out = make([]PhaseStep, len(*in)) copy(*out, *in) } + in.ValidationCfg.DeepCopyInto(&out.ValidationCfg) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PhasePlan. @@ -1640,6 +1642,41 @@ func (in *Templater) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ValidationConfig) DeepCopyInto(out *ValidationConfig) { + *out = *in + if in.Strict != nil { + in, out := &in.Strict, &out.Strict + *out = new(bool) + **out = **in + } + if in.IgnoreMissingSchemas != nil { + in, out := &in.IgnoreMissingSchemas, &out.IgnoreMissingSchemas + *out = new(bool) + **out = **in + } + if in.KindsToSkip != nil { + in, out := &in.KindsToSkip, &out.KindsToSkip + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.CRDList != nil { + in, out := &in.CRDList, &out.CRDList + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValidationConfig. +func (in *ValidationConfig) DeepCopy() *ValidationConfig { + if in == nil { + return nil + } + out := new(ValidationConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VersionsCatalogue) DeepCopyInto(out *VersionsCatalogue) { *out = *in diff --git a/pkg/document/constants.go b/pkg/document/constants.go index 97096b96b..81014c9f4 100644 --- a/pkg/document/constants.go +++ b/pkg/document/constants.go @@ -37,14 +37,17 @@ const ( ClusterctlMetadataVersion = "v1alpha3" ClusterctlMetadataGroup = "clusterctl.cluster.x-k8s.io" - // DocumentValidationGroup defines Group for document-validation container - DocumentValidationGroup = "airshipit.org" - // DocumentValidationVersion defines Version for document-validation container - DocumentValidationVersion = "v1alpha1" - // DocumentValidationKind defines Kind for document-validation container - DocumentValidationKind = "GenericContainer" - // DocumentValidationName defines Name for document-validation container - DocumentValidationName = "document-validation" + // ValidatorGroup defines Group for document-validation container + ValidatorGroup = "airshipit.org" + // ValidatorVersion defines Version for document-validation container + ValidatorVersion = "v1alpha1" + // ValidatorKind defines Kind for document-validation container + ValidatorKind = "GenericContainer" + // ValidatorName defines Name for document-validation container + ValidatorName = "document-validation" + + // CRDKind is a kind for custom resource definition documents + CRDKind = "CustomResourceDefinition" ) // KustomizationFile is used for kustomization file diff --git a/pkg/document/selectors.go b/pkg/document/selectors.go index b6ce34a0d..f0639317a 100644 --- a/pkg/document/selectors.go +++ b/pkg/document/selectors.go @@ -192,8 +192,13 @@ func NewClusterctlMetadataSelector() Selector { // NewValidatorExecutorSelector returns selector to get validator executor documents func NewValidatorExecutorSelector() Selector { - return NewSelector().ByGvk(DocumentValidationGroup, - DocumentValidationVersion, - DocumentValidationKind). - ByName(DocumentValidationName) + return NewSelector().ByGvk(ValidatorGroup, + ValidatorVersion, + ValidatorKind). + ByName(ValidatorName) +} + +// NewCRDSelector returns selector to get custom resource definition documents +func NewCRDSelector() Selector { + return NewSelector().ByKind(CRDKind) } diff --git a/pkg/phase/client.go b/pkg/phase/client.go index 6c0dbf8d3..33fe4e1f7 100644 --- a/pkg/phase/client.go +++ b/pkg/phase/client.go @@ -21,6 +21,7 @@ import ( "path/filepath" "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/yaml" "opendev.org/airship/airshipctl/pkg/api/v1alpha1" cctlclient "opendev.org/airship/airshipctl/pkg/clusterctl/client" @@ -154,16 +155,20 @@ func (p *phase) Validate() error { if err != nil { return err } - if err = executor.Validate(); err != nil { + return validate(executor, p.helper, p.apiObj.Config.ValidationCfg) +} + +func validate(executor ifc.Executor, helper ifc.Helper, validationCfg v1alpha1.ValidationConfig) error { + if err := executor.Validate(); err != nil { return err } buf := &bytes.Buffer{} - if err = executor.Render(buf, ifc.RenderOptions{FilterSelector: document.NewSelector()}); err != nil { + if err := executor.Render(buf, ifc.RenderOptions{FilterSelector: document.NewSelector()}); err != nil { return err } - doc, err := p.helper.PhaseConfigBundle().SelectOne(document.NewValidatorExecutorSelector()) + doc, err := helper.PhaseConfigBundle().SelectOne(document.NewValidatorExecutorSelector()) if err != nil { return err } @@ -174,23 +179,27 @@ func (p *phase) Validate() error { return err } - gvk := apiObj.ConfigRef.GroupVersionKind() - selector := document.NewSelector(). - ByName(apiObj.ConfigRef.Name). - ByNamespace(apiObj.ConfigRef.Namespace). - ByGvk(gvk.Group, gvk.Version, gvk.Kind) - - doc, err = p.helper.PhaseConfigBundle().SelectOne(selector) + valCfg, err := yaml.Marshal(validationCfg) if err != nil { return err } - config, err := doc.AsYAML() - if err != nil { - return err - } - apiObj.Config = string(config) + apiObj.Config = string(valCfg) - return container.NewClientV1Alpha1("", buf, os.Stdout, apiObj, p.helper.TargetPath()).Run() + for _, path := range validationCfg.CRDList { + bundle, err := document.NewBundleByPath(filepath.Join(helper.TargetPath(), path)) + if err != nil { + return err + } + bundle, err = bundle.SelectBundle(document.NewCRDSelector()) + if err != nil { + return err + } + if err = bundle.Write(buf); err != nil { + return err + } + } + + return container.NewClientV1Alpha1("", buf, os.Stdout, apiObj, helper.TargetPath()).Run() } // Render executor documents @@ -264,7 +273,7 @@ type plan struct { // Validate makes sure that phase plan is properly configured func (p *plan) Validate() error { - util.Setenv(util.EnvVar{Key: v1alpha1.ValidatorPreventCleanup}, util.EnvVar{Key: v1alpha1.ValidatorPlanValidation}) + util.Setenv(util.EnvVar{Key: v1alpha1.ValidatorPreventCleanup}) for i, step := range p.apiObj.Phases { log.Printf("validating phase: %s\n", step.Name) if i == len(p.apiObj.Phases)-1 { @@ -274,7 +283,11 @@ func (p *plan) Validate() error { if err != nil { return err } - if err = phaseRunner.Validate(); err != nil { + executor, err := phaseRunner.Executor() + if err != nil { + return err + } + if err = validate(executor, p.helper, p.apiObj.ValidationCfg); err != nil { return err } } diff --git a/pkg/phase/client_test.go b/pkg/phase/client_test.go index d47ff193d..8c9576cb5 100644 --- a/pkg/phase/client_test.go +++ b/pkg/phase/client_test.go @@ -147,10 +147,82 @@ func TestPhaseValidate(t *testing.T) { registryFunc phase.ExecutorRegistry }{ { - name: "Success fake executor", - configFunc: testConfig, - phaseID: ifc.ID{Name: "capi_init"}, - registryFunc: fakeRegistry, + name: "Success fake executor", + configFunc: func(t *testing.T) *config.Config { + cfg := testConfig(t) + cfg.Manifests["dummy_manifest"].MetadataPath = "valid_validation_site/metadata.yaml" + return cfg + }, + phaseID: ifc.ID{Name: "kube_apply"}, + registryFunc: func() map[schema.GroupVersionKind]ifc.ExecutorFactory { + gvk := schema.GroupVersionKind{ + Group: "airshipit.org", + Version: "v1alpha1", + Kind: "KubernetesApply", + } + return map[schema.GroupVersionKind]ifc.ExecutorFactory{ + gvk: fakeExecFactory, + } + }, + }, + { + name: "invalid CRD entrypoint - location not exists", + configFunc: func(t *testing.T) *config.Config { + cfg := testConfig(t) + cfg.Manifests["dummy_manifest"].MetadataPath = "valid_validation_site/metadata.yaml" + return cfg + }, + phaseID: ifc.ID{Name: "kube_apply_noentrypoint"}, + registryFunc: func() map[schema.GroupVersionKind]ifc.ExecutorFactory { + gvk := schema.GroupVersionKind{ + Group: "airshipit.org", + Version: "v1alpha1", + Kind: "KubernetesApply", + } + return map[schema.GroupVersionKind]ifc.ExecutorFactory{ + gvk: fakeExecFactory, + } + }, + errContains: "evalsymlink failure", + }, + { + name: "no CRD documents found", + configFunc: func(t *testing.T) *config.Config { + cfg := testConfig(t) + cfg.Manifests["dummy_manifest"].MetadataPath = "valid_validation_site/metadata.yaml" + return cfg + }, + phaseID: ifc.ID{Name: "kube_apply"}, + registryFunc: func() map[schema.GroupVersionKind]ifc.ExecutorFactory { + gvk := schema.GroupVersionKind{ + Group: "airshipit.org", + Version: "v1alpha1", + Kind: "KubernetesApply", + } + return map[schema.GroupVersionKind]ifc.ExecutorFactory{ + gvk: fakeExecFactory, + } + }, + errContains: "", + }, + { + name: "validator executor not found", + configFunc: func(t *testing.T) *config.Config { + cfg := testConfig(t) + cfg.Manifests["dummy_manifest"].MetadataPath = "invalid_validation_site/metadata.yaml" + return cfg + }, + phaseID: ifc.ID{Name: "kube_apply"}, + registryFunc: func() map[schema.GroupVersionKind]ifc.ExecutorFactory { + gvk := schema.GroupVersionKind{ + Group: "airshipit.org", + Version: "v1alpha1", + Kind: "KubernetesApply", + } + return map[schema.GroupVersionKind]ifc.ExecutorFactory{ + gvk: fakeExecFactory, + } + }, errContains: `document filtered by selector [Group="airshipit.org", Version="v1alpha1", ` + `Kind="GenericContainer", Name="document-validation"] found no documents`, }, @@ -204,7 +276,7 @@ func TestPhaseValidate(t *testing.T) { err = p.Validate() if tt.errContains != "" { require.Error(t, err) - assert.Equal(t, tt.errContains, err.Error()) + assert.Contains(t, err.Error(), tt.errContains) } else { require.NoError(t, err) } diff --git a/pkg/phase/command.go b/pkg/phase/command.go index 13b660c43..e884d3ef9 100644 --- a/pkg/phase/command.go +++ b/pkg/phase/command.go @@ -26,7 +26,6 @@ import ( "opendev.org/airship/airshipctl/pkg/document" phaseerrors "opendev.org/airship/airshipctl/pkg/phase/errors" "opendev.org/airship/airshipctl/pkg/phase/ifc" - "opendev.org/airship/airshipctl/pkg/util" "opendev.org/airship/airshipctl/pkg/util/yaml" ) @@ -285,7 +284,6 @@ func (c *ValidateCommand) RunE() error { return err } - util.Setenv(util.EnvVar{Key: "AIRSHIPCTL_CURRENT_PHASE", Value: c.Options.PhaseID.Name}) helper, err := NewHelper(cfg) if err != nil { return err @@ -352,7 +350,6 @@ func (c *PlanValidateCommand) RunE() error { return err } - util.Setenv(util.EnvVar{Key: "AIRSHIPCTL_CURRENT_PLAN", Value: c.Options.PlanID.Name}) helper, err := NewHelper(cfg) if err != nil { return err diff --git a/pkg/phase/command_test.go b/pkg/phase/command_test.go index d397c423b..5a35a2311 100644 --- a/pkg/phase/command_test.go +++ b/pkg/phase/command_test.go @@ -124,6 +124,7 @@ func TestListCommand(t *testing.T) { apiVersion: airshipit.org/v1alpha1 kind: KubernetesApply name: kubernetes-apply + validation: {} kind: Phase metadata: clusterName: ephemeral-cluster @@ -333,6 +334,7 @@ func TestPlanListCommand(t *testing.T) { name: phasePlan phases: - name: phase + validation: {} ... ` testErr := fmt.Errorf(testFactoryErr) diff --git a/pkg/phase/printers_test.go b/pkg/phase/printers_test.go index 06e828a9f..425b8c7a4 100644 --- a/pkg/phase/printers_test.go +++ b/pkg/phase/printers_test.go @@ -103,6 +103,7 @@ func TestDefaultStatusFunction(t *testing.T) { "executorRef": map[string]interface{}{ "kind": "test", }, + "validation": map[string]interface{}{}, }, } printable := &v1alpha1.Phase{ @@ -164,6 +165,7 @@ func TestDefaultStatusFunctionForPhasePlan(t *testing.T) { "name": "p1", "creationTimestamp": nil, }, + "validation": map[string]interface{}{}, } printable := &v1alpha1.PhasePlan{ TypeMeta: metav1.TypeMeta{ diff --git a/pkg/phase/testdata/invalid_validation_site/metadata.yaml b/pkg/phase/testdata/invalid_validation_site/metadata.yaml new file mode 100755 index 000000000..7f9a3fdc1 --- /dev/null +++ b/pkg/phase/testdata/invalid_validation_site/metadata.yaml @@ -0,0 +1,10 @@ +apiVersion: airshipit.org/v1alpha1 +kind: ManifestMetadata +metadata: + name: manifest-metadata +spec: + phase: + path: invalid_validation_site/phases + docEntryPointPrefix: "" + inventory: + path: "" diff --git a/pkg/phase/testdata/invalid_validation_site/phases/cluster_map.yaml b/pkg/phase/testdata/invalid_validation_site/phases/cluster_map.yaml new file mode 100755 index 000000000..47e720022 --- /dev/null +++ b/pkg/phase/testdata/invalid_validation_site/phases/cluster_map.yaml @@ -0,0 +1,12 @@ +apiVersion: airshipit.org/v1alpha1 +kind: ClusterMap +metadata: + name: clusterctl-v1 +map: + target: + parent: ephemeral + kubeconfigSources: + - type: bundle + ephemeral: + kubeconfigSources: + - type: bundle diff --git a/pkg/phase/testdata/invalid_validation_site/phases/kube_apply.yaml b/pkg/phase/testdata/invalid_validation_site/phases/kube_apply.yaml new file mode 100755 index 000000000..e84dfc08f --- /dev/null +++ b/pkg/phase/testdata/invalid_validation_site/phases/kube_apply.yaml @@ -0,0 +1,10 @@ +apiVersion: airshipit.org/v1alpha1 +kind: Phase +metadata: + name: kube_apply +config: + executorRef: + apiVersion: airshipit.org/v1alpha1 + kind: KubernetesApply + name: kubernetes-apply + documentEntryPoint: no_plan_site/phases \ No newline at end of file diff --git a/pkg/phase/testdata/invalid_validation_site/phases/kubernetes_apply.yaml b/pkg/phase/testdata/invalid_validation_site/phases/kubernetes_apply.yaml new file mode 100755 index 000000000..2bfc137bf --- /dev/null +++ b/pkg/phase/testdata/invalid_validation_site/phases/kubernetes_apply.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: airshipit.org/v1alpha1 +kind: KubernetesApply +metadata: + labels: + airshipit.org/deploy-k8s: "false" + name: kubernetes-apply +config: + waitOptions: + timeout: 600 + pruneOptions: + prune: false diff --git a/pkg/phase/testdata/invalid_validation_site/phases/kustomization.yaml b/pkg/phase/testdata/invalid_validation_site/phases/kustomization.yaml new file mode 100755 index 000000000..5ca14108a --- /dev/null +++ b/pkg/phase/testdata/invalid_validation_site/phases/kustomization.yaml @@ -0,0 +1,4 @@ +resources: + - kube_apply.yaml + - kubernetes_apply.yaml + - cluster_map.yaml diff --git a/pkg/phase/testdata/valid_validation_site/metadata.yaml b/pkg/phase/testdata/valid_validation_site/metadata.yaml new file mode 100755 index 000000000..3fd5e3ae1 --- /dev/null +++ b/pkg/phase/testdata/valid_validation_site/metadata.yaml @@ -0,0 +1,10 @@ +apiVersion: airshipit.org/v1alpha1 +kind: ManifestMetadata +metadata: + name: manifest-metadata +spec: + phase: + path: valid_validation_site/phases + docEntryPointPrefix: "" + inventory: + path: "" diff --git a/pkg/phase/testdata/valid_validation_site/phases/cluster_map.yaml b/pkg/phase/testdata/valid_validation_site/phases/cluster_map.yaml new file mode 100755 index 000000000..47e720022 --- /dev/null +++ b/pkg/phase/testdata/valid_validation_site/phases/cluster_map.yaml @@ -0,0 +1,12 @@ +apiVersion: airshipit.org/v1alpha1 +kind: ClusterMap +metadata: + name: clusterctl-v1 +map: + target: + parent: ephemeral + kubeconfigSources: + - type: bundle + ephemeral: + kubeconfigSources: + - type: bundle diff --git a/pkg/phase/testdata/valid_validation_site/phases/kube_apply.yaml b/pkg/phase/testdata/valid_validation_site/phases/kube_apply.yaml new file mode 100755 index 000000000..4fd5f8c4b --- /dev/null +++ b/pkg/phase/testdata/valid_validation_site/phases/kube_apply.yaml @@ -0,0 +1,24 @@ +apiVersion: airshipit.org/v1alpha1 +kind: Phase +metadata: + name: kube_apply +config: + executorRef: + apiVersion: airshipit.org/v1alpha1 + kind: KubernetesApply + name: kubernetes-apply + documentEntryPoint: no_plan_site/phases +--- +apiVersion: airshipit.org/v1alpha1 +kind: Phase +metadata: + name: kube_apply_noentrypoint +config: + executorRef: + apiVersion: airshipit.org/v1alpha1 + kind: KubernetesApply + name: kubernetes-apply + documentEntryPoint: no_plan_site/phases + validation: + crdList: + - not/exist diff --git a/pkg/phase/testdata/valid_validation_site/phases/kubernetes_apply.yaml b/pkg/phase/testdata/valid_validation_site/phases/kubernetes_apply.yaml new file mode 100755 index 000000000..2bfc137bf --- /dev/null +++ b/pkg/phase/testdata/valid_validation_site/phases/kubernetes_apply.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: airshipit.org/v1alpha1 +kind: KubernetesApply +metadata: + labels: + airshipit.org/deploy-k8s: "false" + name: kubernetes-apply +config: + waitOptions: + timeout: 600 + pruneOptions: + prune: false diff --git a/pkg/phase/testdata/valid_validation_site/phases/kustomization.yaml b/pkg/phase/testdata/valid_validation_site/phases/kustomization.yaml new file mode 100755 index 000000000..1de6a49eb --- /dev/null +++ b/pkg/phase/testdata/valid_validation_site/phases/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - kube_apply.yaml + - kubernetes_apply.yaml + - cluster_map.yaml + - validation_exec.yaml diff --git a/pkg/phase/testdata/valid_validation_site/phases/validation_exec.yaml b/pkg/phase/testdata/valid_validation_site/phases/validation_exec.yaml new file mode 100755 index 000000000..c3c323908 --- /dev/null +++ b/pkg/phase/testdata/valid_validation_site/phases/validation_exec.yaml @@ -0,0 +1,9 @@ +apiVersion: airshipit.org/v1alpha1 +kind: GenericContainer +metadata: + name: document-validation + labels: + airshipit.org/deploy-k8s: "false" +spec: + type: krm + hostNetwork: true diff --git a/pkg/util/tableprinter_test.go b/pkg/util/tableprinter_test.go index 9a80eeeb5..22ab80d2a 100644 --- a/pkg/util/tableprinter_test.go +++ b/pkg/util/tableprinter_test.go @@ -65,6 +65,7 @@ func TestDefaultStatusFunction(t *testing.T) { "config": map[string]interface{}{ "documentEntryPoint": "", "executorRef": nil, + "validation": map[string]interface{}{}, }, } printable := &airapiv1.Phase{