Pin test-infra & pkg to release-0.16 (#281)

This commit is contained in:
Nghia Tran 2020-06-30 10:28:29 -07:00 committed by GitHub
parent 787aec80f7
commit a78409990d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
100 changed files with 5454 additions and 573 deletions

4
go.mod
View File

@ -16,8 +16,8 @@ require (
k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
k8s.io/code-generator v0.18.0
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29
knative.dev/pkg v0.0.0-20200519155757-14eb3ae3a5a7
knative.dev/test-infra v0.0.0-20200519161858-554a95a37986
knative.dev/pkg v0.0.0-20200630170034-2c1a029eb97f
knative.dev/test-infra v0.0.0-20200630141629-15f40fe97047
)
replace (

186
go.sum
View File

@ -1,11 +1,10 @@
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
cloud.google.com/go v0.25.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.30.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.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts=
cloud.google.com/go v0.40.0/go.mod h1:Tk58MuI9rbLMKlAjeO/bDnteAx7tX2gJIXw4T5Jwlro=
cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
@ -46,29 +45,20 @@ contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3
contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU=
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
github.com/Azure/azure-pipeline-go v0.1.9/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v19.1.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v21.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v28.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0=
github.com/Azure/azure-storage-blob-go v0.0.0-20190123011202-457680cc0804/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
github.com/Azure/go-autorest/autorest v0.2.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
@ -82,11 +72,9 @@ github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+v
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/autorest/to v0.1.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
@ -98,7 +86,6 @@ github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t
github.com/GoogleCloudPlatform/cloud-builders/gcs-fetcher v0.0.0-20191203181535-308b93ad1f39/go.mod h1:yfGmCjKuUzk9WzubMlW2zwjhCraIc/J+M40cufdemRM=
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
github.com/GoogleCloudPlatform/testgrid v0.0.1-alpha.3/go.mod h1:f96W2HYy3tiBNV5zbbRc+NczwYHgG1PHXMQfoEWv680=
github.com/GoogleCloudPlatform/testgrid v0.0.7/go.mod h1:lmtHGBL0M/MLbu1tR9BWV7FGZ1FEFIdPqmJiHNCL7y8=
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
@ -138,22 +125,18 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
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/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/aws/aws-k8s-tester v0.0.0-20190114231546-b411acf57dfe/go.mod h1:1ADF5tAtU1/mVtfMcHAYSm2fPw71DA7fFk0yed64/0I=
github.com/aws/aws-k8s-tester v0.9.3/go.mod h1:nsh1f7joi8ZI1lvR+Ron6kJM2QdCYPU/vFePghSSuTc=
github.com/aws/aws-k8s-tester v1.0.0/go.mod h1:NUNd9k43+h9O5tvwL+4N1Ctb//SapmeeFX1G0/2/0Qc=
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.15.90/go.mod h1:es1KtYUFs7le0xQ3rOihkuoVD90z7D0fR2Qm4S00/gU=
github.com/aws/aws-sdk-go v1.16.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.23.20 h1:2CBuL21P0yKdZN5urf2NxKa1ha8fhnY+A3pBCHFeZoA=
github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.23.22/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.29.32/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
github.com/aws/aws-sdk-go v1.29.34 h1:yrzwfDaZFe9oT4AmQeNNunSQA7c0m2chz0B43+bJ1ok=
github.com/aws/aws-sdk-go v1.29.34/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
github.com/aws/aws-sdk-go v1.30.4/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.30.5 h1:i+sSesaMrSxiUt3NJddOApe2mXK+VNBgfcmRTvNFrXM=
github.com/aws/aws-sdk-go v1.30.5/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/bazelbuild/buildtools v0.0.0-20190917191645-69366ca98f89/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -190,7 +173,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo=
github.com/clarketm/json v1.13.4/go.mod h1:ynr2LRfb0fQU34l07csRNBTcivjySLLiY1YzQqKVfdo=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudevents/sdk-go v0.0.0-20190509003705-56931988abe3/go.mod h1:j1nZWMLGg3om8SswStBoY6/SHvcLM19MuZqwDtMtmzs=
github.com/cloudevents/sdk-go v1.0.0/go.mod h1:3TkmM0cFqkhCHOq5JzzRU/RxRkwzoS8TZ+G448qVTog=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
@ -225,7 +208,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC4G4As=
github.com/denisenkom/go-mssqldb v0.0.0-20190111225525-2fea367d496d/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
@ -239,14 +221,11 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/cli v0.0.0-20190925022749-754388324470/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20180531152204-71cd53e4a197/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
@ -297,11 +276,12 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-ini/ini v1.46.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-ini/ini v1.55.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@ -366,20 +346,16 @@ github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfT
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-sql-driver/mysql v0.0.0-20160411075031-7ebe0a500653/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@ -400,7 +376,6 @@ github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
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=
@ -421,7 +396,6 @@ github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAO
github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8=
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
github.com/gomodule/redigo v1.7.0/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
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=
@ -429,7 +403,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE=
github.com/google/go-containerregistry v0.0.0-20200115214256-379933c9c22b/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs=
github.com/google/go-containerregistry v0.0.0-20200123184029-53ce695e4179/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
@ -438,7 +411,6 @@ github.com/google/go-licenses v0.0.0-20191112164736-212ea350c932/go.mod h1:16wa6
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE=
github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
@ -458,12 +430,9 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s=
github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@ -484,18 +453,15 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/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.4.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
@ -507,7 +473,6 @@ github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-multierror v0.0.0-20171204182908-b7773ae21874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@ -536,11 +501,9 @@ github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQT
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jenkins-x/go-scm v1.5.65/go.mod h1:MgGRkJScE/rJ30J/bXYqduN5sDPZqZFITJopsnZmTOw=
github.com/jenkins-x/go-scm v1.5.79/go.mod h1:PCT338UhP/pQ0IeEeMEf/hoLTYKcH7qjGEKd7jPkeYg=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/gorm v0.0.0-20170316141641-572d0a0ab1eb/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
github.com/jinzhu/inflection v0.0.0-20190603042836-f5c5f50e6090/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
@ -553,8 +516,6 @@ github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeY
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@ -567,7 +528,7 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kelseyhightower/envconfig v1.3.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
@ -577,10 +538,7 @@ github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0
github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.2/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/knative/build v0.1.2/go.mod h1:/sU74ZQkwlYA5FwYDJhYTy61i/Kn+5eWfln2jDbw3Qo=
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@ -588,13 +546,11 @@ 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.0.0/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
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/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
@ -623,10 +579,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v0.0.0-20160514122348-38ee283dabf1/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/matttproud/golang_protobuf_extensions v1.0.0/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
@ -652,10 +606,13 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ=
github.com/nats-io/go-nats v1.7.0/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0=
github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
github.com/nats-io/nuid v1.0.0/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
@ -671,7 +628,6 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@ -688,7 +644,6 @@ github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5X
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.0/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=
@ -699,7 +654,6 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.3.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
@ -718,8 +672,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
@ -729,7 +681,6 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.5.0 h1:Ctq0iGpCmr3jeP77kbF2UxgvRwzWWz+4Bh9/vJTyg1A=
github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@ -739,9 +690,6 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@ -753,8 +701,6 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20180612222113-7d6f385de8be/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@ -772,29 +718,22 @@ github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962/go.mod h1:bCqn
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/satori/go.uuid v0.0.0-20160713180306-0aa62d5ddceb/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/githubv4 v0.0.0-20180925043049-51d7b505e2e9/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo=
github.com/shurcooL/githubv4 v0.0.0-20190718010115-4ba037080260/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo=
github.com/shurcooL/githubv4 v0.0.0-20191102174205-af46314aec7b/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/graphql v0.0.0-20180924043259-e4a3a37e6d42/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg=
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@ -817,7 +756,6 @@ github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@ -840,9 +778,8 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tektoncd/pipeline v0.8.0/go.mod h1:IZzJdiX9EqEMuUcgdnElozdYYRh0/ZRC+NKMLj1K3Yw=
github.com/tektoncd/pipeline v0.10.1/go.mod h1:D2X0exT46zYx95BU7ByM8+erpjoN7thmUBvlKThOszU=
github.com/tektoncd/plumbing v0.0.0-20191216083742-847dcf196de9/go.mod h1:QZHgU07PRBTRF6N57w4+ApRu8OgfYLFNqCDlfEZaD9Y=
github.com/tektoncd/pipeline v0.11.0/go.mod h1:hlkH32S92+/UODROH0dmxzyuMxfRFp/Nc3e29MewLn8=
github.com/tektoncd/plumbing v0.0.0-20200217163359-cd0db6e567d2/go.mod h1:QZHgU07PRBTRF6N57w4+ApRu8OgfYLFNqCDlfEZaD9Y=
github.com/tektoncd/plumbing/pipelinerun-logs v0.0.0-20191206114338-712d544c2c21/go.mod h1:S62EUWtqmejjJgUMOGB1CCCHRp6C706laH06BoALkzU=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -851,13 +788,12 @@ github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3 h1:pcQGQzTwCg//7FgV
github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo=
github.com/tsenart/vegeta v12.7.1-0.20190725001342-b5f4fca92137+incompatible h1:ErZrHhRveAoznVW80gbrxz+qxJNydpA2fcQxTPHkZbU=
github.com/tsenart/vegeta v12.7.1-0.20190725001342-b5f4fca92137+incompatible/go.mod h1:Smz/ZWfhKRcyDDChZkG3CyTHdj87lHzio/HOCkbndXM=
github.com/ugorji/go v1.1.1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.18.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo=
github.com/vdemeester/k8s-pkg-credentialprovider v1.13.12-1/go.mod h1:Fko0rTxEtDW2kju5Ky7yFJNS3IcNvW8IPsp4/e9oev0=
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
@ -870,7 +806,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
@ -878,16 +813,13 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
go.etcd.io/bbolt v1.3.1-etcd.7/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20181031231232-83304cfc808c/go.mod h1:weASp41xM3dk0YHg1s/W8ecdGP5G4teSTMBPpYAaUgA=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
go.opencensus.io v0.17.0/go.mod h1:mp1VrMQxhlqqDpKvH4UcQUa4YwlzNmymAjPrDdfxNpI=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@ -897,28 +829,31 @@ go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.9.2-0.20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI=
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -961,7 +896,6 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
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-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
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=
@ -1012,7 +946,6 @@ golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -1021,9 +954,7 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
@ -1050,7 +981,6 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190219203350-90b0e4468f99/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1071,7 +1001,6 @@ golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8 h1:41hwlulw1prEMBxLQSlMSux1zxJf07B3WPsdjJlKZxE=
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1082,7 +1011,6 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1159,6 +1087,7 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200214144324-88be01311a71/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200303214625-2b0b585e22fe/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200317043434-63da46f3035e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
@ -1170,6 +1099,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0=
gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k=
gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
@ -1178,8 +1109,6 @@ gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6d
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181021000519-a2651947f503/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@ -1198,7 +1127,6 @@ google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
google.golang.org/api v0.20.0 h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
@ -1207,10 +1135,7 @@ google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
google.golang.org/genproto v0.0.0-20180608181217-32ee49c4dd80/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181016170114-94acd270e44e/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=
@ -1239,8 +1164,6 @@ google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200326112834-f447254575fd h1:DVCc2PgW9UrvHGZGEv4Mt3uSeQtUrrs7r8pUw+bVwWI=
google.golang.org/genproto v0.0.0-20200326112834-f447254575fd/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.15.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@ -1264,7 +1187,6 @@ gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4
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-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
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=
@ -1303,8 +1225,6 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@ -1337,7 +1257,6 @@ k8s.io/component-base v0.17.2/go.mod h1:zMPW3g5aH7cHJpKYQ/ZsGMcgbsA/VyhEugF3QT1a
k8s.io/component-base v0.17.6/go.mod h1:jgRLWl0B0rOzFNtxQ9E4BphPmDqoMafujdau6AdG2Xo=
k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20190306031000-7a1b7fb0289f/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20190822140433-26a664648505 h1:ZY6yclUKVbZ+SdWnkfY+Je5vrMpKOxmGeKRbsXVmqYM=
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20191108084044-e500ee069b5c/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
@ -1345,47 +1264,25 @@ k8s.io/gengo v0.0.0-20200205140755-e0e292d8aa12 h1:pZzawYyz6VRNPVYpqGv61LWCimQv1
k8s.io/gengo v0.0.0-20200205140755-e0e292d8aa12/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29 h1:NeQXVJ2XFSkRoPzRo8AId01ZER+j8oV4SZADT4iBOXQ=
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU=
k8s.io/kubectl v0.17.2/go.mod h1:y4rfLV0n6aPmvbRCqZQjvOp3ezxsFgpqL+zF5jH/lxk=
k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/kubernetes v1.14.7/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8=
k8s.io/metrics v0.17.2/go.mod h1:3TkNHET4ROd+NfzNxkjoVfQ0Ob4iZnaHmSEA4vYpwLw=
k8s.io/test-infra v0.0.0-20181019233642-2e10a0bbe9b3/go.mod h1:2NzXB13Ji0nqpyublHeiPC4FZwU0TknfvyaaNfl/BTA=
k8s.io/test-infra v0.0.0-20191212060232-70b0b49fe247/go.mod h1:d8SKryJBXAwfCFVL4wieRez47J2NOOAb9d029sWLseQ=
k8s.io/test-infra v0.0.0-20200407001919-bc7f71ef65b8/go.mod h1:/WpJWcaDvuykB322WXP4kJbX8IpalOzuPxA62GpwkJk=
k8s.io/utils v0.0.0-20181019225348-5e321f9a457c/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20190907131718-3d4f5b7dea0b h1:eMM0sTvh3KBVGwJfuNcU86P38TJhlVMAICbFPDG3t0M=
k8s.io/utils v0.0.0-20190907131718-3d4f5b7dea0b/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/test-infra v0.0.0-20200514184223-ba32c8aae783/go.mod h1:bW6thaPZfL2hW7ecjx2WYwlP9KQLM47/xIJyttkVk5s=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200124190032-861946025e34 h1:HjlUD6M0K3P8nRXmr2B9o4F9dUy9TCj/aEpReeyi6+k=
k8s.io/utils v0.0.0-20200124190032-861946025e34/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
knative.dev/caching v0.0.0-20190719140829-2032732871ff/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
knative.dev/eventing-contrib v0.6.1-0.20190723221543-5ce18048c08b/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
knative.dev/pkg v0.0.0-20191101194912-56c2594e4f11/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
knative.dev/pkg v0.0.0-20191111150521-6d806b998379/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
knative.dev/pkg v0.0.0-20200428194351-90fc61bae7f7/go.mod h1:o+e8OVEJKIuvXPsGVPIautjXgs05xbos7G+QMRjuUps=
knative.dev/pkg v0.0.0-20200505191044-3da93ebb24c2 h1:Qu2NlOHb9p3g+CSL/ok9+FySowN60URFEKRSXfWtDv4=
knative.dev/pkg v0.0.0-20200505191044-3da93ebb24c2/go.mod h1:Q6sL35DdGs8hIQZKdaCXJGgY8f90BmNBKSb8z6d/BTM=
knative.dev/pkg v0.0.0-20200515002500-16d7b963416f h1:kcpAMvYUqftHMA69wZ7g83zEW4y8cdnqfdJsSPOlrJQ=
knative.dev/pkg v0.0.0-20200515002500-16d7b963416f/go.mod h1:tMOHGbxtRz8zYFGEGpV/bpoTEM1o89MwYFC4YJXl3GY=
knative.dev/pkg v0.0.0-20200519155757-14eb3ae3a5a7 h1:9S2r59HZJF9nKvoRLg5zJzx6XpVlVyvVRqz/C/h6h2s=
knative.dev/pkg v0.0.0-20200519155757-14eb3ae3a5a7/go.mod h1:QgNZTxnwpB/oSpNcfnLVlw+WpEwwyKAvJlvR3hgeltA=
knative.dev/test-infra v0.0.0-20200407185800-1b88cb3b45a5/go.mod h1:xcdUkMJrLlBswIZqL5zCuBFOC22WIPMQoVX1L35i0vQ=
knative.dev/test-infra v0.0.0-20200505052144-5ea2f705bb55 h1:Ajn44+eHHjPQL/BQicj8LMy8VTD2ypMCfHJuZVGEtew=
knative.dev/test-infra v0.0.0-20200505052144-5ea2f705bb55/go.mod h1:WqF1Azka+FxPZ20keR2zCNtiQA1MP9ZB4BH4HuI+SIU=
knative.dev/test-infra v0.0.0-20200513011557-d03429a76034 h1:JxqONCZVS7or+Fv3ebVQoipuIBH7Ig3Qbx170hgIF+A=
knative.dev/test-infra v0.0.0-20200513011557-d03429a76034/go.mod h1:aMif0KXL4g19YCYwsy4Ocjjz5xgPlseYV+B95Oo4JGE=
knative.dev/test-infra v0.0.0-20200519015156-82551620b0a9 h1:kKfV3QWsxugwXsqgjFd72MjZeAHJ381dWqAxH2KMknc=
knative.dev/test-infra v0.0.0-20200519015156-82551620b0a9/go.mod h1:A5b2OAXTOeHT3hHhVQm3dmtbuWvIDP7qzgtqxA3/2pE=
knative.dev/test-infra v0.0.0-20200519161858-554a95a37986 h1:ZDy43jkWPQ75d4l4DGy+ENQIXlNcnHIh4tB6XxgovNc=
knative.dev/test-infra v0.0.0-20200519161858-554a95a37986/go.mod h1:LeNa1Wvn47efeQUkpkn3XG7Fx9Ga+rhAP13SZyjaEGg=
knative.dev/caching v0.0.0-20200116200605-67bca2c83dfa/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
knative.dev/eventing-contrib v0.11.2/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
knative.dev/pkg v0.0.0-20200207155214-fef852970f43/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
knative.dev/pkg v0.0.0-20200630170034-2c1a029eb97f h1:Y3fmAKacNnQvPBK6Onnb0uC87roq/ypS8rYekfIdci8=
knative.dev/pkg v0.0.0-20200630170034-2c1a029eb97f/go.mod h1:7T15JzvjKXWnvIKcohz4brrsVq8jvwAcJwWY9xigAc0=
knative.dev/test-infra v0.0.0-20200630141629-15f40fe97047 h1:MLcIL0EGkvxRIXcrbPfBRKDVY4wNLVsNbilnZOfHmdk=
knative.dev/test-infra v0.0.0-20200630141629-15f40fe97047/go.mod h1:30tMsI1VXrG2m4ut7CFZbLg1VbcRsslPfGU+GWILm6E=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
@ -1398,12 +1295,13 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/controller-runtime v0.3.0/go.mod h1:Cw6PkEg0Sa7dAYovGT4R0tRkGhHXpYijwNxYhAnAZZk=
sigs.k8s.io/boskos v0.0.0-20200530174753-71e795271860/go.mod h1:L1ubP7d1CCMSQSjKiZv6dGbh7b4kfoG+dFPj8cfYDnI=
sigs.k8s.io/controller-runtime v0.5.0/go.mod h1:REiJzC7Y00U+2YkMbT8wxgrsX5USpXKGhb2sCtAXiT8=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE=
sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI=
vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI=

View File

@ -27,7 +27,7 @@ export GO111MODULE=on
export GOFLAGS=-mod=vendor
# This controls the release branch we track.
VERSION="release-0.15"
VERSION="release-0.16"
# The list of dependencies that we track at HEAD and periodically
# float forward in this repository.

View File

@ -107,6 +107,13 @@ type Provider interface {
IsExpired() bool
}
// ProviderWithContext is a Provider that can retrieve credentials with a Context
type ProviderWithContext interface {
Provider
RetrieveWithContext(Context) (Value, error)
}
// An Expirer is an interface that Providers can implement to expose the expiration
// time, if known. If the Provider cannot accurately provide this info,
// it should not implement this interface.
@ -233,7 +240,9 @@ func (c *Credentials) GetWithContext(ctx Context) (Value, error) {
// Cannot pass context down to the actual retrieve, because the first
// context would cancel the whole group when there is not direct
// association of items in the group.
resCh := c.sf.DoChan("", c.singleRetrieve)
resCh := c.sf.DoChan("", func() (interface{}, error) {
return c.singleRetrieve(&suppressedContext{ctx})
})
select {
case res := <-resCh:
return res.Val.(Value), res.Err
@ -243,12 +252,16 @@ func (c *Credentials) GetWithContext(ctx Context) (Value, error) {
}
}
func (c *Credentials) singleRetrieve() (interface{}, error) {
func (c *Credentials) singleRetrieve(ctx Context) (creds interface{}, err error) {
if curCreds := c.creds.Load(); !c.isExpired(curCreds) {
return curCreds.(Value), nil
}
creds, err := c.provider.Retrieve()
if p, ok := c.provider.(ProviderWithContext); ok {
creds, err = p.RetrieveWithContext(ctx)
} else {
creds, err = c.provider.Retrieve()
}
if err == nil {
c.creds.Store(creds)
}
@ -308,3 +321,19 @@ func (c *Credentials) ExpiresAt() (time.Time, error) {
}
return expirer.ExpiresAt(), nil
}
type suppressedContext struct {
Context
}
func (s *suppressedContext) Deadline() (deadline time.Time, ok bool) {
return time.Time{}, false
}
func (s *suppressedContext) Done() <-chan struct{} {
return nil
}
func (s *suppressedContext) Err() error {
return nil
}

View File

@ -7,6 +7,7 @@ import (
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/credentials"
@ -87,7 +88,14 @@ func NewCredentialsWithClient(client *ec2metadata.EC2Metadata, options ...func(*
// Error will be returned if the request fails, or unable to extract
// the desired credentials.
func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
credsList, err := requestCredList(m.Client)
return m.RetrieveWithContext(aws.BackgroundContext())
}
// RetrieveWithContext retrieves credentials from the EC2 service.
// Error will be returned if the request fails, or unable to extract
// the desired credentials.
func (m *EC2RoleProvider) RetrieveWithContext(ctx credentials.Context) (credentials.Value, error) {
credsList, err := requestCredList(ctx, m.Client)
if err != nil {
return credentials.Value{ProviderName: ProviderName}, err
}
@ -97,7 +105,7 @@ func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
}
credsName := credsList[0]
roleCreds, err := requestCred(m.Client, credsName)
roleCreds, err := requestCred(ctx, m.Client, credsName)
if err != nil {
return credentials.Value{ProviderName: ProviderName}, err
}
@ -130,8 +138,8 @@ const iamSecurityCredsPath = "iam/security-credentials/"
// requestCredList requests a list of credentials from the EC2 service.
// If there are no credentials, or there is an error making or receiving the request
func requestCredList(client *ec2metadata.EC2Metadata) ([]string, error) {
resp, err := client.GetMetadata(iamSecurityCredsPath)
func requestCredList(ctx aws.Context, client *ec2metadata.EC2Metadata) ([]string, error) {
resp, err := client.GetMetadataWithContext(ctx, iamSecurityCredsPath)
if err != nil {
return nil, awserr.New("EC2RoleRequestError", "no EC2 instance role found", err)
}
@ -154,8 +162,8 @@ func requestCredList(client *ec2metadata.EC2Metadata) ([]string, error) {
//
// If the credentials cannot be found, or there is an error reading the response
// and error will be returned.
func requestCred(client *ec2metadata.EC2Metadata, credsName string) (ec2RoleCredRespBody, error) {
resp, err := client.GetMetadata(sdkuri.PathJoin(iamSecurityCredsPath, credsName))
func requestCred(ctx aws.Context, client *ec2metadata.EC2Metadata, credsName string) (ec2RoleCredRespBody, error) {
resp, err := client.GetMetadataWithContext(ctx, sdkuri.PathJoin(iamSecurityCredsPath, credsName))
if err != nil {
return ec2RoleCredRespBody{},
awserr.New("EC2RoleRequestError",

View File

@ -116,7 +116,13 @@ func (p *Provider) IsExpired() bool {
// Retrieve will attempt to request the credentials from the endpoint the Provider
// was configured for. And error will be returned if the retrieval fails.
func (p *Provider) Retrieve() (credentials.Value, error) {
resp, err := p.getCredentials()
return p.RetrieveWithContext(aws.BackgroundContext())
}
// RetrieveWithContext will attempt to request the credentials from the endpoint the Provider
// was configured for. And error will be returned if the retrieval fails.
func (p *Provider) RetrieveWithContext(ctx credentials.Context) (credentials.Value, error) {
resp, err := p.getCredentials(ctx)
if err != nil {
return credentials.Value{ProviderName: ProviderName},
awserr.New("CredentialsEndpointError", "failed to load credentials", err)
@ -148,7 +154,7 @@ type errorOutput struct {
Message string `json:"message"`
}
func (p *Provider) getCredentials() (*getCredentialsOutput, error) {
func (p *Provider) getCredentials(ctx aws.Context) (*getCredentialsOutput, error) {
op := &request.Operation{
Name: "GetCredentials",
HTTPMethod: "GET",
@ -156,6 +162,7 @@ func (p *Provider) getCredentials() (*getCredentialsOutput, error) {
out := &getCredentialsOutput{}
req := p.Client.NewRequest(op, nil, out)
req.SetContext(ctx)
req.HTTPRequest.Header.Set("Accept", "application/json")
if authToken := p.AuthorizationToken; len(authToken) != 0 {
req.HTTPRequest.Header.Set("Authorization", authToken)

View File

@ -87,6 +87,7 @@ import (
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkrand"
"github.com/aws/aws-sdk-go/service/sts"
)
@ -118,6 +119,10 @@ type AssumeRoler interface {
AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
}
type assumeRolerWithContext interface {
AssumeRoleWithContext(aws.Context, *sts.AssumeRoleInput, ...request.Option) (*sts.AssumeRoleOutput, error)
}
// DefaultDuration is the default amount of time in minutes that the credentials
// will be valid for.
var DefaultDuration = time.Duration(15) * time.Minute
@ -265,6 +270,11 @@ func NewCredentialsWithClient(svc AssumeRoler, roleARN string, options ...func(*
// Retrieve generates a new set of temporary credentials using STS.
func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) {
return p.RetrieveWithContext(aws.BackgroundContext())
}
// RetrieveWithContext generates a new set of temporary credentials using STS.
func (p *AssumeRoleProvider) RetrieveWithContext(ctx credentials.Context) (credentials.Value, error) {
// Apply defaults where parameters are not set.
if p.RoleSessionName == "" {
// Try to work out a role name that will hopefully end up unique.
@ -304,7 +314,15 @@ func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) {
}
}
roleOutput, err := p.Client.AssumeRole(input)
var roleOutput *sts.AssumeRoleOutput
var err error
if c, ok := p.Client.(assumeRolerWithContext); ok {
roleOutput, err = c.AssumeRoleWithContext(ctx, input)
} else {
roleOutput, err = p.Client.AssumeRole(input)
}
if err != nil {
return credentials.Value{ProviderName: ProviderName}, err
}

View File

@ -64,6 +64,13 @@ func NewWebIdentityRoleProvider(svc stsiface.STSAPI, roleARN, roleSessionName, p
// 'WebIdentityTokenFilePath' specified destination and if that is empty an
// error will be returned.
func (p *WebIdentityRoleProvider) Retrieve() (credentials.Value, error) {
return p.RetrieveWithContext(aws.BackgroundContext())
}
// RetrieveWithContext will attempt to assume a role from a token which is located at
// 'WebIdentityTokenFilePath' specified destination and if that is empty an
// error will be returned.
func (p *WebIdentityRoleProvider) RetrieveWithContext(ctx credentials.Context) (credentials.Value, error) {
b, err := ioutil.ReadFile(p.tokenFilePath)
if err != nil {
errMsg := fmt.Sprintf("unable to read file at %s", p.tokenFilePath)
@ -81,6 +88,9 @@ func (p *WebIdentityRoleProvider) Retrieve() (credentials.Value, error) {
RoleSessionName: &sessionName,
WebIdentityToken: aws.String(string(b)),
})
req.SetContext(ctx)
// InvalidIdentityToken error is a temporary error that can occur
// when assuming an Role with a JWT web identity token.
req.RetryErrorCodes = append(req.RetryErrorCodes, sts.ErrCodeInvalidIdentityTokenException)

View File

@ -8,6 +8,7 @@ import (
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkuri"
@ -15,7 +16,7 @@ import (
// getToken uses the duration to return a token for EC2 metadata service,
// or an error if the request failed.
func (c *EC2Metadata) getToken(duration time.Duration) (tokenOutput, error) {
func (c *EC2Metadata) getToken(ctx aws.Context, duration time.Duration) (tokenOutput, error) {
op := &request.Operation{
Name: "GetToken",
HTTPMethod: "PUT",
@ -24,6 +25,7 @@ func (c *EC2Metadata) getToken(duration time.Duration) (tokenOutput, error) {
var output tokenOutput
req := c.NewRequest(op, nil, &output)
req.SetContext(ctx)
// remove the fetch token handler from the request handlers to avoid infinite recursion
req.Handlers.Sign.RemoveByName(fetchTokenHandlerName)
@ -50,6 +52,13 @@ func (c *EC2Metadata) getToken(duration time.Duration) (tokenOutput, error) {
// instance metadata service. The content will be returned as a string, or
// error if the request failed.
func (c *EC2Metadata) GetMetadata(p string) (string, error) {
return c.GetMetadataWithContext(aws.BackgroundContext(), p)
}
// GetMetadataWithContext uses the path provided to request information from the EC2
// instance metadata service. The content will be returned as a string, or
// error if the request failed.
func (c *EC2Metadata) GetMetadataWithContext(ctx aws.Context, p string) (string, error) {
op := &request.Operation{
Name: "GetMetadata",
HTTPMethod: "GET",
@ -59,6 +68,8 @@ func (c *EC2Metadata) GetMetadata(p string) (string, error) {
req := c.NewRequest(op, nil, output)
req.SetContext(ctx)
err := req.Send()
return output.Content, err
}
@ -67,6 +78,13 @@ func (c *EC2Metadata) GetMetadata(p string) (string, error) {
// there is no user-data setup for the EC2 instance a "NotFoundError" error
// code will be returned.
func (c *EC2Metadata) GetUserData() (string, error) {
return c.GetUserDataWithContext(aws.BackgroundContext())
}
// GetUserDataWithContext returns the userdata that was configured for the service. If
// there is no user-data setup for the EC2 instance a "NotFoundError" error
// code will be returned.
func (c *EC2Metadata) GetUserDataWithContext(ctx aws.Context) (string, error) {
op := &request.Operation{
Name: "GetUserData",
HTTPMethod: "GET",
@ -75,6 +93,7 @@ func (c *EC2Metadata) GetUserData() (string, error) {
output := &metadataOutput{}
req := c.NewRequest(op, nil, output)
req.SetContext(ctx)
err := req.Send()
return output.Content, err
@ -84,6 +103,13 @@ func (c *EC2Metadata) GetUserData() (string, error) {
// instance metadata service for dynamic data. The content will be returned
// as a string, or error if the request failed.
func (c *EC2Metadata) GetDynamicData(p string) (string, error) {
return c.GetDynamicDataWithContext(aws.BackgroundContext(), p)
}
// GetDynamicDataWithContext uses the path provided to request information from the EC2
// instance metadata service for dynamic data. The content will be returned
// as a string, or error if the request failed.
func (c *EC2Metadata) GetDynamicDataWithContext(ctx aws.Context, p string) (string, error) {
op := &request.Operation{
Name: "GetDynamicData",
HTTPMethod: "GET",
@ -92,6 +118,7 @@ func (c *EC2Metadata) GetDynamicData(p string) (string, error) {
output := &metadataOutput{}
req := c.NewRequest(op, nil, output)
req.SetContext(ctx)
err := req.Send()
return output.Content, err
@ -101,7 +128,14 @@ func (c *EC2Metadata) GetDynamicData(p string) (string, error) {
// instance. Error is returned if the request fails or is unable to parse
// the response.
func (c *EC2Metadata) GetInstanceIdentityDocument() (EC2InstanceIdentityDocument, error) {
resp, err := c.GetDynamicData("instance-identity/document")
return c.GetInstanceIdentityDocumentWithContext(aws.BackgroundContext())
}
// GetInstanceIdentityDocumentWithContext retrieves an identity document describing an
// instance. Error is returned if the request fails or is unable to parse
// the response.
func (c *EC2Metadata) GetInstanceIdentityDocumentWithContext(ctx aws.Context) (EC2InstanceIdentityDocument, error) {
resp, err := c.GetDynamicDataWithContext(ctx, "instance-identity/document")
if err != nil {
return EC2InstanceIdentityDocument{},
awserr.New("EC2MetadataRequestError",
@ -120,7 +154,12 @@ func (c *EC2Metadata) GetInstanceIdentityDocument() (EC2InstanceIdentityDocument
// IAMInfo retrieves IAM info from the metadata API
func (c *EC2Metadata) IAMInfo() (EC2IAMInfo, error) {
resp, err := c.GetMetadata("iam/info")
return c.IAMInfoWithContext(aws.BackgroundContext())
}
// IAMInfoWithContext retrieves IAM info from the metadata API
func (c *EC2Metadata) IAMInfoWithContext(ctx aws.Context) (EC2IAMInfo, error) {
resp, err := c.GetMetadataWithContext(ctx, "iam/info")
if err != nil {
return EC2IAMInfo{},
awserr.New("EC2MetadataRequestError",
@ -145,7 +184,12 @@ func (c *EC2Metadata) IAMInfo() (EC2IAMInfo, error) {
// Region returns the region the instance is running in.
func (c *EC2Metadata) Region() (string, error) {
ec2InstanceIdentityDocument, err := c.GetInstanceIdentityDocument()
return c.RegionWithContext(aws.BackgroundContext())
}
// RegionWithContext returns the region the instance is running in.
func (c *EC2Metadata) RegionWithContext(ctx aws.Context) (string, error) {
ec2InstanceIdentityDocument, err := c.GetInstanceIdentityDocumentWithContext(ctx)
if err != nil {
return "", err
}
@ -162,7 +206,14 @@ func (c *EC2Metadata) Region() (string, error) {
// Can be used to determine if application is running within an EC2 Instance and
// the metadata service is available.
func (c *EC2Metadata) Available() bool {
if _, err := c.GetMetadata("instance-id"); err != nil {
return c.AvailableWithContext(aws.BackgroundContext())
}
// AvailableWithContext returns if the application has access to the EC2 Metadata service.
// Can be used to determine if application is running within an EC2 Instance and
// the metadata service is available.
func (c *EC2Metadata) AvailableWithContext(ctx aws.Context) bool {
if _, err := c.GetMetadataWithContext(ctx, "instance-id"); err != nil {
return false
}

View File

@ -46,7 +46,7 @@ func (t *tokenProvider) fetchTokenHandler(r *request.Request) {
return
}
output, err := t.client.getToken(t.configuredTTL)
output, err := t.client.getToken(r.Context(), t.configuredTTL)
if err != nil {

View File

@ -1139,11 +1139,41 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"fips-ca-central-1": endpoint{
Hostname: "codepipeline-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
"fips-us-east-1": endpoint{
Hostname: "codepipeline-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-east-2": endpoint{
Hostname: "codepipeline-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"fips-us-west-1": endpoint{
Hostname: "codepipeline-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"fips-us-west-2": endpoint{
Hostname: "codepipeline-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"codestar": service{
@ -1174,6 +1204,7 @@ var awsPartition = partition{
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
@ -1755,12 +1786,59 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"fips-us-east-1": endpoint{
Hostname: "ecs-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-east-2": endpoint{
Hostname: "ecs-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"fips-us-west-1": endpoint{
Hostname: "ecs-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"madison-fips-us-west-2": endpoint{
Hostname: "ecs-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"elastic-inference": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{
Hostname: "api.elastic-inference.ap-northeast-1.amazonaws.com",
},
"ap-northeast-2": endpoint{
Hostname: "api.elastic-inference.ap-northeast-2.amazonaws.com",
},
"eu-west-1": endpoint{
Hostname: "api.elastic-inference.eu-west-1.amazonaws.com",
},
"us-east-1": endpoint{
Hostname: "api.elastic-inference.us-east-1.amazonaws.com",
},
"us-east-2": endpoint{
Hostname: "api.elastic-inference.us-east-2.amazonaws.com",
},
"us-west-2": endpoint{
Hostname: "api.elastic-inference.us-west-2.amazonaws.com",
},
},
},
"elasticache": service{
@ -1807,12 +1885,36 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"fips-us-east-1": endpoint{
Hostname: "elasticbeanstalk-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-east-2": endpoint{
Hostname: "elasticbeanstalk-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"fips-us-west-1": endpoint{
Hostname: "elasticbeanstalk-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"fips-us-west-2": endpoint{
Hostname: "elasticbeanstalk-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"elasticfilesystem": service{
@ -2072,12 +2174,36 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"fips-us-east-1": endpoint{
Hostname: "firehose-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-east-2": endpoint{
Hostname: "firehose-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"fips-us-west-1": endpoint{
Hostname: "firehose-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"fips-us-west-2": endpoint{
Hostname: "firehose-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"fms": service{
@ -2226,6 +2352,7 @@ var awsPartition = partition{
"fsx": service{
Endpoints: endpoints{
"ap-east-1": endpoint{},
"ap-northeast-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
@ -2358,10 +2485,11 @@ var awsPartition = partition{
"groundstation": service{
Endpoints: endpoints{
"eu-north-1": endpoint{},
"me-south-1": endpoint{},
"us-east-2": endpoint{},
"us-west-2": endpoint{},
"ap-southeast-2": endpoint{},
"eu-north-1": endpoint{},
"me-south-1": endpoint{},
"us-east-2": endpoint{},
"us-west-2": endpoint{},
},
},
"guardduty": service{
@ -2689,12 +2817,36 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"fips-us-east-1": endpoint{
Hostname: "kinesis-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-east-2": endpoint{
Hostname: "kinesis-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"fips-us-west-1": endpoint{
Hostname: "kinesis-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"fips-us-west-2": endpoint{
Hostname: "kinesis-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"kinesisanalytics": service{
@ -2818,12 +2970,36 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"fips-us-east-1": endpoint{
Hostname: "license-manager-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-east-2": endpoint{
Hostname: "license-manager-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"fips-us-west-1": endpoint{
Hostname: "license-manager-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"fips-us-west-2": endpoint{
Hostname: "license-manager-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"lightsail": service{
@ -3052,12 +3228,36 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"fips-us-east-1": endpoint{
Hostname: "monitoring-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-east-2": endpoint{
Hostname: "monitoring-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"fips-us-west-1": endpoint{
Hostname: "monitoring-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"fips-us-west-2": endpoint{
Hostname: "monitoring-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"mq": service{
@ -4599,25 +4799,25 @@ var awsPartition = partition{
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"ssm-facade-fips-us-east-1": endpoint{
Hostname: "#ssm-facade-fips.us-east-1.amazonaws.com",
Hostname: "ssm-facade-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"ssm-facade-fips-us-east-2": endpoint{
Hostname: "#ssm-facade-fips.us-east-2.amazonaws.com",
Hostname: "ssm-facade-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"ssm-facade-fips-us-west-1": endpoint{
Hostname: "#ssm-facade-fips.us-west-1.amazonaws.com",
Hostname: "ssm-facade-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"ssm-facade-fips-us-west-2": endpoint{
Hostname: "#ssm-facade-fips.us-west-2.amazonaws.com",
Hostname: "ssm-facade-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
@ -5024,6 +5224,12 @@ var awsPartition = partition{
IsRegionalized: boxedFalse,
Endpoints: endpoints{
"aws-fips": endpoint{
Hostname: "waf-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"aws-global": endpoint{
Hostname: "waf.amazonaws.com",
CredentialScope: credentialScope{
@ -5035,22 +5241,222 @@ var awsPartition = partition{
"waf-regional": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"ap-east-1": endpoint{
Hostname: "waf-regional.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
},
"ap-northeast-1": endpoint{
Hostname: "waf-regional.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
"ap-northeast-2": endpoint{
Hostname: "waf-regional.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
"ap-south-1": endpoint{
Hostname: "waf-regional.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
"ap-southeast-1": endpoint{
Hostname: "waf-regional.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
"ap-southeast-2": endpoint{
Hostname: "waf-regional.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
"ca-central-1": endpoint{
Hostname: "waf-regional.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
"eu-central-1": endpoint{
Hostname: "waf-regional.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
"eu-north-1": endpoint{
Hostname: "waf-regional.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
"eu-west-1": endpoint{
Hostname: "waf-regional.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
"eu-west-2": endpoint{
Hostname: "waf-regional.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
"eu-west-3": endpoint{
Hostname: "waf-regional.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
"fips-ap-east-1": endpoint{
Hostname: "waf-regional-fips.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
},
"fips-ap-northeast-1": endpoint{
Hostname: "waf-regional-fips.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
"fips-ap-northeast-2": endpoint{
Hostname: "waf-regional-fips.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
"fips-ap-south-1": endpoint{
Hostname: "waf-regional-fips.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
"fips-ap-southeast-1": endpoint{
Hostname: "waf-regional-fips.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
"fips-ap-southeast-2": endpoint{
Hostname: "waf-regional-fips.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
"fips-ca-central-1": endpoint{
Hostname: "waf-regional-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
"fips-eu-central-1": endpoint{
Hostname: "waf-regional-fips.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
"fips-eu-north-1": endpoint{
Hostname: "waf-regional-fips.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
"fips-eu-west-1": endpoint{
Hostname: "waf-regional-fips.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
"fips-eu-west-2": endpoint{
Hostname: "waf-regional-fips.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
"fips-eu-west-3": endpoint{
Hostname: "waf-regional-fips.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
"fips-me-south-1": endpoint{
Hostname: "waf-regional-fips.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
},
"fips-sa-east-1": endpoint{
Hostname: "waf-regional-fips.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
"fips-us-east-1": endpoint{
Hostname: "waf-regional-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-east-2": endpoint{
Hostname: "waf-regional-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"fips-us-west-1": endpoint{
Hostname: "waf-regional-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"fips-us-west-2": endpoint{
Hostname: "waf-regional-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"me-south-1": endpoint{
Hostname: "waf-regional.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
},
"sa-east-1": endpoint{
Hostname: "waf-regional.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
"us-east-1": endpoint{
Hostname: "waf-regional.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"us-east-2": endpoint{
Hostname: "waf-regional.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"us-west-1": endpoint{
Hostname: "waf-regional.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"us-west-2": endpoint{
Hostname: "waf-regional.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"workdocs": service{
@ -5060,8 +5466,20 @@ var awsPartition = partition{
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"eu-west-1": endpoint{},
"us-east-1": endpoint{},
"us-west-2": endpoint{},
"fips-us-east-1": endpoint{
Hostname: "workdocs-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-west-2": endpoint{
Hostname: "workdocs-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"us-east-1": endpoint{},
"us-west-2": endpoint{},
},
},
"workmail": service{
@ -5962,7 +6380,19 @@ var awsusgovPartition = partition{
Endpoints: endpoints{
"us-gov-east-1": endpoint{},
"us-gov-east-1-fips": endpoint{
Hostname: "codebuild-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
"us-gov-west-1": endpoint{},
"us-gov-west-1-fips": endpoint{
Hostname: "codebuild-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"codecommit": service{
@ -5997,6 +6427,18 @@ var awsusgovPartition = partition{
},
},
},
"codepipeline": service{
Endpoints: endpoints{
"fips-us-gov-west-1": endpoint{
Hostname: "codepipeline-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-west-1": endpoint{},
},
},
"comprehend": service{
Defaults: endpoint{
Protocols: []string{"https"},
@ -6110,6 +6552,18 @@ var awsusgovPartition = partition{
"ecs": service{
Endpoints: endpoints{
"fips-us-gov-east-1": endpoint{
Hostname: "ecs-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
"fips-us-gov-west-1": endpoint{
Hostname: "ecs-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
},
@ -6130,8 +6584,18 @@ var awsusgovPartition = partition{
"elasticbeanstalk": service{
Endpoints: endpoints{
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
"us-gov-east-1": endpoint{
Hostname: "elasticbeanstalk.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
"us-gov-west-1": endpoint{
Hostname: "elasticbeanstalk.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"elasticfilesystem": service{
@ -6182,6 +6646,18 @@ var awsusgovPartition = partition{
"firehose": service{
Endpoints: endpoints{
"fips-us-gov-east-1": endpoint{
Hostname: "firehose-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
"fips-us-gov-west-1": endpoint{
Hostname: "firehose-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
},
@ -6313,6 +6789,18 @@ var awsusgovPartition = partition{
"license-manager": service{
Endpoints: endpoints{
"fips-us-gov-east-1": endpoint{
Hostname: "license-manager-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
"fips-us-gov-west-1": endpoint{
Hostname: "license-manager-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
},
@ -6344,6 +6832,18 @@ var awsusgovPartition = partition{
"monitoring": service{
Endpoints: endpoints{
"fips-us-gov-east-1": endpoint{
Hostname: "monitoring.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
"fips-us-gov-west-1": endpoint{
Hostname: "monitoring.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
},
@ -6781,7 +7281,18 @@ var awsusgovPartition = partition{
"waf-regional": service{
Endpoints: endpoints{
"us-gov-west-1": endpoint{},
"fips-us-gov-west-1": endpoint{
Hostname: "waf-regional-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-west-1": endpoint{
Hostname: "waf-regional.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"workspaces": service{

View File

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "1.29.34"
const SDKVersion = "1.30.5"

View File

@ -0,0 +1,13 @@
language: go
go:
- 1.4.x
- 1.5.x
- 1.6.x
- 1.7.x
- 1.8.x
- 1.9.x
- 1.10.x
- 1.11.x
- 1.12.x
- tip

19
vendor/github.com/kelseyhightower/envconfig/LICENSE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2013 Kelsey Hightower
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,2 @@
Kelsey Hightower kelsey.hightower@gmail.com github.com/kelseyhightower
Travis Parker travis.parker@gmail.com github.com/teepark

192
vendor/github.com/kelseyhightower/envconfig/README.md generated vendored Normal file
View File

@ -0,0 +1,192 @@
# envconfig
[![Build Status](https://travis-ci.org/kelseyhightower/envconfig.svg)](https://travis-ci.org/kelseyhightower/envconfig)
```Go
import "github.com/kelseyhightower/envconfig"
```
## Documentation
See [godoc](http://godoc.org/github.com/kelseyhightower/envconfig)
## Usage
Set some environment variables:
```Bash
export MYAPP_DEBUG=false
export MYAPP_PORT=8080
export MYAPP_USER=Kelsey
export MYAPP_RATE="0.5"
export MYAPP_TIMEOUT="3m"
export MYAPP_USERS="rob,ken,robert"
export MYAPP_COLORCODES="red:1,green:2,blue:3"
```
Write some code:
```Go
package main
import (
"fmt"
"log"
"time"
"github.com/kelseyhightower/envconfig"
)
type Specification struct {
Debug bool
Port int
User string
Users []string
Rate float32
Timeout time.Duration
ColorCodes map[string]int
}
func main() {
var s Specification
err := envconfig.Process("myapp", &s)
if err != nil {
log.Fatal(err.Error())
}
format := "Debug: %v\nPort: %d\nUser: %s\nRate: %f\nTimeout: %s\n"
_, err = fmt.Printf(format, s.Debug, s.Port, s.User, s.Rate, s.Timeout)
if err != nil {
log.Fatal(err.Error())
}
fmt.Println("Users:")
for _, u := range s.Users {
fmt.Printf(" %s\n", u)
}
fmt.Println("Color codes:")
for k, v := range s.ColorCodes {
fmt.Printf(" %s: %d\n", k, v)
}
}
```
Results:
```Bash
Debug: false
Port: 8080
User: Kelsey
Rate: 0.500000
Timeout: 3m0s
Users:
rob
ken
robert
Color codes:
red: 1
green: 2
blue: 3
```
## Struct Tag Support
Envconfig supports the use of struct tags to specify alternate, default, and required
environment variables.
For example, consider the following struct:
```Go
type Specification struct {
ManualOverride1 string `envconfig:"manual_override_1"`
DefaultVar string `default:"foobar"`
RequiredVar string `required:"true"`
IgnoredVar string `ignored:"true"`
AutoSplitVar string `split_words:"true"`
RequiredAndAutoSplitVar string `required:"true" split_words:"true"`
}
```
Envconfig has automatic support for CamelCased struct elements when the
`split_words:"true"` tag is supplied. Without this tag, `AutoSplitVar` above
would look for an environment variable called `MYAPP_AUTOSPLITVAR`. With the
setting applied it will look for `MYAPP_AUTO_SPLIT_VAR`. Note that numbers
will get globbed into the previous word. If the setting does not do the
right thing, you may use a manual override.
Envconfig will process value for `ManualOverride1` by populating it with the
value for `MYAPP_MANUAL_OVERRIDE_1`. Without this struct tag, it would have
instead looked up `MYAPP_MANUALOVERRIDE1`. With the `split_words:"true"` tag
it would have looked up `MYAPP_MANUAL_OVERRIDE1`.
```Bash
export MYAPP_MANUAL_OVERRIDE_1="this will be the value"
# export MYAPP_MANUALOVERRIDE1="and this will not"
```
If envconfig can't find an environment variable value for `MYAPP_DEFAULTVAR`,
it will populate it with "foobar" as a default value.
If envconfig can't find an environment variable value for `MYAPP_REQUIREDVAR`,
it will return an error when asked to process the struct. If
`MYAPP_REQUIREDVAR` is present but empty, envconfig will not return an error.
If envconfig can't find an environment variable in the form `PREFIX_MYVAR`, and there
is a struct tag defined, it will try to populate your variable with an environment
variable that directly matches the envconfig tag in your struct definition:
```shell
export SERVICE_HOST=127.0.0.1
export MYAPP_DEBUG=true
```
```Go
type Specification struct {
ServiceHost string `envconfig:"SERVICE_HOST"`
Debug bool
}
```
Envconfig won't process a field with the "ignored" tag set to "true", even if a corresponding
environment variable is set.
## Supported Struct Field Types
envconfig supports these struct field types:
* string
* int8, int16, int32, int64
* bool
* float32, float64
* slices of any supported type
* maps (keys and values of any supported type)
* [encoding.TextUnmarshaler](https://golang.org/pkg/encoding/#TextUnmarshaler)
* [encoding.BinaryUnmarshaler](https://golang.org/pkg/encoding/#BinaryUnmarshaler)
* [time.Duration](https://golang.org/pkg/time/#Duration)
Embedded structs using these fields are also supported.
## Custom Decoders
Any field whose type (or pointer-to-type) implements `envconfig.Decoder` can
control its own deserialization:
```Bash
export DNS_SERVER=8.8.8.8
```
```Go
type IPDecoder net.IP
func (ipd *IPDecoder) Decode(value string) error {
*ipd = IPDecoder(net.ParseIP(value))
return nil
}
type DNSConfig struct {
Address IPDecoder `envconfig:"DNS_SERVER"`
}
```
Also, envconfig will use a `Set(string) error` method like from the
[flag.Value](https://godoc.org/flag#Value) interface if implemented.

8
vendor/github.com/kelseyhightower/envconfig/doc.go generated vendored Normal file
View File

@ -0,0 +1,8 @@
// Copyright (c) 2013 Kelsey Hightower. All rights reserved.
// Use of this source code is governed by the MIT License that can be found in
// the LICENSE file.
// Package envconfig implements decoding of environment variables based on a user
// defined specification. A typical use is using environment variables for
// configuration settings.
package envconfig

View File

@ -0,0 +1,7 @@
// +build appengine go1.5
package envconfig
import "os"
var lookupEnv = os.LookupEnv

View File

@ -0,0 +1,7 @@
// +build !appengine,!go1.5
package envconfig
import "syscall"
var lookupEnv = syscall.Getenv

View File

@ -0,0 +1,382 @@
// Copyright (c) 2013 Kelsey Hightower. All rights reserved.
// Use of this source code is governed by the MIT License that can be found in
// the LICENSE file.
package envconfig
import (
"encoding"
"errors"
"fmt"
"os"
"reflect"
"regexp"
"strconv"
"strings"
"time"
)
// ErrInvalidSpecification indicates that a specification is of the wrong type.
var ErrInvalidSpecification = errors.New("specification must be a struct pointer")
var gatherRegexp = regexp.MustCompile("([^A-Z]+|[A-Z]+[^A-Z]+|[A-Z]+)")
var acronymRegexp = regexp.MustCompile("([A-Z]+)([A-Z][^A-Z]+)")
// A ParseError occurs when an environment variable cannot be converted to
// the type required by a struct field during assignment.
type ParseError struct {
KeyName string
FieldName string
TypeName string
Value string
Err error
}
// Decoder has the same semantics as Setter, but takes higher precedence.
// It is provided for historical compatibility.
type Decoder interface {
Decode(value string) error
}
// Setter is implemented by types can self-deserialize values.
// Any type that implements flag.Value also implements Setter.
type Setter interface {
Set(value string) error
}
func (e *ParseError) Error() string {
return fmt.Sprintf("envconfig.Process: assigning %[1]s to %[2]s: converting '%[3]s' to type %[4]s. details: %[5]s", e.KeyName, e.FieldName, e.Value, e.TypeName, e.Err)
}
// varInfo maintains information about the configuration variable
type varInfo struct {
Name string
Alt string
Key string
Field reflect.Value
Tags reflect.StructTag
}
// GatherInfo gathers information about the specified struct
func gatherInfo(prefix string, spec interface{}) ([]varInfo, error) {
s := reflect.ValueOf(spec)
if s.Kind() != reflect.Ptr {
return nil, ErrInvalidSpecification
}
s = s.Elem()
if s.Kind() != reflect.Struct {
return nil, ErrInvalidSpecification
}
typeOfSpec := s.Type()
// over allocate an info array, we will extend if needed later
infos := make([]varInfo, 0, s.NumField())
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
ftype := typeOfSpec.Field(i)
if !f.CanSet() || isTrue(ftype.Tag.Get("ignored")) {
continue
}
for f.Kind() == reflect.Ptr {
if f.IsNil() {
if f.Type().Elem().Kind() != reflect.Struct {
// nil pointer to a non-struct: leave it alone
break
}
// nil pointer to struct: create a zero instance
f.Set(reflect.New(f.Type().Elem()))
}
f = f.Elem()
}
// Capture information about the config variable
info := varInfo{
Name: ftype.Name,
Field: f,
Tags: ftype.Tag,
Alt: strings.ToUpper(ftype.Tag.Get("envconfig")),
}
// Default to the field name as the env var name (will be upcased)
info.Key = info.Name
// Best effort to un-pick camel casing as separate words
if isTrue(ftype.Tag.Get("split_words")) {
words := gatherRegexp.FindAllStringSubmatch(ftype.Name, -1)
if len(words) > 0 {
var name []string
for _, words := range words {
if m := acronymRegexp.FindStringSubmatch(words[0]); len(m) == 3 {
name = append(name, m[1], m[2])
} else {
name = append(name, words[0])
}
}
info.Key = strings.Join(name, "_")
}
}
if info.Alt != "" {
info.Key = info.Alt
}
if prefix != "" {
info.Key = fmt.Sprintf("%s_%s", prefix, info.Key)
}
info.Key = strings.ToUpper(info.Key)
infos = append(infos, info)
if f.Kind() == reflect.Struct {
// honor Decode if present
if decoderFrom(f) == nil && setterFrom(f) == nil && textUnmarshaler(f) == nil && binaryUnmarshaler(f) == nil {
innerPrefix := prefix
if !ftype.Anonymous {
innerPrefix = info.Key
}
embeddedPtr := f.Addr().Interface()
embeddedInfos, err := gatherInfo(innerPrefix, embeddedPtr)
if err != nil {
return nil, err
}
infos = append(infos[:len(infos)-1], embeddedInfos...)
continue
}
}
}
return infos, nil
}
// CheckDisallowed checks that no environment variables with the prefix are set
// that we don't know how or want to parse. This is likely only meaningful with
// a non-empty prefix.
func CheckDisallowed(prefix string, spec interface{}) error {
infos, err := gatherInfo(prefix, spec)
if err != nil {
return err
}
vars := make(map[string]struct{})
for _, info := range infos {
vars[info.Key] = struct{}{}
}
if prefix != "" {
prefix = strings.ToUpper(prefix) + "_"
}
for _, env := range os.Environ() {
if !strings.HasPrefix(env, prefix) {
continue
}
v := strings.SplitN(env, "=", 2)[0]
if _, found := vars[v]; !found {
return fmt.Errorf("unknown environment variable %s", v)
}
}
return nil
}
// Process populates the specified struct based on environment variables
func Process(prefix string, spec interface{}) error {
infos, err := gatherInfo(prefix, spec)
for _, info := range infos {
// `os.Getenv` cannot differentiate between an explicitly set empty value
// and an unset value. `os.LookupEnv` is preferred to `syscall.Getenv`,
// but it is only available in go1.5 or newer. We're using Go build tags
// here to use os.LookupEnv for >=go1.5
value, ok := lookupEnv(info.Key)
if !ok && info.Alt != "" {
value, ok = lookupEnv(info.Alt)
}
def := info.Tags.Get("default")
if def != "" && !ok {
value = def
}
req := info.Tags.Get("required")
if !ok && def == "" {
if isTrue(req) {
key := info.Key
if info.Alt != "" {
key = info.Alt
}
return fmt.Errorf("required key %s missing value", key)
}
continue
}
err = processField(value, info.Field)
if err != nil {
return &ParseError{
KeyName: info.Key,
FieldName: info.Name,
TypeName: info.Field.Type().String(),
Value: value,
Err: err,
}
}
}
return err
}
// MustProcess is the same as Process but panics if an error occurs
func MustProcess(prefix string, spec interface{}) {
if err := Process(prefix, spec); err != nil {
panic(err)
}
}
func processField(value string, field reflect.Value) error {
typ := field.Type()
decoder := decoderFrom(field)
if decoder != nil {
return decoder.Decode(value)
}
// look for Set method if Decode not defined
setter := setterFrom(field)
if setter != nil {
return setter.Set(value)
}
if t := textUnmarshaler(field); t != nil {
return t.UnmarshalText([]byte(value))
}
if b := binaryUnmarshaler(field); b != nil {
return b.UnmarshalBinary([]byte(value))
}
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
if field.IsNil() {
field.Set(reflect.New(typ))
}
field = field.Elem()
}
switch typ.Kind() {
case reflect.String:
field.SetString(value)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
var (
val int64
err error
)
if field.Kind() == reflect.Int64 && typ.PkgPath() == "time" && typ.Name() == "Duration" {
var d time.Duration
d, err = time.ParseDuration(value)
val = int64(d)
} else {
val, err = strconv.ParseInt(value, 0, typ.Bits())
}
if err != nil {
return err
}
field.SetInt(val)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
val, err := strconv.ParseUint(value, 0, typ.Bits())
if err != nil {
return err
}
field.SetUint(val)
case reflect.Bool:
val, err := strconv.ParseBool(value)
if err != nil {
return err
}
field.SetBool(val)
case reflect.Float32, reflect.Float64:
val, err := strconv.ParseFloat(value, typ.Bits())
if err != nil {
return err
}
field.SetFloat(val)
case reflect.Slice:
sl := reflect.MakeSlice(typ, 0, 0)
if typ.Elem().Kind() == reflect.Uint8 {
sl = reflect.ValueOf([]byte(value))
} else if len(strings.TrimSpace(value)) != 0 {
vals := strings.Split(value, ",")
sl = reflect.MakeSlice(typ, len(vals), len(vals))
for i, val := range vals {
err := processField(val, sl.Index(i))
if err != nil {
return err
}
}
}
field.Set(sl)
case reflect.Map:
mp := reflect.MakeMap(typ)
if len(strings.TrimSpace(value)) != 0 {
pairs := strings.Split(value, ",")
for _, pair := range pairs {
kvpair := strings.Split(pair, ":")
if len(kvpair) != 2 {
return fmt.Errorf("invalid map item: %q", pair)
}
k := reflect.New(typ.Key()).Elem()
err := processField(kvpair[0], k)
if err != nil {
return err
}
v := reflect.New(typ.Elem()).Elem()
err = processField(kvpair[1], v)
if err != nil {
return err
}
mp.SetMapIndex(k, v)
}
}
field.Set(mp)
}
return nil
}
func interfaceFrom(field reflect.Value, fn func(interface{}, *bool)) {
// it may be impossible for a struct field to fail this check
if !field.CanInterface() {
return
}
var ok bool
fn(field.Interface(), &ok)
if !ok && field.CanAddr() {
fn(field.Addr().Interface(), &ok)
}
}
func decoderFrom(field reflect.Value) (d Decoder) {
interfaceFrom(field, func(v interface{}, ok *bool) { d, *ok = v.(Decoder) })
return d
}
func setterFrom(field reflect.Value) (s Setter) {
interfaceFrom(field, func(v interface{}, ok *bool) { s, *ok = v.(Setter) })
return s
}
func textUnmarshaler(field reflect.Value) (t encoding.TextUnmarshaler) {
interfaceFrom(field, func(v interface{}, ok *bool) { t, *ok = v.(encoding.TextUnmarshaler) })
return t
}
func binaryUnmarshaler(field reflect.Value) (b encoding.BinaryUnmarshaler) {
interfaceFrom(field, func(v interface{}, ok *bool) { b, *ok = v.(encoding.BinaryUnmarshaler) })
return b
}
func isTrue(s string) bool {
b, _ := strconv.ParseBool(s)
return b
}

1
vendor/github.com/kelseyhightower/envconfig/go.mod generated vendored Normal file
View File

@ -0,0 +1 @@
module github.com/kelseyhightower/envconfig

164
vendor/github.com/kelseyhightower/envconfig/usage.go generated vendored Normal file
View File

@ -0,0 +1,164 @@
// Copyright (c) 2016 Kelsey Hightower and others. All rights reserved.
// Use of this source code is governed by the MIT License that can be found in
// the LICENSE file.
package envconfig
import (
"encoding"
"fmt"
"io"
"os"
"reflect"
"strconv"
"strings"
"text/tabwriter"
"text/template"
)
const (
// DefaultListFormat constant to use to display usage in a list format
DefaultListFormat = `This application is configured via the environment. The following environment
variables can be used:
{{range .}}
{{usage_key .}}
[description] {{usage_description .}}
[type] {{usage_type .}}
[default] {{usage_default .}}
[required] {{usage_required .}}{{end}}
`
// DefaultTableFormat constant to use to display usage in a tabular format
DefaultTableFormat = `This application is configured via the environment. The following environment
variables can be used:
KEY TYPE DEFAULT REQUIRED DESCRIPTION
{{range .}}{{usage_key .}} {{usage_type .}} {{usage_default .}} {{usage_required .}} {{usage_description .}}
{{end}}`
)
var (
decoderType = reflect.TypeOf((*Decoder)(nil)).Elem()
setterType = reflect.TypeOf((*Setter)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
binaryUnmarshalerType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
)
func implementsInterface(t reflect.Type) bool {
return t.Implements(decoderType) ||
reflect.PtrTo(t).Implements(decoderType) ||
t.Implements(setterType) ||
reflect.PtrTo(t).Implements(setterType) ||
t.Implements(textUnmarshalerType) ||
reflect.PtrTo(t).Implements(textUnmarshalerType) ||
t.Implements(binaryUnmarshalerType) ||
reflect.PtrTo(t).Implements(binaryUnmarshalerType)
}
// toTypeDescription converts Go types into a human readable description
func toTypeDescription(t reflect.Type) string {
switch t.Kind() {
case reflect.Array, reflect.Slice:
if t.Elem().Kind() == reflect.Uint8 {
return "String"
}
return fmt.Sprintf("Comma-separated list of %s", toTypeDescription(t.Elem()))
case reflect.Map:
return fmt.Sprintf(
"Comma-separated list of %s:%s pairs",
toTypeDescription(t.Key()),
toTypeDescription(t.Elem()),
)
case reflect.Ptr:
return toTypeDescription(t.Elem())
case reflect.Struct:
if implementsInterface(t) && t.Name() != "" {
return t.Name()
}
return ""
case reflect.String:
name := t.Name()
if name != "" && name != "string" {
return name
}
return "String"
case reflect.Bool:
name := t.Name()
if name != "" && name != "bool" {
return name
}
return "True or False"
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
name := t.Name()
if name != "" && !strings.HasPrefix(name, "int") {
return name
}
return "Integer"
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
name := t.Name()
if name != "" && !strings.HasPrefix(name, "uint") {
return name
}
return "Unsigned Integer"
case reflect.Float32, reflect.Float64:
name := t.Name()
if name != "" && !strings.HasPrefix(name, "float") {
return name
}
return "Float"
}
return fmt.Sprintf("%+v", t)
}
// Usage writes usage information to stdout using the default header and table format
func Usage(prefix string, spec interface{}) error {
// The default is to output the usage information as a table
// Create tabwriter instance to support table output
tabs := tabwriter.NewWriter(os.Stdout, 1, 0, 4, ' ', 0)
err := Usagef(prefix, spec, tabs, DefaultTableFormat)
tabs.Flush()
return err
}
// Usagef writes usage information to the specified io.Writer using the specifed template specification
func Usagef(prefix string, spec interface{}, out io.Writer, format string) error {
// Specify the default usage template functions
functions := template.FuncMap{
"usage_key": func(v varInfo) string { return v.Key },
"usage_description": func(v varInfo) string { return v.Tags.Get("desc") },
"usage_type": func(v varInfo) string { return toTypeDescription(v.Field.Type()) },
"usage_default": func(v varInfo) string { return v.Tags.Get("default") },
"usage_required": func(v varInfo) (string, error) {
req := v.Tags.Get("required")
if req != "" {
reqB, err := strconv.ParseBool(req)
if err != nil {
return "", err
}
if reqB {
req = "true"
}
}
return req, nil
},
}
tmpl, err := template.New("envconfig").Funcs(functions).Parse(format)
if err != nil {
return err
}
return Usaget(prefix, spec, out, tmpl)
}
// Usaget writes usage information to the specified io.Writer using the specified template
func Usaget(prefix string, spec interface{}, out io.Writer, tmpl *template.Template) error {
// gather first
infos, err := gatherInfo(prefix, spec)
if err != nil {
return err
}
return tmpl.Execute(out, infos)
}

27
vendor/go.opencensus.io/Makefile generated vendored
View File

@ -8,7 +8,7 @@ ALL_PKGS := $(shell go list $(sort $(dir $(ALL_SRC))))
GOTEST_OPT?=-v -race -timeout 30s
GOTEST_OPT_WITH_COVERAGE = $(GOTEST_OPT) -coverprofile=coverage.txt -covermode=atomic
GOTEST=go test
GOFMT=gofmt
GOIMPORTS=goimports
GOLINT=golint
GOVET=go vet
EMBEDMD=embedmd
@ -17,14 +17,14 @@ TRACE_ID_LINT_EXCEPTION="type name will be used as trace.TraceID by other packag
TRACE_OPTION_LINT_EXCEPTION="type name will be used as trace.TraceOptions by other packages"
README_FILES := $(shell find . -name '*README.md' | sort | tr '\n' ' ')
.DEFAULT_GOAL := fmt-lint-vet-embedmd-test
.DEFAULT_GOAL := imports-lint-vet-embedmd-test
.PHONY: fmt-lint-vet-embedmd-test
fmt-lint-vet-embedmd-test: fmt lint vet embedmd test
.PHONY: imports-lint-vet-embedmd-test
imports-lint-vet-embedmd-test: imports lint vet embedmd test
# TODO enable test-with-coverage in tavis
.PHONY: travis-ci
travis-ci: fmt lint vet embedmd test test-386
travis-ci: imports lint vet embedmd test test-386
all-pkgs:
@echo $(ALL_PKGS) | tr ' ' '\n' | sort
@ -44,15 +44,15 @@ test-386:
test-with-coverage:
$(GOTEST) $(GOTEST_OPT_WITH_COVERAGE) $(ALL_PKGS)
.PHONY: fmt
fmt:
@FMTOUT=`$(GOFMT) -s -l $(ALL_SRC) 2>&1`; \
if [ "$$FMTOUT" ]; then \
echo "$(GOFMT) FAILED => gofmt the following files:\n"; \
echo "$$FMTOUT\n"; \
.PHONY: imports
imports:
@IMPORTSOUT=`$(GOIMPORTS) -l $(ALL_SRC) 2>&1`; \
if [ "$$IMPORTSOUT" ]; then \
echo "$(GOIMPORTS) FAILED => goimports the following files:\n"; \
echo "$$IMPORTSOUT\n"; \
exit 1; \
else \
echo "Fmt finished successfully"; \
echo "Imports finished successfully"; \
fi
.PHONY: lint
@ -91,6 +91,7 @@ embedmd:
.PHONY: install-tools
install-tools:
go get -u golang.org/x/tools/cmd/cover
go get -u golang.org/x/lint/golint
go get -u golang.org/x/tools/cmd/cover
go get -u golang.org/x/tools/cmd/goimports
go get -u github.com/rakyll/embedmd

View File

@ -16,8 +16,8 @@ package ocgrpc
import (
"context"
"go.opencensus.io/trace"
"go.opencensus.io/trace"
"google.golang.org/grpc/stats"
)

View File

@ -16,9 +16,10 @@ package ocgrpc
import (
"context"
"go.opencensus.io/trace"
"google.golang.org/grpc/stats"
"go.opencensus.io/trace"
)
// ServerHandler implements gRPC stats.Handler recording OpenCensus stats and

View File

@ -15,16 +15,16 @@
package ocgrpc
import (
"context"
"strings"
"google.golang.org/grpc/codes"
"context"
"go.opencensus.io/trace"
"go.opencensus.io/trace/propagation"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/stats"
"google.golang.org/grpc/status"
"go.opencensus.io/trace"
"go.opencensus.io/trace/propagation"
)
const traceContextKey = "grpc-trace-bin"

View File

@ -68,7 +68,7 @@ func ParseTraceID(tid string) (trace.TraceID, bool) {
return trace.TraceID{}, false
}
b, err := hex.DecodeString(tid)
if err != nil {
if err != nil || len(b) > 16 {
return trace.TraceID{}, false
}
var traceID trace.TraceID
@ -90,7 +90,7 @@ func ParseSpanID(sid string) (spanID trace.SpanID, ok bool) {
return trace.SpanID{}, false
}
b, err := hex.DecodeString(sid)
if err != nil {
if err != nil || len(b) > 8 {
return trace.SpanID{}, false
}
start := 8 - len(b)

View File

@ -31,10 +31,19 @@ func init() {
}
}
// Recorder provides an interface for exporting measurement information from
// the static Record method by using the WithRecorder option.
type Recorder interface {
// Record records a set of measurements associated with the given tags and attachments.
// The second argument is a `[]Measurement`.
Record(*tag.Map, interface{}, map[string]interface{})
}
type recordOptions struct {
attachments metricdata.Attachments
mutators []tag.Mutator
measurements []Measurement
recorder Recorder
}
// WithAttachments applies provided exemplar attachments.
@ -58,6 +67,14 @@ func WithMeasurements(measurements ...Measurement) Options {
}
}
// WithRecorder records the measurements to the specified `Recorder`, rather
// than to the global metrics recorder.
func WithRecorder(meter Recorder) Options {
return func(ro *recordOptions) {
ro.recorder = meter
}
}
// Options apply changes to recordOptions.
type Options func(*recordOptions)
@ -93,6 +110,9 @@ func RecordWithOptions(ctx context.Context, ros ...Options) error {
return nil
}
recorder := internal.DefaultRecorder
if o.recorder != nil {
recorder = o.recorder.Record
}
if recorder == nil {
return nil
}

View File

@ -14,13 +14,6 @@
package view
import "sync"
var (
exportersMu sync.RWMutex // guards exporters
exporters = make(map[Exporter]struct{})
)
// Exporter exports the collected records as view data.
//
// The ExportView method should return quickly; if an
@ -43,16 +36,10 @@ type Exporter interface {
//
// Binaries can register exporters, libraries shouldn't register exporters.
func RegisterExporter(e Exporter) {
exportersMu.Lock()
defer exportersMu.Unlock()
exporters[e] = struct{}{}
defaultWorker.RegisterExporter(e)
}
// UnregisterExporter unregisters an exporter.
func UnregisterExporter(e Exporter) {
exportersMu.Lock()
defer exportersMu.Unlock()
delete(exporters, e)
defaultWorker.UnregisterExporter(e)
}

View File

@ -18,6 +18,8 @@ package view
import (
"time"
"go.opencensus.io/resource"
"go.opencensus.io/metric/metricdata"
"go.opencensus.io/stats"
)
@ -125,7 +127,7 @@ func rowToTimeseries(v *viewInternal, row *Row, now time.Time, startTime time.Ti
}
}
func viewToMetric(v *viewInternal, now time.Time, startTime time.Time) *metricdata.Metric {
func viewToMetric(v *viewInternal, r *resource.Resource, now time.Time, startTime time.Time) *metricdata.Metric {
if v.metricDescriptor.Type == metricdata.TypeGaugeInt64 ||
v.metricDescriptor.Type == metricdata.TypeGaugeFloat64 {
startTime = time.Time{}
@ -144,6 +146,7 @@ func viewToMetric(v *viewInternal, now time.Time, startTime time.Time) *metricda
m := &metricdata.Metric{
Descriptor: *v.metricDescriptor,
TimeSeries: ts,
Resource: r,
}
return m
}

View File

@ -20,6 +20,8 @@ import (
"sync"
"time"
"go.opencensus.io/resource"
"go.opencensus.io/metric/metricdata"
"go.opencensus.io/metric/metricproducer"
"go.opencensus.io/stats"
@ -28,7 +30,7 @@ import (
)
func init() {
defaultWorker = newWorker()
defaultWorker = NewMeter().(*worker)
go defaultWorker.start()
internal.DefaultRecorder = record
}
@ -47,8 +49,69 @@ type worker struct {
c chan command
quit, done chan bool
mu sync.RWMutex
r *resource.Resource
exportersMu sync.RWMutex
exporters map[Exporter]struct{}
}
// Meter defines an interface which allows a single process to maintain
// multiple sets of metrics exports (intended for the advanced case where a
// single process wants to report metrics about multiple objects, such as
// multiple databases or HTTP services).
//
// Note that this is an advanced use case, and the static functions in this
// module should cover the common use cases.
type Meter interface {
stats.Recorder
// Find returns a registered view associated with this name.
// If no registered view is found, nil is returned.
Find(name string) *View
// Register begins collecting data for the given views.
// Once a view is registered, it reports data to the registered exporters.
Register(views ...*View) error
// Unregister the given views. Data will not longer be exported for these views
// after Unregister returns.
// It is not necessary to unregister from views you expect to collect for the
// duration of your program execution.
Unregister(views ...*View)
// SetReportingPeriod sets the interval between reporting aggregated views in
// the program. If duration is less than or equal to zero, it enables the
// default behavior.
//
// Note: each exporter makes different promises about what the lowest supported
// duration is. For example, the Stackdriver exporter recommends a value no
// lower than 1 minute. Consult each exporter per your needs.
SetReportingPeriod(time.Duration)
// RegisterExporter registers an exporter.
// Collected data will be reported via all the
// registered exporters. Once you no longer
// want data to be exported, invoke UnregisterExporter
// with the previously registered exporter.
//
// Binaries can register exporters, libraries shouldn't register exporters.
RegisterExporter(Exporter)
// UnregisterExporter unregisters an exporter.
UnregisterExporter(Exporter)
// SetResource may be used to set the Resource associated with this registry.
// This is intended to be used in cases where a single process exports metrics
// for multiple Resources, typically in a multi-tenant situation.
SetResource(*resource.Resource)
// Start causes the Meter to start processing Record calls and aggregating
// statistics as well as exporting data.
Start()
// Stop causes the Meter to stop processing calls and terminate data export.
Stop()
// RetrieveData gets a snapshot of the data collected for the the view registered
// with the given name. It is intended for testing only.
RetrieveData(viewName string) ([]*Row, error)
}
var _ Meter = (*worker)(nil)
var defaultWorker *worker
var defaultReportingDuration = 10 * time.Second
@ -56,11 +119,17 @@ var defaultReportingDuration = 10 * time.Second
// Find returns a registered view associated with this name.
// If no registered view is found, nil is returned.
func Find(name string) (v *View) {
return defaultWorker.Find(name)
}
// Find returns a registered view associated with this name.
// If no registered view is found, nil is returned.
func (w *worker) Find(name string) (v *View) {
req := &getViewByNameReq{
name: name,
c: make(chan *getViewByNameResp),
}
defaultWorker.c <- req
w.c <- req
resp := <-req.c
return resp.v
}
@ -68,11 +137,17 @@ func Find(name string) (v *View) {
// Register begins collecting data for the given views.
// Once a view is registered, it reports data to the registered exporters.
func Register(views ...*View) error {
return defaultWorker.Register(views...)
}
// Register begins collecting data for the given views.
// Once a view is registered, it reports data to the registered exporters.
func (w *worker) Register(views ...*View) error {
req := &registerViewReq{
views: views,
err: make(chan error),
}
defaultWorker.c <- req
w.c <- req
return <-req.err
}
@ -81,6 +156,14 @@ func Register(views ...*View) error {
// It is not necessary to unregister from views you expect to collect for the
// duration of your program execution.
func Unregister(views ...*View) {
defaultWorker.Unregister(views...)
}
// Unregister the given views. Data will not longer be exported for these views
// after Unregister returns.
// It is not necessary to unregister from views you expect to collect for the
// duration of your program execution.
func (w *worker) Unregister(views ...*View) {
names := make([]string, len(views))
for i := range views {
names[i] = views[i].Name
@ -89,31 +172,42 @@ func Unregister(views ...*View) {
views: names,
done: make(chan struct{}),
}
defaultWorker.c <- req
w.c <- req
<-req.done
}
// RetrieveData gets a snapshot of the data collected for the the view registered
// with the given name. It is intended for testing only.
func RetrieveData(viewName string) ([]*Row, error) {
return defaultWorker.RetrieveData(viewName)
}
// RetrieveData gets a snapshot of the data collected for the the view registered
// with the given name. It is intended for testing only.
func (w *worker) RetrieveData(viewName string) ([]*Row, error) {
req := &retrieveDataReq{
now: time.Now(),
v: viewName,
c: make(chan *retrieveDataResp),
}
defaultWorker.c <- req
w.c <- req
resp := <-req.c
return resp.rows, resp.err
}
func record(tags *tag.Map, ms interface{}, attachments map[string]interface{}) {
defaultWorker.Record(tags, ms, attachments)
}
// Record records a set of measurements ms associated with the given tags and attachments.
func (w *worker) Record(tags *tag.Map, ms interface{}, attachments map[string]interface{}) {
req := &recordReq{
tm: tags,
ms: ms.([]stats.Measurement),
attachments: attachments,
t: time.Now(),
}
defaultWorker.c <- req
w.c <- req
}
// SetReportingPeriod sets the interval between reporting aggregated views in
@ -124,17 +218,31 @@ func record(tags *tag.Map, ms interface{}, attachments map[string]interface{}) {
// duration is. For example, the Stackdriver exporter recommends a value no
// lower than 1 minute. Consult each exporter per your needs.
func SetReportingPeriod(d time.Duration) {
defaultWorker.SetReportingPeriod(d)
}
// SetReportingPeriod sets the interval between reporting aggregated views in
// the program. If duration is less than or equal to zero, it enables the
// default behavior.
//
// Note: each exporter makes different promises about what the lowest supported
// duration is. For example, the Stackdriver exporter recommends a value no
// lower than 1 minute. Consult each exporter per your needs.
func (w *worker) SetReportingPeriod(d time.Duration) {
// TODO(acetechnologist): ensure that the duration d is more than a certain
// value. e.g. 1s
req := &setReportingPeriodReq{
d: d,
c: make(chan bool),
}
defaultWorker.c <- req
w.c <- req
<-req.c // don't return until the timer is set to the new duration.
}
func newWorker() *worker {
// NewMeter constructs a Meter instance. You should only need to use this if
// you need to separate out Measurement recordings and View aggregations within
// a single process.
func NewMeter() Meter {
return &worker{
measures: make(map[string]*measureRef),
views: make(map[string]*viewInternal),
@ -143,9 +251,23 @@ func newWorker() *worker {
c: make(chan command, 1024),
quit: make(chan bool),
done: make(chan bool),
exporters: make(map[Exporter]struct{}),
}
}
// SetResource associates all data collected by this Meter with the specified
// resource. This resource is reported when using metricexport.ReadAndExport;
// it is not provided when used with ExportView/RegisterExporter, because that
// interface does not provide a means for reporting the Resource.
func (w *worker) SetResource(r *resource.Resource) {
w.r = r
}
func (w *worker) Start() {
go w.start()
}
func (w *worker) start() {
prodMgr := metricproducer.GlobalManager()
prodMgr.AddProducer(w)
@ -155,7 +277,7 @@ func (w *worker) start() {
case cmd := <-w.c:
cmd.handleCommand(w)
case <-w.timer.C:
w.reportUsage(time.Now())
w.reportUsage()
case <-w.quit:
w.timer.Stop()
close(w.c)
@ -165,7 +287,7 @@ func (w *worker) start() {
}
}
func (w *worker) stop() {
func (w *worker) Stop() {
prodMgr := metricproducer.GlobalManager()
prodMgr.DeleteProducer(w)
@ -202,44 +324,45 @@ func (w *worker) tryRegisterView(v *View) (*viewInternal, error) {
return x, nil
}
w.views[vi.view.Name] = vi
w.startTimes[vi] = time.Now()
ref := w.getMeasureRef(vi.view.Measure.Name())
ref.views[vi] = struct{}{}
return vi, nil
}
func (w *worker) unregisterView(viewName string) {
func (w *worker) unregisterView(v *viewInternal) {
w.mu.Lock()
defer w.mu.Unlock()
delete(w.views, viewName)
delete(w.views, v.view.Name)
delete(w.startTimes, v)
if measure := w.measures[v.view.Measure.Name()]; measure != nil {
delete(measure.views, v)
}
}
func (w *worker) reportView(v *viewInternal, now time.Time) {
func (w *worker) reportView(v *viewInternal) {
if !v.isSubscribed() {
return
}
rows := v.collectedRows()
_, ok := w.startTimes[v]
if !ok {
w.startTimes[v] = now
}
viewData := &Data{
View: v.view,
Start: w.startTimes[v],
End: time.Now(),
Rows: rows,
}
exportersMu.Lock()
for e := range exporters {
w.exportersMu.Lock()
defer w.exportersMu.Unlock()
for e := range w.exporters {
e.ExportView(viewData)
}
exportersMu.Unlock()
}
func (w *worker) reportUsage(now time.Time) {
func (w *worker) reportUsage() {
w.mu.Lock()
defer w.mu.Unlock()
for _, v := range w.views {
w.reportView(v, now)
w.reportView(v)
}
}
@ -248,11 +371,6 @@ func (w *worker) toMetric(v *viewInternal, now time.Time) *metricdata.Metric {
return nil
}
_, ok := w.startTimes[v]
if !ok {
w.startTimes[v] = now
}
var startTime time.Time
if v.metricDescriptor.Type == metricdata.TypeGaugeInt64 ||
v.metricDescriptor.Type == metricdata.TypeGaugeFloat64 {
@ -261,7 +379,7 @@ func (w *worker) toMetric(v *viewInternal, now time.Time) *metricdata.Metric {
startTime = w.startTimes[v]
}
return viewToMetric(v, now, startTime)
return viewToMetric(v, w.r, now, startTime)
}
// Read reads all view data and returns them as metrics.
@ -279,3 +397,17 @@ func (w *worker) Read() []*metricdata.Metric {
}
return metrics
}
func (w *worker) RegisterExporter(e Exporter) {
w.exportersMu.Lock()
defer w.exportersMu.Unlock()
w.exporters[e] = struct{}{}
}
func (w *worker) UnregisterExporter(e Exporter) {
w.exportersMu.Lock()
defer w.exportersMu.Unlock()
delete(w.exporters, e)
}

View File

@ -95,7 +95,7 @@ func (cmd *unregisterFromViewReq) handleCommand(w *worker) {
}
// Report pending data for this view before removing it.
w.reportView(vi, time.Now())
w.reportView(vi)
vi.unsubscribe()
if !vi.isSubscribed() {
@ -103,7 +103,7 @@ func (cmd *unregisterFromViewReq) handleCommand(w *worker) {
// The collected data can be cleared.
vi.clearRows()
}
w.unregisterView(name)
w.unregisterView(vi)
}
cmd.done <- struct{}{}
}
@ -163,7 +163,7 @@ func (cmd *recordReq) handleCommand(w *worker) {
}
ref := w.getMeasureRef(m.Measure().Name())
for v := range ref.views {
v.addSample(cmd.tm, m.Value(), cmd.attachments, time.Now())
v.addSample(cmd.tm, m.Value(), cmd.attachments, cmd.t)
}
}
}

View File

@ -44,7 +44,7 @@ func (lm lruMap) len() int {
}
func (lm lruMap) keys() []interface{} {
keys := []interface{}{}
keys := make([]interface{}, len(lm.cacheKeys))
for k := range lm.cacheKeys {
keys = append(keys, k)
}

View File

@ -345,7 +345,7 @@ func (s *Span) SetStatus(status Status) {
}
func (s *Span) interfaceArrayToLinksArray() []Link {
linksArr := make([]Link, 0)
linksArr := make([]Link, 0, len(s.links.queue))
for _, value := range s.links.queue {
linksArr = append(linksArr, value.(Link))
}
@ -353,7 +353,7 @@ func (s *Span) interfaceArrayToLinksArray() []Link {
}
func (s *Span) interfaceArrayToMessageEventArray() []MessageEvent {
messageEventArr := make([]MessageEvent, 0)
messageEventArr := make([]MessageEvent, 0, len(s.messageEvents.queue))
for _, value := range s.messageEvents.queue {
messageEventArr = append(messageEventArr, value.(MessageEvent))
}
@ -361,7 +361,7 @@ func (s *Span) interfaceArrayToMessageEventArray() []MessageEvent {
}
func (s *Span) interfaceArrayToAnnotationArray() []Annotation {
annotationArr := make([]Annotation, 0)
annotationArr := make([]Annotation, 0, len(s.annotations.queue))
for _, value := range s.annotations.queue {
annotationArr = append(annotationArr, value.(Annotation))
}
@ -369,7 +369,7 @@ func (s *Span) interfaceArrayToAnnotationArray() []Annotation {
}
func (s *Span) lruAttributesToAttributeMap() map[string]interface{} {
attributes := make(map[string]interface{})
attributes := make(map[string]interface{}, s.lruAttributes.len())
for _, key := range s.lruAttributes.keys() {
value, ok := s.lruAttributes.get(key)
if ok {
@ -420,7 +420,7 @@ func (s *Span) lazyPrintfInternal(attributes []Attribute, format string, a ...in
var m map[string]interface{}
s.mu.Lock()
if len(attributes) != 0 {
m = make(map[string]interface{})
m = make(map[string]interface{}, len(attributes))
copyAttributes(m, attributes)
}
s.annotations.add(Annotation{
@ -436,7 +436,7 @@ func (s *Span) printStringInternal(attributes []Attribute, str string) {
var a map[string]interface{}
s.mu.Lock()
if len(attributes) != 0 {
a = make(map[string]interface{})
a = make(map[string]interface{}, len(attributes))
copyAttributes(a, attributes)
}
s.annotations.add(Annotation{

495
vendor/golang.org/x/net/http2/h2c/h2c.go generated vendored Normal file
View File

@ -0,0 +1,495 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package h2c implements the unencrypted "h2c" form of HTTP/2.
//
// The h2c protocol is the non-TLS version of HTTP/2 which is not available from
// net/http or golang.org/x/net/http2.
package h2c
import (
"bufio"
"bytes"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"io"
"log"
"net"
"net/http"
"net/textproto"
"os"
"strings"
"golang.org/x/net/http/httpguts"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
)
var (
http2VerboseLogs bool
)
func init() {
e := os.Getenv("GODEBUG")
if strings.Contains(e, "http2debug=1") || strings.Contains(e, "http2debug=2") {
http2VerboseLogs = true
}
}
// h2cHandler is a Handler which implements h2c by hijacking the HTTP/1 traffic
// that should be h2c traffic. There are two ways to begin a h2c connection
// (RFC 7540 Section 3.2 and 3.4): (1) Starting with Prior Knowledge - this
// works by starting an h2c connection with a string of bytes that is valid
// HTTP/1, but unlikely to occur in practice and (2) Upgrading from HTTP/1 to
// h2c - this works by using the HTTP/1 Upgrade header to request an upgrade to
// h2c. When either of those situations occur we hijack the HTTP/1 connection,
// convert it to a HTTP/2 connection and pass the net.Conn to http2.ServeConn.
type h2cHandler struct {
Handler http.Handler
s *http2.Server
}
// NewHandler returns an http.Handler that wraps h, intercepting any h2c
// traffic. If a request is an h2c connection, it's hijacked and redirected to
// s.ServeConn. Otherwise the returned Handler just forwards requests to h. This
// works because h2c is designed to be parseable as valid HTTP/1, but ignored by
// any HTTP server that does not handle h2c. Therefore we leverage the HTTP/1
// compatible parts of the Go http library to parse and recognize h2c requests.
// Once a request is recognized as h2c, we hijack the connection and convert it
// to an HTTP/2 connection which is understandable to s.ServeConn. (s.ServeConn
// understands HTTP/2 except for the h2c part of it.)
func NewHandler(h http.Handler, s *http2.Server) http.Handler {
return &h2cHandler{
Handler: h,
s: s,
}
}
// ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler.
func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Handle h2c with prior knowledge (RFC 7540 Section 3.4)
if r.Method == "PRI" && len(r.Header) == 0 && r.URL.Path == "*" && r.Proto == "HTTP/2.0" {
if http2VerboseLogs {
log.Print("h2c: attempting h2c with prior knowledge.")
}
conn, err := initH2CWithPriorKnowledge(w)
if err != nil {
if http2VerboseLogs {
log.Printf("h2c: error h2c with prior knowledge: %v", err)
}
return
}
defer conn.Close()
s.s.ServeConn(conn, &http2.ServeConnOpts{Handler: s.Handler})
return
}
// Handle Upgrade to h2c (RFC 7540 Section 3.2)
if conn, err := h2cUpgrade(w, r); err == nil {
defer conn.Close()
s.s.ServeConn(conn, &http2.ServeConnOpts{Handler: s.Handler})
return
}
s.Handler.ServeHTTP(w, r)
return
}
// initH2CWithPriorKnowledge implements creating a h2c connection with prior
// knowledge (Section 3.4) and creates a net.Conn suitable for http2.ServeConn.
// All we have to do is look for the client preface that is suppose to be part
// of the body, and reforward the client preface on the net.Conn this function
// creates.
func initH2CWithPriorKnowledge(w http.ResponseWriter) (net.Conn, error) {
hijacker, ok := w.(http.Hijacker)
if !ok {
panic("Hijack not supported.")
}
conn, rw, err := hijacker.Hijack()
if err != nil {
panic(fmt.Sprintf("Hijack failed: %v", err))
}
const expectedBody = "SM\r\n\r\n"
buf := make([]byte, len(expectedBody))
n, err := io.ReadFull(rw, buf)
if err != nil {
return nil, fmt.Errorf("could not read from the buffer: %s", err)
}
if string(buf[:n]) == expectedBody {
c := &rwConn{
Conn: conn,
Reader: io.MultiReader(strings.NewReader(http2.ClientPreface), rw),
BufWriter: rw.Writer,
}
return c, nil
}
conn.Close()
if http2VerboseLogs {
log.Printf(
"h2c: missing the request body portion of the client preface. Wanted: %v Got: %v",
[]byte(expectedBody),
buf[0:n],
)
}
return nil, errors.New("invalid client preface")
}
// drainClientPreface reads a single instance of the HTTP/2 client preface from
// the supplied reader.
func drainClientPreface(r io.Reader) error {
var buf bytes.Buffer
prefaceLen := int64(len(http2.ClientPreface))
n, err := io.CopyN(&buf, r, prefaceLen)
if err != nil {
return err
}
if n != prefaceLen || buf.String() != http2.ClientPreface {
return fmt.Errorf("Client never sent: %s", http2.ClientPreface)
}
return nil
}
// h2cUpgrade establishes a h2c connection using the HTTP/1 upgrade (Section 3.2).
func h2cUpgrade(w http.ResponseWriter, r *http.Request) (net.Conn, error) {
if !isH2CUpgrade(r.Header) {
return nil, errors.New("non-conforming h2c headers")
}
// Initial bytes we put into conn to fool http2 server
initBytes, _, err := convertH1ReqToH2(r)
if err != nil {
return nil, err
}
hijacker, ok := w.(http.Hijacker)
if !ok {
return nil, errors.New("hijack not supported.")
}
conn, rw, err := hijacker.Hijack()
if err != nil {
return nil, fmt.Errorf("hijack failed: %v", err)
}
rw.Write([]byte("HTTP/1.1 101 Switching Protocols\r\n" +
"Connection: Upgrade\r\n" +
"Upgrade: h2c\r\n\r\n"))
rw.Flush()
// A conforming client will now send an H2 client preface which need to drain
// since we already sent this.
if err := drainClientPreface(rw); err != nil {
return nil, err
}
c := &rwConn{
Conn: conn,
Reader: io.MultiReader(initBytes, rw),
BufWriter: newSettingsAckSwallowWriter(rw.Writer),
}
return c, nil
}
// convert the data contained in the HTTP/1 upgrade request into the HTTP/2
// version in byte form.
func convertH1ReqToH2(r *http.Request) (*bytes.Buffer, []http2.Setting, error) {
h2Bytes := bytes.NewBuffer([]byte((http2.ClientPreface)))
framer := http2.NewFramer(h2Bytes, nil)
settings, err := getH2Settings(r.Header)
if err != nil {
return nil, nil, err
}
if err := framer.WriteSettings(settings...); err != nil {
return nil, nil, err
}
headerBytes, err := getH2HeaderBytes(r, getMaxHeaderTableSize(settings))
if err != nil {
return nil, nil, err
}
maxFrameSize := int(getMaxFrameSize(settings))
needOneHeader := len(headerBytes) < maxFrameSize
err = framer.WriteHeaders(http2.HeadersFrameParam{
StreamID: 1,
BlockFragment: headerBytes,
EndHeaders: needOneHeader,
})
if err != nil {
return nil, nil, err
}
for i := maxFrameSize; i < len(headerBytes); i += maxFrameSize {
if len(headerBytes)-i > maxFrameSize {
if err := framer.WriteContinuation(1,
false, // endHeaders
headerBytes[i:maxFrameSize]); err != nil {
return nil, nil, err
}
} else {
if err := framer.WriteContinuation(1,
true, // endHeaders
headerBytes[i:]); err != nil {
return nil, nil, err
}
}
}
return h2Bytes, settings, nil
}
// getMaxFrameSize returns the SETTINGS_MAX_FRAME_SIZE. If not present default
// value is 16384 as specified by RFC 7540 Section 6.5.2.
func getMaxFrameSize(settings []http2.Setting) uint32 {
for _, setting := range settings {
if setting.ID == http2.SettingMaxFrameSize {
return setting.Val
}
}
return 16384
}
// getMaxHeaderTableSize returns the SETTINGS_HEADER_TABLE_SIZE. If not present
// default value is 4096 as specified by RFC 7540 Section 6.5.2.
func getMaxHeaderTableSize(settings []http2.Setting) uint32 {
for _, setting := range settings {
if setting.ID == http2.SettingHeaderTableSize {
return setting.Val
}
}
return 4096
}
// bufWriter is a Writer interface that also has a Flush method.
type bufWriter interface {
io.Writer
Flush() error
}
// rwConn implements net.Conn but overrides Read and Write so that reads and
// writes are forwarded to the provided io.Reader and bufWriter.
type rwConn struct {
net.Conn
io.Reader
BufWriter bufWriter
}
// Read forwards reads to the underlying Reader.
func (c *rwConn) Read(p []byte) (int, error) {
return c.Reader.Read(p)
}
// Write forwards writes to the underlying bufWriter and immediately flushes.
func (c *rwConn) Write(p []byte) (int, error) {
n, err := c.BufWriter.Write(p)
if err := c.BufWriter.Flush(); err != nil {
return 0, err
}
return n, err
}
// settingsAckSwallowWriter is a writer that normally forwards bytes to its
// underlying Writer, but swallows the first SettingsAck frame that it sees.
type settingsAckSwallowWriter struct {
Writer *bufio.Writer
buf []byte
didSwallow bool
}
// newSettingsAckSwallowWriter returns a new settingsAckSwallowWriter.
func newSettingsAckSwallowWriter(w *bufio.Writer) *settingsAckSwallowWriter {
return &settingsAckSwallowWriter{
Writer: w,
buf: make([]byte, 0),
didSwallow: false,
}
}
// Write implements io.Writer interface. Normally forwards bytes to w.Writer,
// except for the first Settings ACK frame that it sees.
func (w *settingsAckSwallowWriter) Write(p []byte) (int, error) {
if !w.didSwallow {
w.buf = append(w.buf, p...)
// Process all the frames we have collected into w.buf
for {
// Append until we get full frame header which is 9 bytes
if len(w.buf) < 9 {
break
}
// Check if we have collected a whole frame.
fh, err := http2.ReadFrameHeader(bytes.NewBuffer(w.buf))
if err != nil {
// Corrupted frame, fail current Write
return 0, err
}
fSize := fh.Length + 9
if uint32(len(w.buf)) < fSize {
// Have not collected whole frame. Stop processing buf, and withold on
// forward bytes to w.Writer until we get the full frame.
break
}
// We have now collected a whole frame.
if fh.Type == http2.FrameSettings && fh.Flags.Has(http2.FlagSettingsAck) {
// If Settings ACK frame, do not forward to underlying writer, remove
// bytes from w.buf, and record that we have swallowed Settings Ack
// frame.
w.didSwallow = true
w.buf = w.buf[fSize:]
continue
}
// Not settings ack frame. Forward bytes to w.Writer.
if _, err := w.Writer.Write(w.buf[:fSize]); err != nil {
// Couldn't forward bytes. Fail current Write.
return 0, err
}
w.buf = w.buf[fSize:]
}
return len(p), nil
}
return w.Writer.Write(p)
}
// Flush calls w.Writer.Flush.
func (w *settingsAckSwallowWriter) Flush() error {
return w.Writer.Flush()
}
// isH2CUpgrade returns true if the header properly request an upgrade to h2c
// as specified by Section 3.2.
func isH2CUpgrade(h http.Header) bool {
return httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Upgrade")], "h2c") &&
httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Connection")], "HTTP2-Settings")
}
// getH2Settings returns the []http2.Setting that are encoded in the
// HTTP2-Settings header.
func getH2Settings(h http.Header) ([]http2.Setting, error) {
vals, ok := h[textproto.CanonicalMIMEHeaderKey("HTTP2-Settings")]
if !ok {
return nil, errors.New("missing HTTP2-Settings header")
}
if len(vals) != 1 {
return nil, fmt.Errorf("expected 1 HTTP2-Settings. Got: %v", vals)
}
settings, err := decodeSettings(vals[0])
if err != nil {
return nil, fmt.Errorf("Invalid HTTP2-Settings: %q", vals[0])
}
return settings, nil
}
// decodeSettings decodes the base64url header value of the HTTP2-Settings
// header. RFC 7540 Section 3.2.1.
func decodeSettings(headerVal string) ([]http2.Setting, error) {
b, err := base64.RawURLEncoding.DecodeString(headerVal)
if err != nil {
return nil, err
}
if len(b)%6 != 0 {
return nil, err
}
settings := make([]http2.Setting, 0)
for i := 0; i < len(b)/6; i++ {
settings = append(settings, http2.Setting{
ID: http2.SettingID(binary.BigEndian.Uint16(b[i*6 : i*6+2])),
Val: binary.BigEndian.Uint32(b[i*6+2 : i*6+6]),
})
}
return settings, nil
}
// getH2HeaderBytes return the headers in r a []bytes encoded by HPACK.
func getH2HeaderBytes(r *http.Request, maxHeaderTableSize uint32) ([]byte, error) {
headerBytes := bytes.NewBuffer(nil)
hpackEnc := hpack.NewEncoder(headerBytes)
hpackEnc.SetMaxDynamicTableSize(maxHeaderTableSize)
// Section 8.1.2.3
err := hpackEnc.WriteField(hpack.HeaderField{
Name: ":method",
Value: r.Method,
})
if err != nil {
return nil, err
}
err = hpackEnc.WriteField(hpack.HeaderField{
Name: ":scheme",
Value: "http",
})
if err != nil {
return nil, err
}
err = hpackEnc.WriteField(hpack.HeaderField{
Name: ":authority",
Value: r.Host,
})
if err != nil {
return nil, err
}
path := r.URL.Path
if r.URL.RawQuery != "" {
path = strings.Join([]string{path, r.URL.RawQuery}, "?")
}
err = hpackEnc.WriteField(hpack.HeaderField{
Name: ":path",
Value: path,
})
if err != nil {
return nil, err
}
// TODO Implement Section 8.3
for header, values := range r.Header {
// Skip non h2 headers
if isNonH2Header(header) {
continue
}
for _, v := range values {
err := hpackEnc.WriteField(hpack.HeaderField{
Name: strings.ToLower(header),
Value: v,
})
if err != nil {
return nil, err
}
}
}
return headerBytes.Bytes(), nil
}
// Connection specific headers listed in RFC 7540 Section 8.1.2.2 that are not
// suppose to be transferred to HTTP/2. The Http2-Settings header is skipped
// since already use to create the HTTP/2 SETTINGS frame.
var nonH2Headers = []string{
"Connection",
"Keep-Alive",
"Proxy-Connection",
"Transfer-Encoding",
"Upgrade",
"Http2-Settings",
}
// isNonH2Header returns true if header should not be transferred to HTTP/2.
func isNonH2Header(header string) bool {
for _, nonH2h := range nonH2Headers {
if header == nonH2h {
return true
}
}
return false
}

View File

@ -47,8 +47,8 @@ func (a ByPath) Len() int { return len(a) }
func (a ByPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByPath) Less(i, j int) bool { return a[i].Path < a[j].Path }
func NewPatch(operation, path string, value interface{}) Operation {
return Operation{Operation: operation, Path: path, Value: value}
func NewOperation(op, path string, value interface{}) Operation {
return Operation{Operation: op, Path: path, Value: value}
}
// CreatePatch creates a patch as specified in http://jsonpatch.com/
@ -162,7 +162,7 @@ func diff(a, b map[string]interface{}, path string, patch []Operation) ([]Operat
av, ok := a[key]
// value was added
if !ok {
patch = append(patch, NewPatch("add", p, bv))
patch = append(patch, NewOperation("add", p, bv))
continue
}
// Types are the same, compare values
@ -178,7 +178,7 @@ func diff(a, b map[string]interface{}, path string, patch []Operation) ([]Operat
if !found {
p := makePath(path, key)
patch = append(patch, NewPatch("remove", p, nil))
patch = append(patch, NewOperation("remove", p, nil))
}
}
return patch, nil
@ -192,10 +192,10 @@ func handleValues(av, bv interface{}, p string, patch []Operation) ([]Operation,
// do nothing
return patch, nil
} else if at == nil && bt != nil {
return append(patch, NewPatch("add", p, bv)), nil
return append(patch, NewOperation("add", p, bv)), nil
} else if at != bt {
// If types have changed, replace completely (preserves null in destination)
return append(patch, NewPatch("replace", p, bv)), nil
return append(patch, NewOperation("replace", p, bv)), nil
}
}
@ -209,7 +209,7 @@ func handleValues(av, bv interface{}, p string, patch []Operation) ([]Operation,
}
case string, float64, bool:
if !matchesValue(av, bv) {
patch = append(patch, NewPatch("replace", p, bv))
patch = append(patch, NewOperation("replace", p, bv))
}
case []interface{}:
bt := bv.([]interface{})
@ -218,10 +218,10 @@ func handleValues(av, bv interface{}, p string, patch []Operation) ([]Operation,
} else {
n := min(len(at), len(bt))
for i := len(at) - 1; i >= n; i-- {
patch = append(patch, NewPatch("remove", makePath(p, i), nil))
patch = append(patch, NewOperation("remove", makePath(p, i), nil))
}
for i := n; i < len(bt); i++ {
patch = append(patch, NewPatch("add", makePath(p, i), bt[i]))
patch = append(patch, NewOperation("add", makePath(p, i), bt[i]))
}
for i := 0; i < n; i++ {
var err error
@ -313,16 +313,16 @@ func min(x int, y int) int {
func backtrace(s, t []interface{}, p string, i int, j int, matrix [][]int) []Operation {
if i > 0 && matrix[i-1][j]+1 == matrix[i][j] {
op := NewPatch("remove", makePath(p, i-1), nil)
op := NewOperation("remove", makePath(p, i-1), nil)
return append([]Operation{op}, backtrace(s, t, p, i-1, j, matrix)...)
}
if j > 0 && matrix[i][j-1]+1 == matrix[i][j] {
op := NewPatch("add", makePath(p, i), t[j-1])
op := NewOperation("add", makePath(p, i), t[j-1])
return append([]Operation{op}, backtrace(s, t, p, i, j-1, matrix)...)
}
if i > 0 && j > 0 && matrix[i-1][j-1]+1 == matrix[i][j] {
if isBasicType(s[0]) {
op := NewPatch("replace", makePath(p, i-1), t[j-1])
op := NewOperation("replace", makePath(p, i-1), t[j-1])
return append([]Operation{op}, backtrace(s, t, p, i-1, j-1, matrix)...)
}

27
vendor/k8s.io/apimachinery/pkg/util/uuid/uuid.go generated vendored Normal file
View File

@ -0,0 +1,27 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package uuid
import (
"github.com/google/uuid"
"k8s.io/apimachinery/pkg/types"
)
func NewUUID() types.UID {
return types.UID(uuid.New().String())
}

View File

@ -0,0 +1,69 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package leaderelection
import (
"net/http"
"sync"
"time"
)
// HealthzAdaptor associates the /healthz endpoint with the LeaderElection object.
// It helps deal with the /healthz endpoint being set up prior to the LeaderElection.
// This contains the code needed to act as an adaptor between the leader
// election code the health check code. It allows us to provide health
// status about the leader election. Most specifically about if the leader
// has failed to renew without exiting the process. In that case we should
// report not healthy and rely on the kubelet to take down the process.
type HealthzAdaptor struct {
pointerLock sync.Mutex
le *LeaderElector
timeout time.Duration
}
// Name returns the name of the health check we are implementing.
func (l *HealthzAdaptor) Name() string {
return "leaderElection"
}
// Check is called by the healthz endpoint handler.
// It fails (returns an error) if we own the lease but had not been able to renew it.
func (l *HealthzAdaptor) Check(req *http.Request) error {
l.pointerLock.Lock()
defer l.pointerLock.Unlock()
if l.le == nil {
return nil
}
return l.le.Check(l.timeout)
}
// SetLeaderElection ties a leader election object to a HealthzAdaptor
func (l *HealthzAdaptor) SetLeaderElection(le *LeaderElector) {
l.pointerLock.Lock()
defer l.pointerLock.Unlock()
l.le = le
}
// NewLeaderHealthzAdaptor creates a basic healthz adaptor to monitor a leader election.
// timeout determines the time beyond the lease expiry to be allowed for timeout.
// checks within the timeout period after the lease expires will still return healthy.
func NewLeaderHealthzAdaptor(timeout time.Duration) *HealthzAdaptor {
result := &HealthzAdaptor{
timeout: timeout,
}
return result
}

View File

@ -0,0 +1,400 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package leaderelection implements leader election of a set of endpoints.
// It uses an annotation in the endpoints object to store the record of the
// election state. This implementation does not guarantee that only one
// client is acting as a leader (a.k.a. fencing).
//
// A client only acts on timestamps captured locally to infer the state of the
// leader election. The client does not consider timestamps in the leader
// election record to be accurate because these timestamps may not have been
// produced by a local clock. The implemention does not depend on their
// accuracy and only uses their change to indicate that another client has
// renewed the leader lease. Thus the implementation is tolerant to arbitrary
// clock skew, but is not tolerant to arbitrary clock skew rate.
//
// However the level of tolerance to skew rate can be configured by setting
// RenewDeadline and LeaseDuration appropriately. The tolerance expressed as a
// maximum tolerated ratio of time passed on the fastest node to time passed on
// the slowest node can be approximately achieved with a configuration that sets
// the same ratio of LeaseDuration to RenewDeadline. For example if a user wanted
// to tolerate some nodes progressing forward in time twice as fast as other nodes,
// the user could set LeaseDuration to 60 seconds and RenewDeadline to 30 seconds.
//
// While not required, some method of clock synchronization between nodes in the
// cluster is highly recommended. It's important to keep in mind when configuring
// this client that the tolerance to skew rate varies inversely to master
// availability.
//
// Larger clusters often have a more lenient SLA for API latency. This should be
// taken into account when configuring the client. The rate of leader transitions
// should be monitored and RetryPeriod and LeaseDuration should be increased
// until the rate is stable and acceptably low. It's important to keep in mind
// when configuring this client that the tolerance to API latency varies inversely
// to master availability.
//
// DISCLAIMER: this is an alpha API. This library will likely change significantly
// or even be removed entirely in subsequent releases. Depend on this API at
// your own risk.
package leaderelection
import (
"bytes"
"context"
"fmt"
"time"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/clock"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
rl "k8s.io/client-go/tools/leaderelection/resourcelock"
"k8s.io/klog"
)
const (
JitterFactor = 1.2
)
// NewLeaderElector creates a LeaderElector from a LeaderElectionConfig
func NewLeaderElector(lec LeaderElectionConfig) (*LeaderElector, error) {
if lec.LeaseDuration <= lec.RenewDeadline {
return nil, fmt.Errorf("leaseDuration must be greater than renewDeadline")
}
if lec.RenewDeadline <= time.Duration(JitterFactor*float64(lec.RetryPeriod)) {
return nil, fmt.Errorf("renewDeadline must be greater than retryPeriod*JitterFactor")
}
if lec.LeaseDuration < 1 {
return nil, fmt.Errorf("leaseDuration must be greater than zero")
}
if lec.RenewDeadline < 1 {
return nil, fmt.Errorf("renewDeadline must be greater than zero")
}
if lec.RetryPeriod < 1 {
return nil, fmt.Errorf("retryPeriod must be greater than zero")
}
if lec.Callbacks.OnStartedLeading == nil {
return nil, fmt.Errorf("OnStartedLeading callback must not be nil")
}
if lec.Callbacks.OnStoppedLeading == nil {
return nil, fmt.Errorf("OnStoppedLeading callback must not be nil")
}
if lec.Lock == nil {
return nil, fmt.Errorf("Lock must not be nil.")
}
le := LeaderElector{
config: lec,
clock: clock.RealClock{},
metrics: globalMetricsFactory.newLeaderMetrics(),
}
le.metrics.leaderOff(le.config.Name)
return &le, nil
}
type LeaderElectionConfig struct {
// Lock is the resource that will be used for locking
Lock rl.Interface
// LeaseDuration is the duration that non-leader candidates will
// wait to force acquire leadership. This is measured against time of
// last observed ack.
//
// A client needs to wait a full LeaseDuration without observing a change to
// the record before it can attempt to take over. When all clients are
// shutdown and a new set of clients are started with different names against
// the same leader record, they must wait the full LeaseDuration before
// attempting to acquire the lease. Thus LeaseDuration should be as short as
// possible (within your tolerance for clock skew rate) to avoid a possible
// long waits in the scenario.
//
// Core clients default this value to 15 seconds.
LeaseDuration time.Duration
// RenewDeadline is the duration that the acting master will retry
// refreshing leadership before giving up.
//
// Core clients default this value to 10 seconds.
RenewDeadline time.Duration
// RetryPeriod is the duration the LeaderElector clients should wait
// between tries of actions.
//
// Core clients default this value to 2 seconds.
RetryPeriod time.Duration
// Callbacks are callbacks that are triggered during certain lifecycle
// events of the LeaderElector
Callbacks LeaderCallbacks
// WatchDog is the associated health checker
// WatchDog may be null if its not needed/configured.
WatchDog *HealthzAdaptor
// ReleaseOnCancel should be set true if the lock should be released
// when the run context is cancelled. If you set this to true, you must
// ensure all code guarded by this lease has successfully completed
// prior to cancelling the context, or you may have two processes
// simultaneously acting on the critical path.
ReleaseOnCancel bool
// Name is the name of the resource lock for debugging
Name string
}
// LeaderCallbacks are callbacks that are triggered during certain
// lifecycle events of the LeaderElector. These are invoked asynchronously.
//
// possible future callbacks:
// * OnChallenge()
type LeaderCallbacks struct {
// OnStartedLeading is called when a LeaderElector client starts leading
OnStartedLeading func(context.Context)
// OnStoppedLeading is called when a LeaderElector client stops leading
OnStoppedLeading func()
// OnNewLeader is called when the client observes a leader that is
// not the previously observed leader. This includes the first observed
// leader when the client starts.
OnNewLeader func(identity string)
}
// LeaderElector is a leader election client.
type LeaderElector struct {
config LeaderElectionConfig
// internal bookkeeping
observedRecord rl.LeaderElectionRecord
observedRawRecord []byte
observedTime time.Time
// used to implement OnNewLeader(), may lag slightly from the
// value observedRecord.HolderIdentity if the transition has
// not yet been reported.
reportedLeader string
// clock is wrapper around time to allow for less flaky testing
clock clock.Clock
metrics leaderMetricsAdapter
// name is the name of the resource lock for debugging
name string
}
// Run starts the leader election loop
func (le *LeaderElector) Run(ctx context.Context) {
defer func() {
runtime.HandleCrash()
le.config.Callbacks.OnStoppedLeading()
}()
if !le.acquire(ctx) {
return // ctx signalled done
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
go le.config.Callbacks.OnStartedLeading(ctx)
le.renew(ctx)
}
// RunOrDie starts a client with the provided config or panics if the config
// fails to validate.
func RunOrDie(ctx context.Context, lec LeaderElectionConfig) {
le, err := NewLeaderElector(lec)
if err != nil {
panic(err)
}
if lec.WatchDog != nil {
lec.WatchDog.SetLeaderElection(le)
}
le.Run(ctx)
}
// GetLeader returns the identity of the last observed leader or returns the empty string if
// no leader has yet been observed.
func (le *LeaderElector) GetLeader() string {
return le.observedRecord.HolderIdentity
}
// IsLeader returns true if the last observed leader was this client else returns false.
func (le *LeaderElector) IsLeader() bool {
return le.observedRecord.HolderIdentity == le.config.Lock.Identity()
}
// acquire loops calling tryAcquireOrRenew and returns true immediately when tryAcquireOrRenew succeeds.
// Returns false if ctx signals done.
func (le *LeaderElector) acquire(ctx context.Context) bool {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
succeeded := false
desc := le.config.Lock.Describe()
klog.Infof("attempting to acquire leader lease %v...", desc)
wait.JitterUntil(func() {
succeeded = le.tryAcquireOrRenew()
le.maybeReportTransition()
if !succeeded {
klog.V(4).Infof("failed to acquire lease %v", desc)
return
}
le.config.Lock.RecordEvent("became leader")
le.metrics.leaderOn(le.config.Name)
klog.Infof("successfully acquired lease %v", desc)
cancel()
}, le.config.RetryPeriod, JitterFactor, true, ctx.Done())
return succeeded
}
// renew loops calling tryAcquireOrRenew and returns immediately when tryAcquireOrRenew fails or ctx signals done.
func (le *LeaderElector) renew(ctx context.Context) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
wait.Until(func() {
timeoutCtx, timeoutCancel := context.WithTimeout(ctx, le.config.RenewDeadline)
defer timeoutCancel()
err := wait.PollImmediateUntil(le.config.RetryPeriod, func() (bool, error) {
done := make(chan bool, 1)
go func() {
defer close(done)
done <- le.tryAcquireOrRenew()
}()
select {
case <-timeoutCtx.Done():
return false, fmt.Errorf("failed to tryAcquireOrRenew %s", timeoutCtx.Err())
case result := <-done:
return result, nil
}
}, timeoutCtx.Done())
le.maybeReportTransition()
desc := le.config.Lock.Describe()
if err == nil {
klog.V(5).Infof("successfully renewed lease %v", desc)
return
}
le.config.Lock.RecordEvent("stopped leading")
le.metrics.leaderOff(le.config.Name)
klog.Infof("failed to renew lease %v: %v", desc, err)
cancel()
}, le.config.RetryPeriod, ctx.Done())
// if we hold the lease, give it up
if le.config.ReleaseOnCancel {
le.release()
}
}
// release attempts to release the leader lease if we have acquired it.
func (le *LeaderElector) release() bool {
if !le.IsLeader() {
return true
}
leaderElectionRecord := rl.LeaderElectionRecord{
LeaderTransitions: le.observedRecord.LeaderTransitions,
}
if err := le.config.Lock.Update(leaderElectionRecord); err != nil {
klog.Errorf("Failed to release lock: %v", err)
return false
}
le.observedRecord = leaderElectionRecord
le.observedTime = le.clock.Now()
return true
}
// tryAcquireOrRenew tries to acquire a leader lease if it is not already acquired,
// else it tries to renew the lease if it has already been acquired. Returns true
// on success else returns false.
func (le *LeaderElector) tryAcquireOrRenew() bool {
now := metav1.Now()
leaderElectionRecord := rl.LeaderElectionRecord{
HolderIdentity: le.config.Lock.Identity(),
LeaseDurationSeconds: int(le.config.LeaseDuration / time.Second),
RenewTime: now,
AcquireTime: now,
}
// 1. obtain or create the ElectionRecord
oldLeaderElectionRecord, oldLeaderElectionRawRecord, err := le.config.Lock.Get()
if err != nil {
if !errors.IsNotFound(err) {
klog.Errorf("error retrieving resource lock %v: %v", le.config.Lock.Describe(), err)
return false
}
if err = le.config.Lock.Create(leaderElectionRecord); err != nil {
klog.Errorf("error initially creating leader election record: %v", err)
return false
}
le.observedRecord = leaderElectionRecord
le.observedTime = le.clock.Now()
return true
}
// 2. Record obtained, check the Identity & Time
if !bytes.Equal(le.observedRawRecord, oldLeaderElectionRawRecord) {
le.observedRecord = *oldLeaderElectionRecord
le.observedRawRecord = oldLeaderElectionRawRecord
le.observedTime = le.clock.Now()
}
if len(oldLeaderElectionRecord.HolderIdentity) > 0 &&
le.observedTime.Add(le.config.LeaseDuration).After(now.Time) &&
!le.IsLeader() {
klog.V(4).Infof("lock is held by %v and has not yet expired", oldLeaderElectionRecord.HolderIdentity)
return false
}
// 3. We're going to try to update. The leaderElectionRecord is set to it's default
// here. Let's correct it before updating.
if le.IsLeader() {
leaderElectionRecord.AcquireTime = oldLeaderElectionRecord.AcquireTime
leaderElectionRecord.LeaderTransitions = oldLeaderElectionRecord.LeaderTransitions
} else {
leaderElectionRecord.LeaderTransitions = oldLeaderElectionRecord.LeaderTransitions + 1
}
// update the lock itself
if err = le.config.Lock.Update(leaderElectionRecord); err != nil {
klog.Errorf("Failed to update lock: %v", err)
return false
}
le.observedRecord = leaderElectionRecord
le.observedTime = le.clock.Now()
return true
}
func (le *LeaderElector) maybeReportTransition() {
if le.observedRecord.HolderIdentity == le.reportedLeader {
return
}
le.reportedLeader = le.observedRecord.HolderIdentity
if le.config.Callbacks.OnNewLeader != nil {
go le.config.Callbacks.OnNewLeader(le.reportedLeader)
}
}
// Check will determine if the current lease is expired by more than timeout.
func (le *LeaderElector) Check(maxTolerableExpiredLease time.Duration) error {
if !le.IsLeader() {
// Currently not concerned with the case that we are hot standby
return nil
}
// If we are more than timeout seconds after the lease duration that is past the timeout
// on the lease renew. Time to start reporting ourselves as unhealthy. We should have
// died but conditions like deadlock can prevent this. (See #70819)
if le.clock.Since(le.observedTime) > le.config.LeaseDuration+maxTolerableExpiredLease {
return fmt.Errorf("failed election to renew leadership on lease %s", le.config.Name)
}
return nil
}

109
vendor/k8s.io/client-go/tools/leaderelection/metrics.go generated vendored Normal file
View File

@ -0,0 +1,109 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package leaderelection
import (
"sync"
)
// This file provides abstractions for setting the provider (e.g., prometheus)
// of metrics.
type leaderMetricsAdapter interface {
leaderOn(name string)
leaderOff(name string)
}
// GaugeMetric represents a single numerical value that can arbitrarily go up
// and down.
type SwitchMetric interface {
On(name string)
Off(name string)
}
type noopMetric struct{}
func (noopMetric) On(name string) {}
func (noopMetric) Off(name string) {}
// defaultLeaderMetrics expects the caller to lock before setting any metrics.
type defaultLeaderMetrics struct {
// leader's value indicates if the current process is the owner of name lease
leader SwitchMetric
}
func (m *defaultLeaderMetrics) leaderOn(name string) {
if m == nil {
return
}
m.leader.On(name)
}
func (m *defaultLeaderMetrics) leaderOff(name string) {
if m == nil {
return
}
m.leader.Off(name)
}
type noMetrics struct{}
func (noMetrics) leaderOn(name string) {}
func (noMetrics) leaderOff(name string) {}
// MetricsProvider generates various metrics used by the leader election.
type MetricsProvider interface {
NewLeaderMetric() SwitchMetric
}
type noopMetricsProvider struct{}
func (_ noopMetricsProvider) NewLeaderMetric() SwitchMetric {
return noopMetric{}
}
var globalMetricsFactory = leaderMetricsFactory{
metricsProvider: noopMetricsProvider{},
}
type leaderMetricsFactory struct {
metricsProvider MetricsProvider
onlyOnce sync.Once
}
func (f *leaderMetricsFactory) setProvider(mp MetricsProvider) {
f.onlyOnce.Do(func() {
f.metricsProvider = mp
})
}
func (f *leaderMetricsFactory) newLeaderMetrics() leaderMetricsAdapter {
mp := f.metricsProvider
if mp == (noopMetricsProvider{}) {
return noMetrics{}
}
return &defaultLeaderMetrics{
leader: mp.NewLeaderMetric(),
}
}
// SetProvider sets the metrics provider for all subsequently created work
// queues. Only the first call has an effect.
func SetProvider(metricsProvider MetricsProvider) {
globalMetricsFactory.setProvider(metricsProvider)
}

View File

@ -0,0 +1,113 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resourcelock
import (
"encoding/json"
"errors"
"fmt"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
)
// TODO: This is almost a exact replica of Endpoints lock.
// going forwards as we self host more and more components
// and use ConfigMaps as the means to pass that configuration
// data we will likely move to deprecate the Endpoints lock.
type ConfigMapLock struct {
// ConfigMapMeta should contain a Name and a Namespace of a
// ConfigMapMeta object that the LeaderElector will attempt to lead.
ConfigMapMeta metav1.ObjectMeta
Client corev1client.ConfigMapsGetter
LockConfig ResourceLockConfig
cm *v1.ConfigMap
}
// Get returns the election record from a ConfigMap Annotation
func (cml *ConfigMapLock) Get() (*LeaderElectionRecord, []byte, error) {
var record LeaderElectionRecord
var err error
cml.cm, err = cml.Client.ConfigMaps(cml.ConfigMapMeta.Namespace).Get(cml.ConfigMapMeta.Name, metav1.GetOptions{})
if err != nil {
return nil, nil, err
}
if cml.cm.Annotations == nil {
cml.cm.Annotations = make(map[string]string)
}
recordBytes, found := cml.cm.Annotations[LeaderElectionRecordAnnotationKey]
if found {
if err := json.Unmarshal([]byte(recordBytes), &record); err != nil {
return nil, nil, err
}
}
return &record, []byte(recordBytes), nil
}
// Create attempts to create a LeaderElectionRecord annotation
func (cml *ConfigMapLock) Create(ler LeaderElectionRecord) error {
recordBytes, err := json.Marshal(ler)
if err != nil {
return err
}
cml.cm, err = cml.Client.ConfigMaps(cml.ConfigMapMeta.Namespace).Create(&v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: cml.ConfigMapMeta.Name,
Namespace: cml.ConfigMapMeta.Namespace,
Annotations: map[string]string{
LeaderElectionRecordAnnotationKey: string(recordBytes),
},
},
})
return err
}
// Update will update an existing annotation on a given resource.
func (cml *ConfigMapLock) Update(ler LeaderElectionRecord) error {
if cml.cm == nil {
return errors.New("configmap not initialized, call get or create first")
}
recordBytes, err := json.Marshal(ler)
if err != nil {
return err
}
cml.cm.Annotations[LeaderElectionRecordAnnotationKey] = string(recordBytes)
cml.cm, err = cml.Client.ConfigMaps(cml.ConfigMapMeta.Namespace).Update(cml.cm)
return err
}
// RecordEvent in leader election while adding meta-data
func (cml *ConfigMapLock) RecordEvent(s string) {
if cml.LockConfig.EventRecorder == nil {
return
}
events := fmt.Sprintf("%v %v", cml.LockConfig.Identity, s)
cml.LockConfig.EventRecorder.Eventf(&v1.ConfigMap{ObjectMeta: cml.cm.ObjectMeta}, v1.EventTypeNormal, "LeaderElection", events)
}
// Describe is used to convert details on current resource lock
// into a string
func (cml *ConfigMapLock) Describe() string {
return fmt.Sprintf("%v/%v", cml.ConfigMapMeta.Namespace, cml.ConfigMapMeta.Name)
}
// Identity returns the Identity of the lock
func (cml *ConfigMapLock) Identity() string {
return cml.LockConfig.Identity
}

View File

@ -0,0 +1,111 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resourcelock
import (
"encoding/json"
"errors"
"fmt"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
)
type EndpointsLock struct {
// EndpointsMeta should contain a Name and a Namespace of an
// Endpoints object that the LeaderElector will attempt to lead.
EndpointsMeta metav1.ObjectMeta
Client corev1client.EndpointsGetter
LockConfig ResourceLockConfig
e *v1.Endpoints
}
// Get returns the election record from a Endpoints Annotation
func (el *EndpointsLock) Get() (*LeaderElectionRecord, []byte, error) {
var record LeaderElectionRecord
var err error
el.e, err = el.Client.Endpoints(el.EndpointsMeta.Namespace).Get(el.EndpointsMeta.Name, metav1.GetOptions{})
if err != nil {
return nil, nil, err
}
if el.e.Annotations == nil {
el.e.Annotations = make(map[string]string)
}
recordBytes, found := el.e.Annotations[LeaderElectionRecordAnnotationKey]
if found {
if err := json.Unmarshal([]byte(recordBytes), &record); err != nil {
return nil, nil, err
}
}
return &record, []byte(recordBytes), nil
}
// Create attempts to create a LeaderElectionRecord annotation
func (el *EndpointsLock) Create(ler LeaderElectionRecord) error {
recordBytes, err := json.Marshal(ler)
if err != nil {
return err
}
el.e, err = el.Client.Endpoints(el.EndpointsMeta.Namespace).Create(&v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: el.EndpointsMeta.Name,
Namespace: el.EndpointsMeta.Namespace,
Annotations: map[string]string{
LeaderElectionRecordAnnotationKey: string(recordBytes),
},
},
})
return err
}
// Update will update and existing annotation on a given resource.
func (el *EndpointsLock) Update(ler LeaderElectionRecord) error {
if el.e == nil {
return errors.New("endpoint not initialized, call get or create first")
}
recordBytes, err := json.Marshal(ler)
if err != nil {
return err
}
if el.e.Annotations == nil {
el.e.Annotations = make(map[string]string)
}
el.e.Annotations[LeaderElectionRecordAnnotationKey] = string(recordBytes)
el.e, err = el.Client.Endpoints(el.EndpointsMeta.Namespace).Update(el.e)
return err
}
// RecordEvent in leader election while adding meta-data
func (el *EndpointsLock) RecordEvent(s string) {
if el.LockConfig.EventRecorder == nil {
return
}
events := fmt.Sprintf("%v %v", el.LockConfig.Identity, s)
el.LockConfig.EventRecorder.Eventf(&v1.Endpoints{ObjectMeta: el.e.ObjectMeta}, v1.EventTypeNormal, "LeaderElection", events)
}
// Describe is used to convert details on current resource lock
// into a string
func (el *EndpointsLock) Describe() string {
return fmt.Sprintf("%v/%v", el.EndpointsMeta.Namespace, el.EndpointsMeta.Name)
}
// Identity returns the Identity of the lock
func (el *EndpointsLock) Identity() string {
return el.LockConfig.Identity
}

View File

@ -0,0 +1,141 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resourcelock
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
)
const (
LeaderElectionRecordAnnotationKey = "control-plane.alpha.kubernetes.io/leader"
EndpointsResourceLock = "endpoints"
ConfigMapsResourceLock = "configmaps"
LeasesResourceLock = "leases"
EndpointsLeasesResourceLock = "endpointsleases"
ConfigMapsLeasesResourceLock = "configmapsleases"
)
// LeaderElectionRecord is the record that is stored in the leader election annotation.
// This information should be used for observational purposes only and could be replaced
// with a random string (e.g. UUID) with only slight modification of this code.
// TODO(mikedanese): this should potentially be versioned
type LeaderElectionRecord struct {
// HolderIdentity is the ID that owns the lease. If empty, no one owns this lease and
// all callers may acquire. Versions of this library prior to Kubernetes 1.14 will not
// attempt to acquire leases with empty identities and will wait for the full lease
// interval to expire before attempting to reacquire. This value is set to empty when
// a client voluntarily steps down.
HolderIdentity string `json:"holderIdentity"`
LeaseDurationSeconds int `json:"leaseDurationSeconds"`
AcquireTime metav1.Time `json:"acquireTime"`
RenewTime metav1.Time `json:"renewTime"`
LeaderTransitions int `json:"leaderTransitions"`
}
// EventRecorder records a change in the ResourceLock.
type EventRecorder interface {
Eventf(obj runtime.Object, eventType, reason, message string, args ...interface{})
}
// ResourceLockConfig common data that exists across different
// resource locks
type ResourceLockConfig struct {
// Identity is the unique string identifying a lease holder across
// all participants in an election.
Identity string
// EventRecorder is optional.
EventRecorder EventRecorder
}
// Interface offers a common interface for locking on arbitrary
// resources used in leader election. The Interface is used
// to hide the details on specific implementations in order to allow
// them to change over time. This interface is strictly for use
// by the leaderelection code.
type Interface interface {
// Get returns the LeaderElectionRecord
Get() (*LeaderElectionRecord, []byte, error)
// Create attempts to create a LeaderElectionRecord
Create(ler LeaderElectionRecord) error
// Update will update and existing LeaderElectionRecord
Update(ler LeaderElectionRecord) error
// RecordEvent is used to record events
RecordEvent(string)
// Identity will return the locks Identity
Identity() string
// Describe is used to convert details on current resource lock
// into a string
Describe() string
}
// Manufacture will create a lock of a given type according to the input parameters
func New(lockType string, ns string, name string, coreClient corev1.CoreV1Interface, coordinationClient coordinationv1.CoordinationV1Interface, rlc ResourceLockConfig) (Interface, error) {
endpointsLock := &EndpointsLock{
EndpointsMeta: metav1.ObjectMeta{
Namespace: ns,
Name: name,
},
Client: coreClient,
LockConfig: rlc,
}
configmapLock := &ConfigMapLock{
ConfigMapMeta: metav1.ObjectMeta{
Namespace: ns,
Name: name,
},
Client: coreClient,
LockConfig: rlc,
}
leaseLock := &LeaseLock{
LeaseMeta: metav1.ObjectMeta{
Namespace: ns,
Name: name,
},
Client: coordinationClient,
LockConfig: rlc,
}
switch lockType {
case EndpointsResourceLock:
return endpointsLock, nil
case ConfigMapsResourceLock:
return configmapLock, nil
case LeasesResourceLock:
return leaseLock, nil
case EndpointsLeasesResourceLock:
return &MultiLock{
Primary: endpointsLock,
Secondary: leaseLock,
}, nil
case ConfigMapsLeasesResourceLock:
return &MultiLock{
Primary: configmapLock,
Secondary: leaseLock,
}, nil
default:
return nil, fmt.Errorf("Invalid lock-type %s", lockType)
}
}

View File

@ -0,0 +1,129 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resourcelock
import (
"encoding/json"
"errors"
"fmt"
coordinationv1 "k8s.io/api/coordination/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
coordinationv1client "k8s.io/client-go/kubernetes/typed/coordination/v1"
)
type LeaseLock struct {
// LeaseMeta should contain a Name and a Namespace of a
// LeaseMeta object that the LeaderElector will attempt to lead.
LeaseMeta metav1.ObjectMeta
Client coordinationv1client.LeasesGetter
LockConfig ResourceLockConfig
lease *coordinationv1.Lease
}
// Get returns the election record from a Lease spec
func (ll *LeaseLock) Get() (*LeaderElectionRecord, []byte, error) {
var err error
ll.lease, err = ll.Client.Leases(ll.LeaseMeta.Namespace).Get(ll.LeaseMeta.Name, metav1.GetOptions{})
if err != nil {
return nil, nil, err
}
record := LeaseSpecToLeaderElectionRecord(&ll.lease.Spec)
recordByte, err := json.Marshal(*record)
if err != nil {
return nil, nil, err
}
return record, recordByte, nil
}
// Create attempts to create a Lease
func (ll *LeaseLock) Create(ler LeaderElectionRecord) error {
var err error
ll.lease, err = ll.Client.Leases(ll.LeaseMeta.Namespace).Create(&coordinationv1.Lease{
ObjectMeta: metav1.ObjectMeta{
Name: ll.LeaseMeta.Name,
Namespace: ll.LeaseMeta.Namespace,
},
Spec: LeaderElectionRecordToLeaseSpec(&ler),
})
return err
}
// Update will update an existing Lease spec.
func (ll *LeaseLock) Update(ler LeaderElectionRecord) error {
if ll.lease == nil {
return errors.New("lease not initialized, call get or create first")
}
ll.lease.Spec = LeaderElectionRecordToLeaseSpec(&ler)
var err error
ll.lease, err = ll.Client.Leases(ll.LeaseMeta.Namespace).Update(ll.lease)
return err
}
// RecordEvent in leader election while adding meta-data
func (ll *LeaseLock) RecordEvent(s string) {
if ll.LockConfig.EventRecorder == nil {
return
}
events := fmt.Sprintf("%v %v", ll.LockConfig.Identity, s)
ll.LockConfig.EventRecorder.Eventf(&coordinationv1.Lease{ObjectMeta: ll.lease.ObjectMeta}, corev1.EventTypeNormal, "LeaderElection", events)
}
// Describe is used to convert details on current resource lock
// into a string
func (ll *LeaseLock) Describe() string {
return fmt.Sprintf("%v/%v", ll.LeaseMeta.Namespace, ll.LeaseMeta.Name)
}
// Identity returns the Identity of the lock
func (ll *LeaseLock) Identity() string {
return ll.LockConfig.Identity
}
func LeaseSpecToLeaderElectionRecord(spec *coordinationv1.LeaseSpec) *LeaderElectionRecord {
var r LeaderElectionRecord
if spec.HolderIdentity != nil {
r.HolderIdentity = *spec.HolderIdentity
}
if spec.LeaseDurationSeconds != nil {
r.LeaseDurationSeconds = int(*spec.LeaseDurationSeconds)
}
if spec.LeaseTransitions != nil {
r.LeaderTransitions = int(*spec.LeaseTransitions)
}
if spec.AcquireTime != nil {
r.AcquireTime = metav1.Time{spec.AcquireTime.Time}
}
if spec.RenewTime != nil {
r.RenewTime = metav1.Time{spec.RenewTime.Time}
}
return &r
}
func LeaderElectionRecordToLeaseSpec(ler *LeaderElectionRecord) coordinationv1.LeaseSpec {
leaseDurationSeconds := int32(ler.LeaseDurationSeconds)
leaseTransitions := int32(ler.LeaderTransitions)
return coordinationv1.LeaseSpec{
HolderIdentity: &ler.HolderIdentity,
LeaseDurationSeconds: &leaseDurationSeconds,
AcquireTime: &metav1.MicroTime{ler.AcquireTime.Time},
RenewTime: &metav1.MicroTime{ler.RenewTime.Time},
LeaseTransitions: &leaseTransitions,
}
}

View File

@ -0,0 +1,103 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resourcelock
import (
"bytes"
"encoding/json"
apierrors "k8s.io/apimachinery/pkg/api/errors"
)
const (
UnknownLeader = "leaderelection.k8s.io/unknown"
)
// MultiLock is used for lock's migration
type MultiLock struct {
Primary Interface
Secondary Interface
}
// Get returns the older election record of the lock
func (ml *MultiLock) Get() (*LeaderElectionRecord, []byte, error) {
primary, primaryRaw, err := ml.Primary.Get()
if err != nil {
return nil, nil, err
}
secondary, secondaryRaw, err := ml.Secondary.Get()
if err != nil {
// Lock is held by old client
if apierrors.IsNotFound(err) && primary.HolderIdentity != ml.Identity() {
return primary, primaryRaw, nil
}
return nil, nil, err
}
if primary.HolderIdentity != secondary.HolderIdentity {
primary.HolderIdentity = UnknownLeader
primaryRaw, err = json.Marshal(primary)
if err != nil {
return nil, nil, err
}
}
return primary, ConcatRawRecord(primaryRaw, secondaryRaw), nil
}
// Create attempts to create both primary lock and secondary lock
func (ml *MultiLock) Create(ler LeaderElectionRecord) error {
err := ml.Primary.Create(ler)
if err != nil && !apierrors.IsAlreadyExists(err) {
return err
}
return ml.Secondary.Create(ler)
}
// Update will update and existing annotation on both two resources.
func (ml *MultiLock) Update(ler LeaderElectionRecord) error {
err := ml.Primary.Update(ler)
if err != nil {
return err
}
_, _, err = ml.Secondary.Get()
if err != nil && apierrors.IsNotFound(err) {
return ml.Secondary.Create(ler)
}
return ml.Secondary.Update(ler)
}
// RecordEvent in leader election while adding meta-data
func (ml *MultiLock) RecordEvent(s string) {
ml.Primary.RecordEvent(s)
ml.Secondary.RecordEvent(s)
}
// Describe is used to convert details on current resource lock
// into a string
func (ml *MultiLock) Describe() string {
return ml.Primary.Describe()
}
// Identity returns the Identity of the lock
func (ml *MultiLock) Identity() string {
return ml.Primary.Identity()
}
func ConcatRawRecord(primaryRaw, secondaryRaw []byte) []byte {
return bytes.Join([][]byte{primaryRaw, secondaryRaw}, []byte(","))
}

View File

@ -184,25 +184,25 @@ func (r conditionsImpl) GetCondition(t ConditionType) *Condition {
// SetCondition sets or updates the Condition on Conditions for Condition.Type.
// If there is an update, Conditions are stored back sorted.
func (r conditionsImpl) SetCondition(new Condition) {
func (r conditionsImpl) SetCondition(cond Condition) {
if r.accessor == nil {
return
}
t := new.Type
t := cond.Type
var conditions Conditions
for _, c := range r.accessor.GetConditions() {
if c.Type != t {
conditions = append(conditions, c)
} else {
// If we'd only update the LastTransitionTime, then return.
new.LastTransitionTime = c.LastTransitionTime
if reflect.DeepEqual(&new, &c) {
cond.LastTransitionTime = c.LastTransitionTime
if reflect.DeepEqual(cond, c) {
return
}
}
}
new.LastTransitionTime = VolatileTime{Inner: metav1.NewTime(time.Now())}
conditions = append(conditions, new)
cond.LastTransitionTime = VolatileTime{Inner: metav1.NewTime(time.Now())}
conditions = append(conditions, cond)
// Sorted for convenience of the consumer, i.e. kubectl.
sort.Slice(conditions, func(i, j int) bool { return conditions[i].Type < conditions[j].Type })
r.accessor.SetConditions(conditions)

View File

@ -36,7 +36,7 @@ func CheckDeprecated(ctx context.Context, obj interface{}) *FieldError {
// CheckDeprecated checks whether the provided named deprecated fields
// are set in a context where deprecation is disallowed.
// This is a json shallow check. We will recursively check inlined structs.
func CheckDeprecatedUpdate(ctx context.Context, obj interface{}, original interface{}) *FieldError {
func CheckDeprecatedUpdate(ctx context.Context, obj, original interface{}) *FieldError {
if IsDeprecatedAllowed(ctx) {
return nil
}

View File

@ -18,4 +18,12 @@ package duck
const (
GroupName = "duck.knative.dev"
// AddressableDuckVersionLabel is the label we use to declare
// that a type conforms to the Addressable duck type.
AddressableDuckVersionLabel = "duck.knative.dev/addressable"
// SourceDuckVersionLabel is the label we use to declare
// that a type conforms to the Source duck type.
SourceDuckVersionLabel = "duck.knative.dev/source"
)

View File

@ -21,6 +21,7 @@ import (
"knative.dev/pkg/apis"
"knative.dev/pkg/apis/duck"
"knative.dev/pkg/kmeta"
)
// +genduck
@ -45,6 +46,12 @@ type Status struct {
// +patchMergeKey=type
// +patchStrategy=merge
Conditions Conditions `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
// Annotations is additional Status fields for the Resource to save some
// additional State as well as convey more information to the user. This is
// roughly akin to Annotations on any k8s resource, just the reconciler conveying
// richer information outwards.
Annotations map[string]string `json:"annotations,omitempty"`
}
var _ apis.ConditionsAccessor = (*Status)(nil)
@ -87,6 +94,10 @@ func (s *Status) GetCondition(t apis.ConditionType) *apis.Condition {
// return true the condition type will be copied to the sink
func (source *Status) ConvertTo(ctx context.Context, sink *Status, predicates ...func(apis.ConditionType) bool) {
sink.ObservedGeneration = source.ObservedGeneration
if source.Annotations != nil {
// This will deep copy the map.
sink.Annotations = kmeta.UnionMaps(source.Annotations)
}
conditions := make(apis.Conditions, 0, len(source.Conditions))
for _, c := range source.Conditions {

View File

@ -428,6 +428,13 @@ func (in *Status) DeepCopyInto(out *Status) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}

View File

@ -204,11 +204,12 @@ func flatten(path []string) string {
var newPath []string
for _, part := range path {
for _, p := range strings.Split(part, ".") {
if p == CurrentField {
switch {
case p == CurrentField:
continue
} else if len(newPath) > 0 && isIndex(p) {
case len(newPath) > 0 && isIndex(p):
newPath[len(newPath)-1] += p
} else {
default:
newPath = append(newPath, p)
}
}
@ -383,7 +384,7 @@ func ErrOutOfBoundsValue(value, lower, upper interface{}, fieldPath string) *Fie
func CheckDisallowedFields(request, maskedRequest interface{}) *FieldError {
if disallowed, err := kmp.CompareSetFields(request, maskedRequest); err != nil {
return &FieldError{
Message: fmt.Sprintf("Internal Error"),
Message: "Internal Error",
Paths: []string{CurrentField},
}
} else if len(disallowed) > 0 {

View File

@ -201,7 +201,7 @@ func isKRShaped(tags map[string]map[string]string) bool {
if !has {
return false
}
return vals["krshapedlogic"] == "true"
return vals["krshapedlogic"] != "false"
}
func isNonNamespaced(tags map[string]map[string]string) bool {

View File

@ -142,9 +142,21 @@ func (g *reconcilerControllerGenerator) GenerateType(c *generator.Context, t *ty
Package: "context",
Name: "Context",
}),
"fmtSprintf": c.Universe.Function(types.Name{
Package: "fmt",
Name: "Sprintf",
"reconcilerLeaderAwareFuncs": c.Universe.Type(types.Name{
Package: "knative.dev/pkg/reconciler",
Name: "LeaderAwareFuncs",
}),
"reconcilerBucket": c.Universe.Type(types.Name{
Package: "knative.dev/pkg/reconciler",
Name: "Bucket",
}),
"typesNamespacedName": c.Universe.Type(types.Name{
Package: "k8s.io/apimachinery/pkg/types",
Name: "NamespacedName",
}),
"labelsEverything": c.Universe.Function(types.Name{
Package: "k8s.io/apimachinery/pkg/labels",
Name: "Everything",
}),
"stringsReplaceAll": c.Universe.Function(types.Name{
Package: "strings",
@ -154,6 +166,10 @@ func (g *reconcilerControllerGenerator) GenerateType(c *generator.Context, t *ty
Package: "reflect",
Name: "TypeOf",
}),
"fmtSprintf": c.Universe.Function(types.Name{
Package: "fmt",
Name: "Sprintf",
}),
}
sw.Do(reconcilerControllerNewImpl, m)
@ -185,9 +201,27 @@ func NewImpl(ctx {{.contextContext|raw}}, r Interface{{if .hasClass}}, classValu
{{.type|lowercaseSingular}}Informer := {{.informerGet|raw}}(ctx)
lister := {{.type|lowercaseSingular}}Informer.Lister()
rec := &reconcilerImpl{
LeaderAwareFuncs: {{.reconcilerLeaderAwareFuncs|raw}}{
PromoteFunc: func(bkt {{.reconcilerBucket|raw}}, enq func({{.reconcilerBucket|raw}}, {{.typesNamespacedName|raw}})) error {
all, err := lister.List({{.labelsEverything|raw}}())
if err != nil {
return err
}
for _, elt := range all {
// TODO: Consider letting users specify a filter in options.
enq(bkt, {{.typesNamespacedName|raw}}{
Namespace: elt.GetNamespace(),
Name: elt.GetName(),
})
}
return nil
},
},
Client: {{.clientGet|raw}}(ctx),
Lister: {{.type|lowercaseSingular}}Informer.Lister(),
Lister: lister,
reconciler: r,
finalizerName: defaultFinalizerName,
{{if .hasClass}}classValue: classValue,{{end}}
@ -211,6 +245,9 @@ func NewImpl(ctx {{.contextContext|raw}}, r Interface{{if .hasClass}}, classValu
if opts.AgentName != "" {
agentName = opts.AgentName
}
if opts.SkipStatusUpdates {
rec.skipStatusUpdates = true
}
}
rec.Recorder = createRecorder(ctx, agentName)

View File

@ -147,10 +147,35 @@ func (g *reconcilerReconcilerGenerator) GenerateType(c *generator.Context, t *ty
Package: "context",
Name: "Context",
}),
"fmtErrorf": c.Universe.Package("fmt").Function("Errorf"),
"reflectDeepEqual": c.Universe.Package("reflect").Function("DeepEqual"),
"equalitySemantic": c.Universe.Package("k8s.io/apimachinery/pkg/api/equality").Variable("Semantic"),
"jsonMarshal": c.Universe.Package("encoding/json").Function("Marshal"),
"typesMergePatchType": c.Universe.Package("k8s.io/apimachinery/pkg/types").Constant("MergePatchType"),
"syncRWMutex": c.Universe.Type(types.Name{
Package: "sync",
Name: "RWMutex",
}),
"reconcilerLeaderAware": c.Universe.Type(types.Name{
Package: "knative.dev/pkg/reconciler",
Name: "LeaderAware",
}),
"reconcilerLeaderAwareFuncs": c.Universe.Type(types.Name{
Package: "knative.dev/pkg/reconciler",
Name: "LeaderAwareFuncs",
}),
"reconcilerBucket": c.Universe.Type(types.Name{
Package: "knative.dev/pkg/reconciler",
Name: "Bucket",
}),
"typesNamespacedName": c.Universe.Type(types.Name{
Package: "k8s.io/apimachinery/pkg/types",
Name: "NamespacedName",
}),
"labelsEverything": c.Universe.Function(types.Name{
Package: "k8s.io/apimachinery/pkg/labels",
Name: "Everything",
}),
}
sw.Do(reconcilerInterfaceFactory, m)
@ -186,8 +211,30 @@ type Finalizer interface {
FinalizeKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}}
}
// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a
// controller reconciling {{.type|raw}} if they want to process resources for which
// they are not the leader.
type ReadOnlyInterface interface {
// ObserveKind implements logic to observe {{.type|raw}}.
// This method should not write to the API.
ObserveKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}}
}
// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a
// controller finalizing {{.type|raw}} if they want to process tombstoned resources
// even when they are not the leader. Due to the nature of how finalizers are handled
// there are no guarantees that this will be called.
type ReadOnlyFinalizer interface {
// ObserveFinalizeKind implements custom logic to observe the final state of {{.type|raw}}.
// This method should not write to the API.
ObserveFinalizeKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}}
}
// reconcilerImpl implements controller.Reconciler for {{.type|raw}} resources.
type reconcilerImpl struct {
// LeaderAwareFuncs is inlined to help us implement {{.reconcilerLeaderAware|raw}}
{{.reconcilerLeaderAwareFuncs|raw}}
// Client is used to write back status updates.
Client {{.clientsetInterface|raw}}
@ -208,6 +255,10 @@ type reconcilerImpl struct {
// finalizerName is the name of the finalizer to reconcile.
finalizerName string
// skipStatusUpdates configures whether or not this reconciler automatically updates
// the status of the reconciled resource.
skipStatusUpdates bool
{{if .hasClass}}
// classValue is the resource annotation[{{ .class }}] instance value this reconciler instance filters on.
classValue string
@ -216,6 +267,8 @@ type reconcilerImpl struct {
// Check that our Reconciler implements controller.Reconciler
var _ controller.Reconciler = (*reconcilerImpl)(nil)
// Check that our generated Reconciler is always LeaderAware.
var _ {{.reconcilerLeaderAware|raw}} = (*reconcilerImpl)(nil)
`
@ -226,7 +279,30 @@ func NewReconciler(ctx {{.contextContext|raw}}, logger *{{.zapSugaredLogger|raw}
logger.Fatalf("up to one options struct is supported, found %d", len(options))
}
// Fail fast when users inadvertently implement the other LeaderAware interface.
// For the typed reconcilers, Promote shouldn't take any arguments.
if _, ok := r.({{.reconcilerLeaderAware|raw}}); ok {
logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r)
}
// TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer.
rec := &reconcilerImpl{
LeaderAwareFuncs: {{.reconcilerLeaderAwareFuncs|raw}}{
PromoteFunc: func(bkt {{.reconcilerBucket|raw}}, enq func({{.reconcilerBucket|raw}}, {{.typesNamespacedName|raw}})) error {
all, err := lister.List({{.labelsEverything|raw}}())
if err != nil {
return err
}
for _, elt := range all {
// TODO: Consider letting users specify a filter in options.
enq(bkt, {{.typesNamespacedName|raw}}{
Namespace: elt.GetNamespace(),
Name: elt.GetName(),
})
}
return nil
},
},
Client: client,
Lister: lister,
Recorder: recorder,
@ -253,6 +329,25 @@ var reconcilerImplFactory = `
func (r *reconcilerImpl) Reconcile(ctx {{.contextContext|raw}}, key string) error {
logger := {{.loggingFromContext|raw}}(ctx)
// Convert the namespace/name string into a distinct namespace and name
namespace, name, err := {{.cacheSplitMetaNamespaceKey|raw}}(key)
if err != nil {
logger.Errorf("invalid resource key: %s", key)
return nil
}
// Establish whether we are the leader for use below.
isLeader := r.IsLeaderFor({{.typesNamespacedName|raw}}{
Namespace: namespace,
Name: name,
})
roi, isROI := r.reconciler.(ReadOnlyInterface)
rof, isROF := r.reconciler.(ReadOnlyFinalizer);
if !isLeader && !isROI && !isROF {
// If we are not the leader, and we don't implement either ReadOnly
// interface, then take a fast-path out.
return nil
}
// If configStore is set, attach the frozen configuration to the context.
if r.configStore != nil {
ctx = r.configStore.ToContext(ctx)
@ -261,19 +356,7 @@ func (r *reconcilerImpl) Reconcile(ctx {{.contextContext|raw}}, key string) erro
// Add the recorder to context.
ctx = {{.controllerWithEventRecorder|raw}}(ctx, r.Recorder)
// Convert the namespace/name string into a distinct namespace and name
{{if .nonNamespaced}}
_, name, err := {{.cacheSplitMetaNamespaceKey|raw}}(key)
{{else}}
namespace, name, err := {{.cacheSplitMetaNamespaceKey|raw}}(key)
{{end}}
if err != nil {
logger.Errorf("invalid resource key: %s", key)
return nil
}
// Get the resource with this namespace/name.
{{if .nonNamespaced}}
getter := r.Lister
{{else}}
@ -302,27 +385,34 @@ func (r *reconcilerImpl) Reconcile(ctx {{.contextContext|raw}}, key string) erro
var reconcileEvent {{.reconcilerEvent|raw}}
if resource.GetDeletionTimestamp().IsZero() {
// Append the target method to the logger.
logger = logger.With(zap.String("targetMethod", "ReconcileKind"))
if isLeader {
// Append the target method to the logger.
logger = logger.With(zap.String("targetMethod", "ReconcileKind"))
// Set and update the finalizer on resource if r.reconciler
// implements Finalizer.
if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil {
logger.Warnw("Failed to set finalizers", zap.Error(err))
// Set and update the finalizer on resource if r.reconciler
// implements Finalizer.
if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil {
return {{.fmtErrorf|raw}}("failed to set finalizers: %w", err)
}
{{if .isKRShaped}}
reconciler.PreProcessReconcile(ctx, resource)
{{end}}
// Reconcile this copy of the resource and then write back any status
// updates regardless of whether the reconciliation errored out.
reconcileEvent = r.reconciler.ReconcileKind(ctx, resource)
{{if .isKRShaped}}
reconciler.PostProcessReconcile(ctx, resource, original)
{{end}}
} else if isROI {
// Append the target method to the logger.
logger = logger.With(zap.String("targetMethod", "ObserveKind"))
// Observe any changes to this resource, since we are not the leader.
reconcileEvent = roi.ObserveKind(ctx, resource)
}
{{if .isKRShaped}}
reconciler.PreProcessReconcile(ctx, resource)
{{end}}
// Reconcile this copy of the resource and then write back any status
// updates regardless of whether the reconciliation errored out.
reconcileEvent = r.reconciler.ReconcileKind(ctx, resource)
{{if .isKRShaped}}
reconciler.PostProcessReconcile(ctx, resource)
{{end}}
} else if fin, ok := r.reconciler.(Finalizer); ok {
} else if fin, ok := r.reconciler.(Finalizer); isLeader && ok {
// Append the target method to the logger.
logger = logger.With(zap.String("targetMethod", "FinalizeKind"))
@ -330,21 +420,32 @@ func (r *reconcilerImpl) Reconcile(ctx {{.contextContext|raw}}, key string) erro
// and reconciled cleanly (nil or normal event), remove the finalizer.
reconcileEvent = fin.FinalizeKind(ctx, resource)
if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil {
logger.Warnw("Failed to clear finalizers", zap.Error(err))
return {{.fmtErrorf|raw}}("failed to clear finalizers: %w", err)
}
} else if !isLeader && isROF {
// Append the target method to the logger.
logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind"))
// For finalizing reconcilers, just observe when we aren't the leader.
reconcileEvent = rof.ObserveFinalizeKind(ctx, resource)
}
// Synchronize the status.
if {{.equalitySemantic|raw}}.DeepEqual(original.Status, resource.Status) {
// If we didn't change anything then don't call updateStatus.
// This is important because the copy we loaded from the injectionInformer's
// cache may be stale and we don't want to overwrite a prior update
// to status with this stale state.
} else if err = r.updateStatus(original, resource); err != nil {
logger.Warnw("Failed to update resource status", zap.Error(err))
r.Recorder.Eventf(resource, {{.corev1EventTypeWarning|raw}}, "UpdateFailed",
"Failed to update status for %q: %v", resource.Name, err)
return err
if !r.skipStatusUpdates {
// Synchronize the status.
if {{.equalitySemantic|raw}}.DeepEqual(original.Status, resource.Status) {
// If we didn't change anything then don't call updateStatus.
// This is important because the copy we loaded from the injectionInformer's
// cache may be stale and we don't want to overwrite a prior update
// to status with this stale state.
} else if !isLeader {
logger.Warn("Saw status changes when we aren't the leader!")
// TODO: Consider logging the diff at Debug?
} else if err = r.updateStatus(original, resource); err != nil {
logger.Warnw("Failed to update resource status", zap.Error(err))
r.Recorder.Eventf(resource, {{.corev1EventTypeWarning|raw}}, "UpdateFailed",
"Failed to update status for %q: %v", resource.Name, err)
return err
}
}
// Report the reconciler event, if any.
@ -463,10 +564,11 @@ func (r *reconcilerImpl) updateFinalizersFiltered(ctx {{.contextContext|raw}}, r
{{else}}
patcher := r.Client.{{.group}}{{.version}}().{{.type|apiGroup}}(resource.Namespace)
{{end}}
resource, err = patcher.Patch(resource.Name, {{.typesMergePatchType|raw}}, patch)
resourceName := resource.Name
resource, err = patcher.Patch(resourceName, {{.typesMergePatchType|raw}}, patch)
if err != nil {
r.Recorder.Eventf(resource, {{.corev1EventTypeWarning|raw}}, "FinalizerUpdateFailed",
"Failed to update finalizers for %q: %v", resource.Name, err)
"Failed to update finalizers for %q: %v", resourceName, err)
} else {
r.Recorder.Eventf(resource, {{.corev1EventTypeNormal|raw}}, "FinalizerUpdate",
"Updated %q finalizers", resource.GetName())
@ -518,4 +620,5 @@ func (r *reconcilerImpl) clearFinalizer(ctx {{.contextContext|raw}}, resource *{
// Synchronize the finalizers filtered by r.finalizerName.
return r.updateFinalizersFiltered(ctx, resource)
}
`

View File

@ -77,6 +77,14 @@ func (g *reconcilerReconcilerStubGenerator) GenerateType(c *generator.Context, t
Package: g.reconcilerPkg,
Name: "Finalizer",
}),
"reconcilerReadOnlyInterface": c.Universe.Type(types.Name{
Package: g.reconcilerPkg,
Name: "ReadOnlyInterface",
}),
"reconcilerReadOnlyFinalizer": c.Universe.Type(types.Name{
Package: g.reconcilerPkg,
Name: "ReadOnlyFinalizer",
}),
"corev1EventTypeNormal": c.Universe.Type(types.Name{
Package: "k8s.io/api/core/v1",
Name: "EventTypeNormal",
@ -112,16 +120,26 @@ var _ {{.reconcilerInterface|raw}} = (*Reconciler)(nil)
// Optionally check that our Reconciler implements Finalizer
//var _ {{.reconcilerFinalizer|raw}} = (*Reconciler)(nil)
// Optionally check that our Reconciler implements ReadOnlyInterface
// Implement this to observe resources even when we are not the leader.
//var _ {{.reconcilerReadOnlyInterface|raw}} = (*Reconciler)(nil)
// Optionally check that our Reconciler implements ReadOnlyFinalizer
// Implement this to observe tombstoned resources even when we are not
// the leader (best effort).
//var _ {{.reconcilerReadOnlyFinalizer|raw}} = (*Reconciler)(nil)
// ReconcileKind implements Interface.ReconcileKind.
func (r *Reconciler) ReconcileKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}} {
// TODO: use this if the resource implements InitializeConditions.
{{if not .isKRShaped}}// TODO: use this if the resource implements InitializeConditions.
// o.Status.InitializeConditions()
{{end}}
// TODO: add custom reconciliation logic here.
{{if not .isKRShaped}}
// TODO: use this if the object has .status.ObservedGeneration.
// o.Status.ObservedGeneration = o.Generation
// o.Status.ObservedGeneration = o.Generation{{end}}
return newReconciledNormal(o.Namespace, o.Name)
}
@ -131,4 +149,16 @@ func (r *Reconciler) ReconcileKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}
// // TODO: add custom finalization logic here.
// return nil
//}
// Optionally, use ObserveKind to observe the resource when we are not the leader.
// func (r *Reconciler) ObserveKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}} {
// // TODO: add custom observation logic here.
// return nil
// }
// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader.
//func (r *Reconciler) ObserveFinalizeKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}} {
// // TODO: add custom observation logic here.
// return nil
//}
`

View File

@ -0,0 +1,44 @@
/*
Copyright 2020 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package configmap
import (
"fmt"
"hash/crc32"
"regexp"
"strings"
)
const (
// ExampleKey signifies a given example configuration in a ConfigMap.
ExampleKey = "_example"
// ExampleChecksumAnnotation is the annotation that stores the computed checksum.
ExampleChecksumAnnotation = "knative.dev/example-checksum"
)
var (
// Allows for normalizing by collapsing newlines.
sequentialNewlines = regexp.MustCompile("(?:\r?\n)+")
)
// Checksum generates a checksum for the example value to be compared against
// a respective annotation.
// Leading and trailing spaces are ignored.
func Checksum(value string) string {
return fmt.Sprintf("%08x", crc32.ChecksumIEEE([]byte(sequentialNewlines.ReplaceAllString(strings.TrimSpace(value), `\n`))))
}

View File

@ -26,9 +26,8 @@ import (
type ManualWatcher struct {
Namespace string
// Guards mutations to defaultImpl fields
m sync.RWMutex
// Guards observers
m sync.RWMutex
observers map[string][]Observer
}
@ -40,7 +39,7 @@ func (w *ManualWatcher) Watch(name string, o ...Observer) {
defer w.m.Unlock()
if w.observers == nil {
w.observers = make(map[string][]Observer, len(o))
w.observers = make(map[string][]Observer, 1)
}
w.observers[name] = append(w.observers[name], o...)
}
@ -58,13 +57,8 @@ func (w *ManualWatcher) OnChange(configMap *corev1.ConfigMap) {
// Within our namespace, take the lock and see if there are any registered observers.
w.m.RLock()
defer w.m.RUnlock()
observers, ok := w.observers[configMap.Name]
if !ok {
return // No observers.
}
// Iterate over the observers and invoke their callbacks.
for _, o := range observers {
for _, o := range w.observers[configMap.Name] {
o(configMap)
}
}

View File

@ -22,6 +22,7 @@ import (
"strings"
"time"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/sets"
)
@ -76,6 +77,20 @@ func AsInt64(key string, target *int64) ParseFunc {
}
}
// AsUint32 parses the value at key as an uint32 into the target, if it exists.
func AsUint32(key string, target *uint32) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := strconv.ParseUint(raw, 10, 32)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = uint32(val)
}
return nil
}
}
// AsFloat64 parses the value at key as a float64 into the target, if it exists.
func AsFloat64(key string, target *float64) ParseFunc {
return func(data map[string]string) error {
@ -114,6 +129,21 @@ func AsStringSet(key string, target *sets.String) ParseFunc {
}
}
// AsQuantity parses the value at key as a *resource.Quantity into the target, if it exists
func AsQuantity(key string, target **resource.Quantity) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := resource.ParseQuantity(raw)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = &val
}
return nil
}
}
// Parse parses the given map using the parser functions passed in.
func Parse(data map[string]string, parsers ...ParseFunc) error {
for _, parse := range parsers {

View File

@ -23,9 +23,6 @@ import (
corev1 "k8s.io/api/core/v1"
)
// ExampleKey signifies a given example configuration in a ConfigMap.
const ExampleKey = "_example"
// Logger is the interface that UntypedStore expects its logger to conform to.
// UntypedStore will log when updates succeed or fail.
type Logger interface {
@ -157,9 +154,7 @@ func (s *UntypedStore) OnConfigChanged(c *corev1.ConfigMap) {
s.logger.Infof("%s config %q config was added or updated: %#v", s.name, name, result)
storage.Store(result)
go func() {
for _, f := range s.onAfterStore {
f(name, result)
}
}()
for _, f := range s.onAfterStore {
f(name, result)
}
}

View File

@ -18,6 +18,7 @@ package controller
import (
"context"
"errors"
"fmt"
"sync"
"time"
@ -35,8 +36,10 @@ import (
"k8s.io/client-go/util/workqueue"
"knative.dev/pkg/kmeta"
kle "knative.dev/pkg/leaderelection"
"knative.dev/pkg/logging"
"knative.dev/pkg/logging/logkey"
"knative.dev/pkg/reconciler"
)
const (
@ -175,6 +178,10 @@ func FilterWithNameAndNamespace(namespace, name string) func(obj interface{}) bo
// Impl is our core controller implementation. It handles queuing and feeding work
// from the queue to an implementation of Reconciler.
type Impl struct {
// Name is the unique name for this controller workqueue within this process.
// This is used for surfacing metrics, and per-controller leader election.
Name string
// Reconciler is the workhorse of this controller, it is fed the keys
// from the workqueue to process. Public for testing.
Reconciler Reconciler
@ -204,7 +211,9 @@ func NewImpl(r Reconciler, logger *zap.SugaredLogger, workQueueName string) *Imp
}
func NewImplWithStats(r Reconciler, logger *zap.SugaredLogger, workQueueName string, reporter StatsReporter) *Impl {
logger = logger.Named(workQueueName)
return &Impl{
Name: workQueueName,
Reconciler: r,
WorkQueue: workqueue.NewNamedRateLimitingQueue(
workqueue.DefaultControllerRateLimiter(),
@ -340,6 +349,14 @@ func (c *Impl) EnqueueKey(key types.NamespacedName) {
c.logger.Debugf("Adding to queue %s (depth: %d)", safeKey(key), c.WorkQueue.Len())
}
// MaybeEnqueueBucketKey takes a Bucket and namespace/name string and puts it onto the work queue.
func (c *Impl) MaybeEnqueueBucketKey(bkt reconciler.Bucket, key types.NamespacedName) {
if bkt.Has(key) {
c.WorkQueue.Add(key)
c.logger.Debugf("Adding to queue %s (depth: %d)", safeKey(key), c.WorkQueue.Len())
}
}
// EnqueueKeyAfter takes a namespace/name string and schedules its execution in
// the work queue after given delay.
func (c *Impl) EnqueueKeyAfter(key types.NamespacedName, delay time.Duration) {
@ -348,10 +365,12 @@ func (c *Impl) EnqueueKeyAfter(key types.NamespacedName, delay time.Duration) {
}
// RunContext starts the controller's worker threads, the number of which is threadiness.
// If the context has been decorated for LeaderElection, then an elector is built and run.
// It then blocks until the context is cancelled, at which point it shuts down its
// internal work queue and waits for workers to finish processing their current
// work items.
func (c *Impl) RunContext(ctx context.Context, threadiness int) error {
logger := c.logger
defer runtime.HandleCrash()
sg := sync.WaitGroup{}
defer sg.Wait()
@ -362,8 +381,20 @@ func (c *Impl) RunContext(ctx context.Context, threadiness int) error {
}
}()
if la, ok := c.Reconciler.(reconciler.LeaderAware); ok {
// Build and execute an elector.
le, err := kle.BuildElector(ctx, la, c.Name, c.MaybeEnqueueBucketKey)
if err != nil {
return err
}
sg.Add(1)
go func() {
defer sg.Done()
le.Run(ctx)
}()
}
// Launch workers to process resources that get enqueued to our workqueue.
logger := c.logger
logger.Info("Starting controller and workers")
for i := 0; i < threadiness; i++ {
sg.Add(1)
@ -448,7 +479,7 @@ func (c *Impl) processNextWorkItem() bool {
func (c *Impl) handleErr(err error, key types.NamespacedName) {
c.logger.Errorw("Reconcile error", zap.Error(err))
// Re-queue the key if it's an transient error.
// Re-queue the key if it's a transient error.
// We want to check that the queue is shutting down here
// since controller Run might have exited by now (since while this item was
// being processed, queue.Len==0).
@ -483,8 +514,8 @@ func (c *Impl) FilteredGlobalResync(f func(interface{}) bool, si cache.SharedInf
}
// NewPermanentError returns a new instance of permanentError.
// Users can wrap an error as permanentError with this in reconcile,
// when he does not expect the key to get re-queued.
// Users can wrap an error as permanentError with this in reconcile
// when they do not expect the key to get re-queued.
func NewPermanentError(err error) error {
return permanentError{e: err}
}
@ -495,16 +526,21 @@ type permanentError struct {
e error
}
// IsPermanentError returns true if given error is permanentError
// IsPermanentError returns true if the given error is a permanentError or
// wraps a permanentError.
func IsPermanentError(err error) bool {
switch err.(type) {
case permanentError:
return true
default:
return false
}
return errors.Is(err, permanentError{})
}
// Is implements the Is() interface of error. It returns whether the target
// error can be treated as equivalent to a permanentError.
func (permanentError) Is(target error) bool {
_, ok := target.(permanentError)
return ok
}
var _ error = permanentError{}
// Error implements the Error() interface of error.
func (err permanentError) Error() string {
if err.e == nil {
@ -514,6 +550,12 @@ func (err permanentError) Error() string {
return err.e.Error()
}
// Unwrap implements the Unwrap() interface of error. It returns the error
// wrapped inside permanentError.
func (err permanentError) Unwrap() error {
return err.e
}
// Informer is the group of methods that a type must implement to be passed to
// StartInformers.
type Informer interface {

View File

@ -31,6 +31,10 @@ type Options struct {
// AgentName is the name of the agent this reconciler uses. This overrides
// the default controller's agent name.
AgentName string
// SkipStatusUpdates configures this reconciler to either do automated status
// updates (default) or skip them if this is set to true.
SkipStatusUpdates bool
}
// OptionsFn is a callback method signature that accepts an Impl and returns

View File

@ -26,9 +26,7 @@ import (
_ "k8s.io/code-generator/cmd/defaulter-gen"
_ "k8s.io/code-generator/cmd/informer-gen"
_ "k8s.io/code-generator/cmd/lister-gen"
_ "k8s.io/kube-openapi/cmd/openapi-gen"
_ "knative.dev/pkg/codegen/cmd/injection-gen"
_ "knative.dev/test-infra/scripts"
)

View File

@ -19,6 +19,12 @@ set -o nounset
set -o pipefail
export GO111MODULE=on
# If we run with -mod=vendor here, then generate-groups.sh looks for vendor files in the wrong place.
export GOFLAGS=-mod=
if [ -z "${GOPATH:-}" ]; then
export GOPATH=$(go env GOPATH)
fi
source $(dirname $0)/../vendor/knative.dev/test-infra/scripts/library.sh
@ -41,7 +47,7 @@ EXTERNAL_INFORMER_PKG="k8s.io/client-go/informers" \
${REPO_ROOT_DIR}/hack/generate-knative.sh "injection" \
k8s.io/client-go \
k8s.io/api \
"admissionregistration:v1beta1 apps:v1 autoscaling:v1,v2beta1 batch:v1,v1beta1 core:v1 rbac:v1" \
"admissionregistration:v1beta1,v1 apps:v1 autoscaling:v1,v2beta1 batch:v1,v1beta1 core:v1 rbac:v1" \
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \
--force-genreconciler-kinds "Namespace"
@ -50,7 +56,7 @@ VERSIONED_CLIENTSET_PKG="k8s.io/apiextensions-apiserver/pkg/client/clientset/cli
${REPO_ROOT_DIR}/hack/generate-knative.sh "injection" \
k8s.io/apiextensions-apiserver/pkg/client \
k8s.io/apiextensions-apiserver/pkg/apis \
"apiextensions:v1beta1" \
"apiextensions:v1beta1,v1" \
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \
--force-genreconciler-kinds "CustomResourceDefinition"

View File

@ -26,7 +26,7 @@ cd ${ROOT_DIR}
# The list of dependencies that we track at HEAD and periodically
# float forward in this repository.
FLOATING_DEPS=(
"knative.dev/test-infra@release-0.15"
"knative.dev/test-infra@release-0.16"
)
# Parse flags to determine any we should pass to dep.

View File

@ -0,0 +1,41 @@
#!/usr/bin/env bash
# Copyright 2020 The Knative Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
export GO111MODULE=on
export K8S_VERSION="$1"
K8S_DEPS=(
"k8s.io/api"
"k8s.io/apiextensions-apiserver"
"k8s.io/apimachinery"
"k8s.io/code-generator"
"k8s.io/client-go"
)
for dep in "${K8S_DEPS[@]}"
do
go mod edit \
-require="${dep}@${K8S_VERSION}" \
-replace="${dep}=${dep}@${K8S_VERSION}"
done
./hack/update-deps.sh

View File

@ -454,14 +454,14 @@ for that resource.
#### Annotation based common logic
**krshaped=true may become the default if omitted in the future**
**krshapedlogic=false may be used to omit common reconciler logic**
Reconcilers can handle common logic for resources that conform to the KRShaped
interface. This allows the generated code to automatically increment
ObservedGeneration.
```go
// +genreconciler:krshapedlogic=true
// +genreconciler
```
Setting this annotation will emit the following in the generated reconciler.
@ -471,7 +471,7 @@ reconciler.PreProcessReconcile(ctx, resource)
reconcileEvent = r.reconciler.ReconcileKind(ctx, resource)
reconciler.PostProcessReconcile(ctx, resource)
reconciler.PostProcessReconcile(ctx, resource, oldResource)
```
#### Stubs

View File

@ -25,16 +25,18 @@ func CopyMap(a map[string]string) map[string]string {
return ret
}
// UnionMaps returns a map constructed from the union of `a` and `b`,
// where value from `b` wins.
func UnionMaps(a, b map[string]string) map[string]string {
out := make(map[string]string, len(a)+len(b))
for k, v := range a {
out[k] = v
// UnionMaps returns a map constructed from the union of input maps.
// where values from latter maps win.
func UnionMaps(maps ...map[string]string) map[string]string {
if len(maps) == 0 {
return map[string]string{}
}
for k, v := range b {
out[k] = v
out := make(map[string]string, len(maps[0]))
for _, m := range maps {
for k, v := range m {
out[k] = v
}
}
return out
}

View File

@ -0,0 +1,194 @@
/*
Copyright 2020 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package leaderelection
import (
"fmt"
"os"
"strconv"
"strings"
"time"
"github.com/kelseyhightower/envconfig"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/client-go/tools/leaderelection/resourcelock"
cm "knative.dev/pkg/configmap"
)
const configMapNameEnv = "CONFIG_LEADERELECTION_NAME"
// MaxBuckets is the maximum number of buckets to allow users to define.
// This is a variable so that it may be customized in the binary entrypoint.
var MaxBuckets uint32 = 10
var validResourceLocks = sets.NewString(resourcelock.LeasesResourceLock)
// NewConfigFromMap returns a Config for the given map, or an error.
func NewConfigFromMap(data map[string]string) (*Config, error) {
config := defaultConfig()
if err := cm.Parse(data,
cm.AsString("resourceLock", &config.ResourceLock),
cm.AsDuration("leaseDuration", &config.LeaseDuration),
cm.AsDuration("renewDeadline", &config.RenewDeadline),
cm.AsDuration("retryPeriod", &config.RetryPeriod),
cm.AsUint32("buckets", &config.Buckets),
// enabledComponents are not validated here, because they are dependent on
// the component. Components should provide additional validation for this
// field.
cm.AsStringSet("enabledComponents", &config.EnabledComponents),
); err != nil {
return nil, err
}
if config.Buckets < 1 || config.Buckets > MaxBuckets {
return nil, fmt.Errorf("buckets: value must be between %d <= %d <= %d", 1, config.Buckets, MaxBuckets)
}
if !validResourceLocks.Has(config.ResourceLock) {
return nil, fmt.Errorf(`resourceLock: invalid value %q: valid values are "leases"`, config.ResourceLock)
}
return config, nil
}
// NewConfigFromConfigMap returns a new Config from the given ConfigMap.
func NewConfigFromConfigMap(configMap *corev1.ConfigMap) (*Config, error) {
if configMap == nil {
config := defaultConfig()
return config, nil
}
return NewConfigFromMap(configMap.Data)
}
// Config represents the leader election config for a set of components
// contained within a single namespace. Typically these will correspond to a
// single source repository, viz: serving or eventing.
type Config struct {
ResourceLock string
Buckets uint32
LeaseDuration time.Duration
RenewDeadline time.Duration
RetryPeriod time.Duration
EnabledComponents sets.String
}
func (c *Config) GetComponentConfig(name string) ComponentConfig {
if c.EnabledComponents.Has(name) {
return ComponentConfig{
Component: name,
LeaderElect: true,
Buckets: c.Buckets,
ResourceLock: c.ResourceLock,
LeaseDuration: c.LeaseDuration,
RenewDeadline: c.RenewDeadline,
RetryPeriod: c.RetryPeriod,
}
}
return defaultComponentConfig(name)
}
func defaultConfig() *Config {
return &Config{
ResourceLock: "leases",
Buckets: 1,
LeaseDuration: 15 * time.Second,
RenewDeadline: 10 * time.Second,
RetryPeriod: 2 * time.Second,
EnabledComponents: sets.NewString(),
}
}
// ComponentConfig represents the leader election config for a single component.
type ComponentConfig struct {
Component string
LeaderElect bool
Buckets uint32
ResourceLock string
LeaseDuration time.Duration
RenewDeadline time.Duration
RetryPeriod time.Duration
}
// statefulSetID is a envconfig Decodable controller ordinal and name.
type statefulSetID struct {
ssName string
ordinal int
}
func (ssID *statefulSetID) Decode(v string) error {
if i := strings.LastIndex(v, "-"); i != -1 {
ui, err := strconv.ParseUint(v[i+1:], 10, 64)
ssID.ordinal = int(ui)
ssID.ssName = v[:i]
return err
}
return fmt.Errorf("%q is not a valid stateful set controller ordinal", v)
}
var _ envconfig.Decoder = (*statefulSetID)(nil)
// statefulSetConfig represents the required information for a StatefulSet service.
type statefulSetConfig struct {
StatefulSetID statefulSetID `envconfig:"STATEFUL_CONTROLLER_ORDINAL" required:"true"`
ServiceName string `envconfig:"STATEFUL_SERVICE_NAME" required:"true"`
Port string `envconfig:"STATEFUL_SERVICE_PORT" default:"80"`
Protocol string `envconfig:"STATEFUL_SERVICE_PROTOCOL" default:"http"`
}
// newStatefulSetConfig builds a stateful set LE config.
func newStatefulSetConfig() (*statefulSetConfig, error) {
ssc := &statefulSetConfig{}
if err := envconfig.Process("", ssc); err != nil {
return nil, err
}
return ssc, nil
}
func defaultComponentConfig(name string) ComponentConfig {
return ComponentConfig{
Component: name,
LeaderElect: false,
}
}
// ConfigMapName returns the name of the configmap to read for leader election
// settings.
func ConfigMapName() string {
cm := os.Getenv(configMapNameEnv)
if cm == "" {
return "config-leader-election"
}
return cm
}
// UniqueID returns a unique ID for use with a leader elector that prevents from
// pods running on the same host from colliding with one another.
func UniqueID() (string, error) {
id, err := os.Hostname()
if err != nil {
return "", err
}
return id + "_" + string(uuid.NewUUID()), nil
}

View File

@ -0,0 +1,271 @@
/*
Copyright 2020 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package leaderelection
import (
"context"
"fmt"
"hash/fnv"
"strings"
"sync"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
"knative.dev/pkg/logging"
"knative.dev/pkg/network"
"knative.dev/pkg/reconciler"
"knative.dev/pkg/system"
)
// WithDynamicLeaderElectorBuilder sets up the statefulset elector based on environment,
// falling back on the standard elector.
func WithDynamicLeaderElectorBuilder(ctx context.Context, kc kubernetes.Interface, cc ComponentConfig) context.Context {
logger := logging.FromContext(ctx)
ssc, err := newStatefulSetConfig()
if err == nil {
logger.Info("Running with StatefulSet leader election")
return withStatefulSetElectorBuilder(ctx, cc, *ssc)
}
logger.Info("Running with Standard leader election")
return WithStandardLeaderElectorBuilder(ctx, kc, cc)
}
// WithStandardLeaderElectorBuilder infuses a context with the ability to build
// LeaderElectors with the provided component configuration acquiring resource
// locks via the provided kubernetes client.
func WithStandardLeaderElectorBuilder(ctx context.Context, kc kubernetes.Interface, cc ComponentConfig) context.Context {
return context.WithValue(ctx, builderKey{}, &standardBuilder{
kc: kc,
lec: cc,
})
}
// withStatefulSetElectorBuilder infuses a context with the ability to build
// Electors which are assigned leadership based on the StatefulSet ordinal from
// the provided component configuration.
func withStatefulSetElectorBuilder(ctx context.Context, cc ComponentConfig, ssc statefulSetConfig) context.Context {
return context.WithValue(ctx, builderKey{}, &statefulSetBuilder{
lec: cc,
ssc: ssc,
})
}
// HasLeaderElection returns whether there is leader election configuration
// associated with the context
func HasLeaderElection(ctx context.Context) bool {
val := ctx.Value(builderKey{})
return val != nil
}
// Elector is the interface for running a leader elector.
type Elector interface {
Run(context.Context)
}
// BuildElector builds a leaderelection.LeaderElector for the named LeaderAware
// reconciler using a builder added to the context via WithStandardLeaderElectorBuilder.
func BuildElector(ctx context.Context, la reconciler.LeaderAware, name string, enq func(reconciler.Bucket, types.NamespacedName)) (Elector, error) {
if val := ctx.Value(builderKey{}); val != nil {
switch builder := val.(type) {
case *standardBuilder:
return builder.buildElector(ctx, la, name, enq)
case *statefulSetBuilder:
return builder.buildElector(ctx, la, enq)
}
}
return &unopposedElector{
la: la,
bkt: reconciler.UniversalBucket(),
enq: enq,
}, nil
}
type builderKey struct{}
type standardBuilder struct {
kc kubernetes.Interface
lec ComponentConfig
}
func (b *standardBuilder) buildElector(ctx context.Context, la reconciler.LeaderAware,
name string, enq func(reconciler.Bucket, types.NamespacedName)) (Elector, error) {
logger := logging.FromContext(ctx)
id, err := UniqueID()
if err != nil {
return nil, err
}
buckets := make([]Elector, 0, b.lec.Buckets)
for i := uint32(0); i < b.lec.Buckets; i++ {
bkt := &bucket{
// The resource name is the lowercase:
// {component}.{workqueue}.{index}-of-{total}
name: strings.ToLower(fmt.Sprintf("%s.%s.%02d-of-%02d", b.lec.Component, name, i, b.lec.Buckets)),
index: i,
total: b.lec.Buckets,
}
rl, err := resourcelock.New(b.lec.ResourceLock,
system.Namespace(), // use namespace we are running in
bkt.Name(),
b.kc.CoreV1(),
b.kc.CoordinationV1(),
resourcelock.ResourceLockConfig{
Identity: id,
})
if err != nil {
return nil, err
}
logger.Infof("%s will run in leader-elected mode with id %q", bkt.Name(), rl.Identity())
le, err := leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{
Lock: rl,
LeaseDuration: b.lec.LeaseDuration,
RenewDeadline: b.lec.RenewDeadline,
RetryPeriod: b.lec.RetryPeriod,
Callbacks: leaderelection.LeaderCallbacks{
OnStartedLeading: func(context.Context) {
logger.Infof("%q has started leading %q", rl.Identity(), bkt.Name())
if err := la.Promote(bkt, enq); err != nil {
// TODO(mattmoor): We expect this to effectively never happen,
// but if it does, we should support wrapping `le` in an elector
// we can cancel here.
logger.Fatalf("%q failed to Promote: %v", rl.Identity(), err)
}
},
OnStoppedLeading: func() {
logger.Infof("%q has stopped leading %q", rl.Identity(), bkt.Name())
la.Demote(bkt)
},
},
ReleaseOnCancel: true,
Name: rl.Identity(),
})
if err != nil {
return nil, err
}
// TODO: use health check watchdog, knative/pkg#1048
// if lec.WatchDog != nil {
// lec.WatchDog.SetLeaderElection(le)
// }
buckets = append(buckets, &runUntilCancelled{Elector: le})
}
return &runAll{les: buckets}, nil
}
type statefulSetBuilder struct {
lec ComponentConfig
ssc statefulSetConfig
}
func (b *statefulSetBuilder) buildElector(ctx context.Context, la reconciler.LeaderAware, enq func(reconciler.Bucket, types.NamespacedName)) (Elector, error) {
logger := logging.FromContext(ctx)
ordinal := uint32(b.ssc.StatefulSetID.ordinal)
logger.Infof("%s will run in StatefulSet ordinal assignement mode with ordinal %d",
b.lec.Component, ordinal)
return &unopposedElector{
bkt: &bucket{
// The name is the full pod DNS of the owner pod of this bucket.
name: fmt.Sprintf("%s://%s-%d.%s.%s.svc.%s:%s", b.ssc.Protocol,
b.ssc.StatefulSetID.ssName, ordinal, b.ssc.ServiceName,
system.Namespace(), network.GetClusterDomainName(), b.ssc.Port),
index: ordinal,
total: b.lec.Buckets,
},
la: la,
enq: enq,
}, nil
}
// unopposedElector promotes when run without needing to be elected.
type unopposedElector struct {
bkt reconciler.Bucket
la reconciler.LeaderAware
enq func(reconciler.Bucket, types.NamespacedName)
}
// Run implements Elector
func (ue *unopposedElector) Run(ctx context.Context) {
ue.la.Promote(ue.bkt, ue.enq)
}
type runAll struct {
les []Elector
}
// Run implements Elector
func (ra *runAll) Run(ctx context.Context) {
sg := sync.WaitGroup{}
defer sg.Wait()
for _, le := range ra.les {
sg.Add(1)
go func(le Elector) {
defer sg.Done()
le.Run(ctx)
}(le)
}
}
// runUntilCancelled wraps a single-term Elector into one that runs until
// the passed context is cancelled.
type runUntilCancelled struct {
// Elector is a single-term elector as we get from K8s leaderelection package.
Elector
}
// Run implements Elector
func (ruc *runUntilCancelled) Run(ctx context.Context) {
// Turn the single-term elector into a continuous election cycle.
for {
ruc.Elector.Run(ctx)
select {
case <-ctx.Done():
return // Run quit because context was cancelled, we are done!
default:
// Context wasn't cancelled, start over.
}
}
}
type bucket struct {
name string
// We are bucket {index} of {total}
index uint32
total uint32
}
var _ reconciler.Bucket = (*bucket)(nil)
// Name implements reconciler.Bucket
func (b *bucket) Name() string {
return b.name
}
// Has implements reconciler.Bucket
func (b *bucket) Has(nn types.NamespacedName) bool {
h := fnv.New32a()
h.Write([]byte(nn.Namespace + "." + nn.Name))
ii := h.Sum32() % b.total
return b.index == ii
}

View File

@ -0,0 +1,27 @@
/*
Copyright 2020 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package leaderelection
// ControllerOrdinal tries to get ordinal from the pod name of a StatefulSet,
// which is provided from the environment variable CONTROLLER_ORDINAL.
func ControllerOrdinal() (int, error) {
ssc, err := newStatefulSetConfig()
if err != nil {
return 0, err
}
return ssc.StatefulSetID.ordinal, nil
}

View File

@ -1,4 +0,0 @@
# The OWNERS file is used by prow to automatically merge approved PRs.
approvers:
- configmap-approvers

View File

@ -31,9 +31,8 @@ import (
"knative.dev/pkg/logging/logkey"
)
const ConfigMapNameEnv = "CONFIG_LOGGING_NAME"
const (
configMapNameEnv = "CONFIG_LOGGING_NAME"
loggerConfigKey = "zap-logger-config"
fallbackLoggerName = "fallback-logger"
)
@ -233,7 +232,7 @@ func UpdateLevelFromConfigMap(logger *zap.SugaredLogger, atomicLevel zap.AtomicL
// ConfigMapName gets the name of the logging ConfigMap
func ConfigMapName() string {
cm := os.Getenv(ConfigMapNameEnv)
cm := os.Getenv(configMapNameEnv)
if cm == "" {
return "config-logging"
}

View File

@ -20,6 +20,7 @@ import (
"strings"
"go.uber.org/zap/zapcore"
"knative.dev/pkg/logging/logkey"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
@ -49,10 +50,10 @@ func StringSet(s sets.String) zapcore.ObjectMarshalerFunc {
// logger.Info("Enqueuing", zap.Object("key", logging.NamespacedName(n)))
func NamespacedName(n types.NamespacedName) zapcore.ObjectMarshalerFunc {
return func(enc zapcore.ObjectEncoder) error {
if n.Namespace != "" {
enc.AddString("key", n.Name)
if n.Namespace == "" {
enc.AddString(logkey.Key, n.Name)
} else {
enc.AddString("key", n.Namespace+"/"+n.Name)
enc.AddString(logkey.Key, n.Namespace+"/"+n.Name)
}
return nil
}

View File

@ -37,39 +37,44 @@ import (
type metricsBackend string
const (
// BackendDestinationKey points to the config map entry key for metrics backend destination.
BackendDestinationKey = "metrics.backend-destination"
// DomainEnv points to the metrics domain env var.
DomainEnv = "METRICS_DOMAIN"
// The following keys are used to configure metrics reporting.
// See https://github.com/knative/serving/blob/master/config/config-observability.yaml
// for details.
AllowStackdriverCustomMetricsKey = "metrics.allow-stackdriver-custom-metrics"
BackendDestinationKey = "metrics.backend-destination"
ReportingPeriodKey = "metrics.reporting-period-seconds"
StackdriverCustomMetricSubDomainKey = "metrics.stackdriver-custom-metrics-subdomain"
allowStackdriverCustomMetricsKey = "metrics.allow-stackdriver-custom-metrics"
collectorAddressKey = "metrics.opencensus-address"
collectorSecureKey = "metrics.opencensus-require-tls"
reportingPeriodKey = "metrics.reporting-period-seconds"
// Stackdriver client configuration keys
StackdriverProjectIDKey = "metrics.stackdriver-project-id"
StackdriverGCPLocationKey = "metrics.stackdriver-gcp-location"
StackdriverClusterNameKey = "metrics.stackdriver-cluster-name"
StackdriverUseSecretKey = "metrics.stackdriver-use-secret"
DomainEnv = "METRICS_DOMAIN"
// Stackdriver is used for Stackdriver backend
Stackdriver metricsBackend = "stackdriver"
// Prometheus is used for Prometheus backend
Prometheus metricsBackend = "prometheus"
// OpenCensus is used to export to the OpenCensus Agent / Collector,
// which can send to many other services.
OpenCensus metricsBackend = "opencensus"
// None is used to export, well, nothing.
None metricsBackend = "none"
stackdriverClusterNameKey = "metrics.stackdriver-cluster-name"
stackdriverCustomMetricSubDomainKey = "metrics.stackdriver-custom-metrics-subdomain"
stackdriverGCPLocationKey = "metrics.stackdriver-gcp-location"
stackdriverProjectIDKey = "metrics.stackdriver-project-id"
stackdriverUseSecretKey = "metrics.stackdriver-use-secret"
defaultBackendEnvName = "DEFAULT_METRICS_BACKEND"
CollectorAddressKey = "metrics.opencensus-address"
CollectorSecureKey = "metrics.opencensus-require-tls"
defaultPrometheusPort = 9090
maxPrometheusPort = 65535
minPrometheusPort = 1024
prometheusPortEnvName = "METRICS_PROMETHEUS_PORT"
)
// Metrics backend "enum".
const (
// stackdriver is used for Stackdriver backend
stackdriver metricsBackend = "stackdriver"
// prometheus is used for Prometheus backend
prometheus metricsBackend = "prometheus"
// openCensus is used to export to the OpenCensus Agent / Collector,
// which can send to many other services.
openCensus metricsBackend = "opencensus"
// none is used to export, well, nothing.
none metricsBackend = "none"
)
type metricsConfig struct {
@ -141,10 +146,10 @@ type StackdriverClientConfig struct {
// NewStackdriverClientConfigFromMap creates a stackdriverClientConfig from the given map
func NewStackdriverClientConfigFromMap(config map[string]string) *StackdriverClientConfig {
return &StackdriverClientConfig{
ProjectID: config[StackdriverProjectIDKey],
GCPLocation: config[StackdriverGCPLocationKey],
ClusterName: config[StackdriverClusterNameKey],
UseSecret: strings.EqualFold(config[StackdriverUseSecretKey], "true"),
ProjectID: config[stackdriverProjectIDKey],
GCPLocation: config[stackdriverGCPLocationKey],
ClusterName: config[stackdriverClusterNameKey],
UseSecret: strings.EqualFold(config[stackdriverUseSecretKey], "true"),
}
}
@ -183,7 +188,7 @@ func createMetricsConfig(ops ExporterOptions, logger *zap.SugaredLogger) (*metri
backend := os.Getenv(defaultBackendEnvName)
if backend == "" {
// Use Prometheus if DEFAULT_METRICS_BACKEND does not exist or is empty
backend = string(Prometheus)
backend = string(prometheus)
}
// Override backend if it is set in the config map.
if backendFromConfig, ok := m[BackendDestinationKey]; ok {
@ -191,18 +196,18 @@ func createMetricsConfig(ops ExporterOptions, logger *zap.SugaredLogger) (*metri
}
lb := metricsBackend(strings.ToLower(backend))
switch lb {
case Stackdriver, Prometheus, OpenCensus:
case stackdriver, prometheus, openCensus:
mc.backendDestination = lb
default:
return nil, fmt.Errorf("unsupported metrics backend value %q", backend)
}
if mc.backendDestination == OpenCensus {
mc.collectorAddress = ops.ConfigMap[CollectorAddressKey]
if isSecure := ops.ConfigMap[CollectorSecureKey]; isSecure != "" {
if mc.backendDestination == openCensus {
mc.collectorAddress = ops.ConfigMap[collectorAddressKey]
if isSecure := ops.ConfigMap[collectorSecureKey]; isSecure != "" {
var err error
if mc.requireSecure, err = strconv.ParseBool(isSecure); err != nil {
return nil, fmt.Errorf("invalid %s value %q", CollectorSecureKey, isSecure)
return nil, fmt.Errorf("invalid %s value %q", collectorSecureKey, isSecure)
}
if mc.requireSecure {
@ -214,21 +219,28 @@ func createMetricsConfig(ops ExporterOptions, logger *zap.SugaredLogger) (*metri
}
}
if mc.backendDestination == Prometheus {
if mc.backendDestination == prometheus {
pp := ops.PrometheusPort
if pp == 0 {
pp = defaultPrometheusPort
var err error
pp, err = prometheusPort()
if err != nil {
return nil, fmt.Errorf("failed to determine Prometheus port: %w", err)
}
}
if pp < minPrometheusPort || pp > maxPrometheusPort {
return nil, fmt.Errorf("invalid port %v, should between %v and %v", pp, minPrometheusPort, maxPrometheusPort)
return nil, fmt.Errorf("invalid port %d, should be between %d and %d",
pp, minPrometheusPort, maxPrometheusPort)
}
mc.prometheusPort = pp
}
// If stackdriverClientConfig is not provided for stackdriver backend destination, OpenCensus will try to
// use the application default credentials. If that is not available, Opencensus would fail to create the
// metrics exporter.
if mc.backendDestination == Stackdriver {
if mc.backendDestination == stackdriver {
scc := NewStackdriverClientConfigFromMap(m)
mc.stackdriverClientConfig = *scc
mc.isStackdriverBackend = true
@ -236,15 +248,15 @@ func createMetricsConfig(ops ExporterOptions, logger *zap.SugaredLogger) (*metri
var err error
mc.stackdriverMetricTypePrefix = path.Join(mc.domain, mc.component)
customMetricsSubDomain := m[StackdriverCustomMetricSubDomainKey]
customMetricsSubDomain := m[stackdriverCustomMetricSubDomainKey]
if customMetricsSubDomain == "" {
customMetricsSubDomain = defaultCustomMetricSubDomain
}
mc.stackdriverCustomMetricTypePrefix = path.Join(customMetricTypePrefix, customMetricsSubDomain, mc.component)
if ascmStr := m[AllowStackdriverCustomMetricsKey]; ascmStr != "" {
if ascmStr := m[allowStackdriverCustomMetricsKey]; ascmStr != "" {
allowCustomMetrics, err = strconv.ParseBool(ascmStr)
if err != nil {
return nil, fmt.Errorf("invalid %s value %q", AllowStackdriverCustomMetricsKey, ascmStr)
return nil, fmt.Errorf("invalid %s value %q", allowStackdriverCustomMetricsKey, ascmStr)
}
}
@ -289,15 +301,15 @@ func createMetricsConfig(ops ExporterOptions, logger *zap.SugaredLogger) (*metri
// For Prometheus, we will use a lower value since the exporter doesn't
// push anything but just responds to pull requests, and shorter durations
// do not really hurt the performance and we rely on the scraping configuration.
if repStr, ok := m[ReportingPeriodKey]; ok && repStr != "" {
if repStr, ok := m[reportingPeriodKey]; ok && repStr != "" {
repInt, err := strconv.Atoi(repStr)
if err != nil {
return nil, fmt.Errorf("invalid %s value %q", ReportingPeriodKey, repStr)
return nil, fmt.Errorf("invalid %s value %q", reportingPeriodKey, repStr)
}
mc.reportingPeriod = time.Duration(repInt) * time.Second
} else if mc.backendDestination == Stackdriver {
} else if mc.backendDestination == stackdriver {
mc.reportingPeriod = 60 * time.Second
} else if mc.backendDestination == Prometheus {
} else if mc.backendDestination == prometheus {
mc.reportingPeriod = 5 * time.Second
}
@ -327,6 +339,25 @@ import (
)`, DomainEnv, DomainEnv))
}
// prometheusPort returns the TCP port number configured via the environment
// for the Prometheus metrics exporter if it's set, a default value otherwise.
// No validation is performed on the port value, other than ensuring that value
// is a valid port number (16-bit unsigned integer).
func prometheusPort() (int, error) {
ppStr := os.Getenv(prometheusPortEnvName)
if ppStr == "" {
return defaultPrometheusPort, nil
}
pp, err := strconv.ParseUint(ppStr, 10, 16)
if err != nil {
return -1, fmt.Errorf("the environment variable %q could not be parsed as a port number: %w",
prometheusPortEnvName, err)
}
return int(pp), nil
}
// JsonToMetricsOptions converts a json string of a
// ExporterOptions. Returns a non-nil ExporterOptions always.
func JsonToMetricsOptions(jsonOpts string) (*ExporterOptions, error) {

View File

@ -29,10 +29,10 @@ const (
DefaultLogURLTemplate = "http://localhost:8001/api/v1/namespaces/knative-monitoring/services/kibana-logging/proxy/app/kibana#/discover?_a=(query:(match:(kubernetes.labels.knative-dev%2FrevisionUID:(query:'${REVISION_UID}',type:phrase))))"
// The following is used to set the default metrics backend
DefaultRequestMetricsBackend = "prometheus"
defaultRequestMetricsBackend = "prometheus"
// The env var name for config-observability
ConfigMapNameEnv = "CONFIG_OBSERVABILITY_NAME"
configMapNameEnv = "CONFIG_OBSERVABILITY_NAME"
)
// ObservabilityConfig contains the configuration defined in the observability ConfigMap.
@ -64,7 +64,7 @@ type ObservabilityConfig struct {
func defaultConfig() *ObservabilityConfig {
return &ObservabilityConfig{
LoggingURLTemplate: DefaultLogURLTemplate,
RequestMetricsBackend: DefaultRequestMetricsBackend,
RequestMetricsBackend: defaultRequestMetricsBackend,
}
}
@ -95,7 +95,7 @@ func NewObservabilityConfigFromConfigMap(configMap *corev1.ConfigMap) (*Observab
// ConfigMapName gets the name of the metrics ConfigMap
func ConfigMapName() string {
cm := os.Getenv(ConfigMapNameEnv)
cm := os.Getenv(configMapNameEnv)
if cm == "" {
return "config-observability"
}

View File

@ -85,6 +85,26 @@ func UpdateExporterFromConfigMap(component string, logger *zap.SugaredLogger) fu
return ConfigMapWatcher(component, nil, logger)
}
// RegisterResourceView is similar to view.Register(), except that it will
// register the view across all Resources tracked by the system, rather than
// simply the default view.
// this is a placeholder for real implementation in https://github.com/knative/pkg/pull/1392.
// That PR will introduce a breaking change, as we need to convert some view.Register to RegisterResourceView in
// all callers, in serving, eventing, and eventing-contrib.
// Since that PR is huge, a better approach is to introduce the breaking change up front, by creating this
// passthrough method, and fixing all the callers before merging that PR.
func RegisterResourceView(views ...*view.View) error {
return view.Register(views...)
}
// UnregisterResourceView is similar to view.unRegister(), except that it will
// unregister the view across all Resources tracked by the system, rather than
// simply the default view.
// this is a placeholder for real implementation in https://github.com/knative/pkg/pull/1392.
func UnregisterResourceView(views ...*view.View) {
view.Unregister(views...)
}
// ConfigMapWatcher returns a helper func which updates the exporter configuration based on
// values in the supplied ConfigMap. This method captures a corev1.SecretLister which is used
// to configure mTLS with the opencensus agent.
@ -176,11 +196,11 @@ func isNewExporterRequired(newConfig *metricsConfig) bool {
// If the OpenCensus address has changed, restart the exporter.
// TODO(evankanderson): Should we just always restart the opencensus agent?
if newConfig.backendDestination == OpenCensus {
if newConfig.backendDestination == openCensus {
return newConfig.collectorAddress != cc.collectorAddress || newConfig.requireSecure != cc.requireSecure
}
return newConfig.backendDestination == Stackdriver && newConfig.stackdriverClientConfig != cc.stackdriverClientConfig
return newConfig.backendDestination == stackdriver && newConfig.stackdriverClientConfig != cc.stackdriverClientConfig
}
// newMetricsExporter gets a metrics exporter based on the config.
@ -198,13 +218,13 @@ func newMetricsExporter(config *metricsConfig, logger *zap.SugaredLogger) (view.
var err error
var e view.Exporter
switch config.backendDestination {
case OpenCensus:
case openCensus:
e, err = newOpenCensusExporter(config, logger)
case Stackdriver:
case stackdriver:
e, err = newStackdriverExporter(config, logger)
case Prometheus:
case prometheus:
e, err = newPrometheusExporter(config, logger)
case None:
case none:
e, err = nil, nil
default:
err = fmt.Errorf("unsupported metrics backend %v", config.backendDestination)

View File

@ -21,7 +21,7 @@ import (
"net/http"
"sync"
"contrib.go.opencensus.io/exporter/prometheus"
prom "contrib.go.opencensus.io/exporter/prometheus"
"go.opencensus.io/stats/view"
"go.uber.org/zap"
)
@ -32,7 +32,7 @@ var (
)
func newPrometheusExporter(config *metricsConfig, logger *zap.SugaredLogger) (view.Exporter, error) {
e, err := prometheus.NewExporter(prometheus.Options{Namespace: config.component})
e, err := prom.NewExporter(prom.Options{Namespace: config.component})
if err != nil {
logger.Errorw("Failed to create the Prometheus exporter.", zap.Error(err))
return nil, err
@ -61,7 +61,7 @@ func resetCurPromSrv() {
}
}
func startNewPromSrv(e *prometheus.Exporter, port int) *http.Server {
func startNewPromSrv(e *prom.Exporter, port int) *http.Server {
sm := http.NewServeMux()
sm.Handle("/metrics", e)
curPromSrvMux.Lock()

View File

@ -40,7 +40,7 @@ func RecordBatch(ctx context.Context, mss ...stats.Measurement) {
// be used to create a view.Distribution.
func Buckets125(low, high float64) []float64 {
buckets := []float64{low}
for last := low; last < high; last = last * 10 {
for last := low; last < high; last *= 10 {
buckets = append(buckets, 2*last, 5*last, 10*last)
}
return buckets

View File

@ -21,7 +21,7 @@ import (
"path"
"sync"
"contrib.go.opencensus.io/exporter/stackdriver"
sd "contrib.go.opencensus.io/exporter/stackdriver"
"contrib.go.opencensus.io/exporter/stackdriver/monitoredresource"
"go.opencensus.io/metric/metricdata"
"go.opencensus.io/stats/view"
@ -60,7 +60,7 @@ var (
// In product usage, this is always set to function newOpencensusSDExporter.
// In unit tests this is set to a fake one to avoid calling actual Google API
// service.
newStackdriverExporterFunc func(stackdriver.Options) (view.Exporter, error)
newStackdriverExporterFunc func(sd.Options) (view.Exporter, error)
// kubeclient is the in-cluster Kubernetes kubeclient, which is lazy-initialized on first use.
kubeclient *kubernetes.Clientset
@ -100,12 +100,15 @@ func init() {
kubeclientInitErr = nil
}
func newOpencensusSDExporter(o stackdriver.Options) (view.Exporter, error) {
e, err := stackdriver.NewExporter(o)
if err == nil {
// Start the exporter.
// TODO(https://github.com/knative/pkg/issues/866): Move this to an interface.
e.StartMetricsExporter()
func newOpencensusSDExporter(o sd.Options) (view.Exporter, error) {
e, err := sd.NewExporter(o)
if err != nil {
return nil, err
}
// Start the exporter.
// TODO(https://github.com/knative/pkg/issues/866): Move this to an interface.
if err := e.StartMetricsExporter(); err != nil {
return nil, err
}
return e, nil
}
@ -120,7 +123,7 @@ func newStackdriverExporter(config *metricsConfig, logger *zap.SugaredLogger) (v
logger.Warnw("Issue configuring Stackdriver exporter client options, no additional client options will be used: ", zap.Error(err))
}
// Automatically fall back on Google application default credentials
e, err := newStackdriverExporterFunc(stackdriver.Options{
e, err := newStackdriverExporterFunc(sd.Options{
ProjectID: gm.project,
Location: gm.location,
MonitoringClientOptions: co,
@ -128,7 +131,7 @@ func newStackdriverExporter(config *metricsConfig, logger *zap.SugaredLogger) (v
GetMetricPrefix: mpf,
ResourceByDescriptor: getResourceByDescriptorFunc(config.stackdriverMetricTypePrefix, gm),
ReportingInterval: config.reportingPeriod,
DefaultMonitoringLabels: &stackdriver.Labels{},
DefaultMonitoringLabels: &sd.Labels{},
})
if err != nil {
logger.Errorw("Failed to create the Stackdriver exporter: ", zap.Error(err))

View File

@ -19,7 +19,7 @@ package metrics
// InitForTesting initialize the necessary global variables for unit tests.
func InitForTesting() {
setCurMetricsConfig(&metricsConfig{
backendDestination: Prometheus,
backendDestination: prometheus,
component: "test",
domain: "test",
})

19
vendor/knative.dev/pkg/network/doc.go vendored Normal file
View File

@ -0,0 +1,19 @@
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package network holds the typed objects that define the schemas for
// configuring the knative networking layer.
package network

View File

@ -0,0 +1,75 @@
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package network
import (
"bufio"
"fmt"
"io"
"os"
"strings"
"sync"
)
const (
resolverFileName = "/etc/resolv.conf"
defaultDomainName = "cluster.local"
)
var (
domainName string
once sync.Once
)
// GetServiceHostname returns the fully qualified service hostname
func GetServiceHostname(name string, namespace string) string {
return fmt.Sprintf("%s.%s.svc.%s", name, namespace, GetClusterDomainName())
}
// GetClusterDomainName returns cluster's domain name or an error
// Closes issue: https://github.com/knative/eventing/issues/714
func GetClusterDomainName() string {
once.Do(func() {
f, err := os.Open(resolverFileName)
if err == nil {
defer f.Close()
domainName = getClusterDomainName(f)
} else {
domainName = defaultDomainName
}
})
return domainName
}
func getClusterDomainName(r io.Reader) string {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
elements := strings.Split(scanner.Text(), " ")
if elements[0] != "search" {
continue
}
for i := 1; i < len(elements)-1; i++ {
if strings.HasPrefix(elements[i], "svc.") {
return strings.TrimSuffix(elements[i][4:], ".")
}
}
}
// For all abnormal cases return default domain name
return defaultDomainName
}

View File

@ -0,0 +1,43 @@
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package network
import (
"io/ioutil"
"net/http"
"go.uber.org/zap"
)
// ErrorHandler sets up a handler suitable for use with the ErrorHandler field on
// httputil's reverse proxy.
func ErrorHandler(logger *zap.SugaredLogger) func(http.ResponseWriter, *http.Request, error) {
return func(w http.ResponseWriter, req *http.Request, err error) {
ss := readSockStat(logger)
logger.Errorw("error reverse proxying request; sockstat: "+ss, zap.Error(err))
http.Error(w, err.Error(), http.StatusBadGateway)
}
}
func readSockStat(logger *zap.SugaredLogger) string {
b, err := ioutil.ReadFile("/proc/net/sockstat")
if err != nil {
logger.Errorw("Unable to read sockstat", zap.Error(err))
return ""
}
return string(b)
}

55
vendor/knative.dev/pkg/network/h2c.go vendored Normal file
View File

@ -0,0 +1,55 @@
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package network
import (
"crypto/tls"
"net"
"net/http"
"time"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
// NewServer returns a new HTTP Server with HTTP2 handler.
func NewServer(addr string, h http.Handler) *http.Server {
h1s := &http.Server{
Addr: addr,
Handler: h2c.NewHandler(h, &http2.Server{}),
}
return h1s
}
// NewH2CTransport constructs a new H2C transport.
// That transport will reroute all HTTPS traffic to HTTP. This is
// to explicitly allow h2c (http2 without TLS) transport.
// See https://github.com/golang/go/issues/14141 for more details.
func NewH2CTransport() http.RoundTripper {
return &http2.Transport{
AllowHTTP: true,
DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
d := &net.Dialer{
Timeout: DefaultConnTimeout,
KeepAlive: 5 * time.Second,
DualStack: true,
}
return d.Dial(netw, addr)
},
}
}

View File

@ -0,0 +1,67 @@
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package network
import (
"net/http"
"strings"
"time"
)
const (
// DefaultConnTimeout specifies a short default connection timeout
// to avoid hitting the issue fixed in
// https://github.com/kubernetes/kubernetes/pull/72534 but only
// avalailable after Kubernetes 1.14.
//
// Our connections are usually between pods in the same cluster
// like activator <-> queue-proxy, or even between containers
// within the same pod queue-proxy <-> user-container, so a
// smaller connect timeout would be justifiable.
//
// We should consider exposing this as a configuration.
DefaultConnTimeout = 200 * time.Millisecond
// DefaultDrainTimeout is the time that Knative components on the data
// path will wait before shutting down server, but after starting to fail
// readiness probes to ensure network layer propagation and so that no requests
// are routed to this pod.
DefaultDrainTimeout = 30 * time.Second
// UserAgentKey is the constant for header "User-Agent".
UserAgentKey = "User-Agent"
// ProbeHeaderName is the name of a header that can be added to
// requests to probe the knative networking layer. Requests
// with this header will not be passed to the user container or
// included in request metrics.
ProbeHeaderName = "K-Network-Probe"
// Since K8s 1.8, prober requests have
// User-Agent = "kube-probe/{major-version}.{minor-version}".
KubeProbeUAPrefix = "kube-probe/"
// Istio with mTLS rewrites probes, but their probes pass a different
// user-agent. So we augment the probes with this header.
KubeletProbeHeaderName = "K-Kubelet-Probe"
)
// IsKubeletProbe returns true if the request is a Kubernetes probe.
func IsKubeletProbe(r *http.Request) bool {
return strings.HasPrefix(r.Header.Get("User-Agent"), KubeProbeUAPrefix) ||
r.Header.Get(KubeletProbeHeaderName) != ""
}

View File

@ -0,0 +1,128 @@
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package network
import (
"context"
"fmt"
"net"
"net/http"
"time"
"k8s.io/apimachinery/pkg/util/wait"
)
// RoundTripperFunc implementation roundtrips a request.
type RoundTripperFunc func(*http.Request) (*http.Response, error)
// RoundTrip implements http.RoundTripper.
func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) {
return rt(r)
}
func newAutoTransport(v1 http.RoundTripper, v2 http.RoundTripper) http.RoundTripper {
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
t := v1
if r.ProtoMajor == 2 {
t = v2
}
return t.RoundTrip(r)
})
}
const sleepTO = 30 * time.Millisecond
var backOffTemplate = wait.Backoff{
Duration: 50 * time.Millisecond,
Factor: 1.4,
Jitter: 0.1, // At most 10% jitter.
Steps: 15,
}
// DialWithBackOff executes `net.Dialer.DialContext()` with exponentially increasing
// dial timeouts. In addition it sleeps with random jitter between tries.
var DialWithBackOff = NewBackoffDialer(backOffTemplate)
// NewBackoffDialer returns a dialer that executes `net.Dialer.DialContext()` with
// exponentially increasing dial timeouts. In addition it sleeps with random jitter
// between tries.
func NewBackoffDialer(backoffConfig wait.Backoff) func(context.Context, string, string) (net.Conn, error) {
return func(ctx context.Context, network, address string) (net.Conn, error) {
return dialBackOffHelper(ctx, network, address, backoffConfig, sleepTO)
}
}
func dialBackOffHelper(ctx context.Context, network, address string, bo wait.Backoff, sleep time.Duration) (net.Conn, error) {
dialer := &net.Dialer{
Timeout: bo.Duration, // Initial duration.
KeepAlive: 5 * time.Second,
DualStack: true,
}
start := time.Now()
for {
c, err := dialer.DialContext(ctx, network, address)
if err != nil {
if err, ok := err.(net.Error); ok && err.Timeout() {
if bo.Steps < 1 {
break
}
dialer.Timeout = bo.Step()
time.Sleep(wait.Jitter(sleep, 1.0)) // Sleep with jitter.
continue
}
return nil, err
}
return c, nil
}
elapsed := time.Since(start)
return nil, fmt.Errorf("timed out dialing after %.2fs", elapsed.Seconds())
}
func newHTTPTransport(connTimeout time.Duration, disableKeepAlives bool) http.RoundTripper {
return &http.Transport{
// Those match net/http/transport.go
Proxy: http.ProxyFromEnvironment,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
DisableKeepAlives: disableKeepAlives,
// Those are bespoke.
DialContext: DialWithBackOff,
MaxIdleConns: 1000,
MaxIdleConnsPerHost: 100,
}
}
// NewProberTransport creates a RoundTripper that is useful for probing,
// since it will not cache connections.
func NewProberTransport() http.RoundTripper {
return newAutoTransport(
newHTTPTransport(DefaultConnTimeout, true /*disable keep-alives*/),
NewH2CTransport())
}
// NewAutoTransport creates a RoundTripper that can use appropriate transport
// based on the request's HTTP version.
func NewAutoTransport() http.RoundTripper {
return newAutoTransport(
newHTTPTransport(DefaultConnTimeout, false /*disable keep-alives*/),
NewH2CTransport())
}
// AutoTransport uses h2c for HTTP2 requests and falls back to `http.DefaultTransport` for all others
var AutoTransport = NewAutoTransport()

View File

@ -0,0 +1,117 @@
/*
Copyright 2020 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package reconciler
import (
"sync"
"k8s.io/apimachinery/pkg/types"
)
// Bucket is an opaque type used to scope leadership.
type Bucket interface {
// Name returns a string representing this bucket, which uniquely
// identifies the bucket and is suitable for use as a resource lock name.
Name() string
// Has determines whether this Bucket contains a particular key.
Has(key types.NamespacedName) bool
}
// UniversalBucket returns a Bucket that "Has()" all keys.
func UniversalBucket() Bucket {
return &bucket{}
}
type bucket struct{}
var _ Bucket = (*bucket)(nil)
// Name implements Bucket
func (b *bucket) Name() string {
return ""
}
// Has implements Bucket
func (b *bucket) Has(nn types.NamespacedName) bool {
return true
}
// LeaderAware is implemented by Reconcilers that are aware of their leader status.
type LeaderAware interface {
// Promote is called when we become the leader of a given Bucket. It must be
// supplied with an enqueue function through which a Bucket resync may be triggered.
Promote(b Bucket, enq func(Bucket, types.NamespacedName)) error
// Demote is called when we stop being the leader for the specified Bucket.
Demote(Bucket)
}
// LeaderAwareFuncs implements LeaderAware using the given functions for handling
// promotion and demotion.
type LeaderAwareFuncs struct {
sync.RWMutex
buckets map[string]Bucket
PromoteFunc func(b Bucket, enq func(Bucket, types.NamespacedName)) error
DemoteFunc func(b Bucket)
}
var _ LeaderAware = (*LeaderAwareFuncs)(nil)
// IsLeaderFor implements LeaderAware
func (laf *LeaderAwareFuncs) IsLeaderFor(key types.NamespacedName) bool {
laf.RLock()
defer laf.RUnlock()
for _, bkt := range laf.buckets {
if bkt.Has(key) {
return true
}
}
return false
}
// Promote implements LeaderAware
func (laf *LeaderAwareFuncs) Promote(b Bucket, enq func(Bucket, types.NamespacedName)) error {
func() {
laf.Lock()
defer laf.Unlock()
if laf.buckets == nil {
laf.buckets = make(map[string]Bucket, 1)
}
laf.buckets[b.Name()] = b
}()
if promote := laf.PromoteFunc; promote != nil {
return promote(b, enq)
}
return nil
}
// Demote implements LeaderAware
func (laf *LeaderAwareFuncs) Demote(b Bucket) {
func() {
laf.Lock()
defer laf.Unlock()
delete(laf.buckets, b.Name())
}()
if demote := laf.DemoteFunc; demote != nil {
demote(b)
}
}

View File

@ -18,7 +18,12 @@ package reconciler
import (
"context"
"reflect"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"knative.dev/pkg/apis"
duckv1 "knative.dev/pkg/apis/duck/v1"
"knative.dev/pkg/logging"
)
@ -29,28 +34,60 @@ const failedGenerationBump = "NewObservedGenFailure"
func PreProcessReconcile(ctx context.Context, resource duckv1.KRShaped) {
newStatus := resource.GetStatus()
if newStatus.ObservedGeneration != resource.GetGeneration() {
condSet := resource.GetConditionSet()
manager := condSet.Manage(newStatus)
// We may be reading a version of the object that was stored at an older version
// and may not have had all of the assumed defaults specified. This won't result
// in this getting written back to the API Server, but lets downstream logic make
// assumptions about defaulting.
if d, ok := resource.(apis.Defaultable); ok {
d.SetDefaults(ctx)
}
// Ensure conditions are initialized before we modify.
condSet := resource.GetConditionSet()
manager := condSet.Manage(newStatus)
manager.InitializeConditions()
if newStatus.ObservedGeneration != resource.GetGeneration() {
// Reset Ready/Successful to unknown. The reconciler is expected to overwrite this.
manager.MarkUnknown(condSet.GetTopLevelConditionType(), failedGenerationBump, "unsuccessfully observed a new generation")
}
}
// PostProcessReconcile contains logic to apply after reconciliation of a resource.
func PostProcessReconcile(ctx context.Context, resource duckv1.KRShaped) {
func PostProcessReconcile(ctx context.Context, resource, oldResource duckv1.KRShaped) {
logger := logging.FromContext(ctx)
newStatus := resource.GetStatus()
mgr := resource.GetConditionSet().Manage(newStatus)
status := resource.GetStatus()
mgr := resource.GetConditionSet().Manage(status)
// Bump observed generation to denote that we have processed this
// generation regardless of success or failure.
newStatus.ObservedGeneration = resource.GetGeneration()
status.ObservedGeneration = resource.GetGeneration()
if rc := mgr.GetTopLevelCondition(); rc == nil {
logger.Warn("A reconciliation included no top-level condition")
} else if rc.Reason == failedGenerationBump {
logger.Warn("A reconciler observed a new generation without updating the resource status")
}
groomConditionsTransitionTime(resource, oldResource)
}
// groomConditionsTransitionTime ensures that the LastTransitionTime only advances for resources
// where the condition has changed during reconciliation. This also ensures that all advanced
// conditions share the same timestamp.
func groomConditionsTransitionTime(resource, oldResource duckv1.KRShaped) {
now := apis.VolatileTime{Inner: metav1.NewTime(time.Now())}
sts := resource.GetStatus()
for i := range sts.Conditions {
cond := &sts.Conditions[i]
if oldCond := oldResource.GetStatus().GetCondition(cond.Type); oldCond != nil {
cond.LastTransitionTime = oldCond.LastTransitionTime
if reflect.DeepEqual(cond, oldCond) {
continue
}
}
cond.LastTransitionTime = now
}
}

32
vendor/knative.dev/pkg/system/clock.go vendored Normal file
View File

@ -0,0 +1,32 @@
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package system
import (
"time"
)
// Mockable interface for time based testing
type Clock interface {
Now() time.Time
}
type RealClock struct{}
func (RealClock) Now() time.Time {
return time.Now()
}

59
vendor/knative.dev/pkg/system/env.go vendored Normal file
View File

@ -0,0 +1,59 @@
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package system
import (
"fmt"
"os"
)
const (
NamespaceEnvKey = "SYSTEM_NAMESPACE"
ResourceLabelEnvKey = "SYSTEM_RESOURCE_LABEL"
)
// Namespace returns the name of the K8s namespace where our system components
// run.
func Namespace() string {
if ns := os.Getenv(NamespaceEnvKey); ns != "" {
return ns
}
panic(fmt.Sprintf(`The environment variable %q is not set
If this is a process running on Kubernetes, then it should be using the downward
API to initialize this variable via:
env:
- name: %s
valueFrom:
fieldRef:
fieldPath: metadata.namespace
If this is a Go unit test consuming system.Namespace() then it should add the
following import:
import (
_ "knative.dev/pkg/system/testing"
)`, NamespaceEnvKey, NamespaceEnvKey))
}
// ResourceLabel returns the label key identifying K8s objects our system
// components source their configuration from.
func ResourceLabel() string {
return os.Getenv(ResourceLabelEnvKey)
}

View File

@ -1,9 +1,12 @@
/*
Copyright 2018 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -11,13 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package scripts is a placeholder that allows us to pull the shell scripts
// via go mod vendor.
package scripts
import (
"fmt"
)
func main() {
fmt.Println("This is a dummy go file so `go dep` can be used with knative/test-infra/scripts")
fmt.Println("This file can be safely removed if one day this directory contains real, useful go code")
}

View File

@ -108,6 +108,8 @@ function dump_cluster_state() {
echo ">>> Details" >> ${output}
if [[ "${crd}" == "secrets" ]]; then
echo "Secrets are ignored for security reasons" >> ${output}
elif [[ "${crd}" == "events" ]]; then
echo "events are ignored as making a lot of noise" >> ${output}
else
kubectl get ${crd} --all-namespaces -o yaml >> ${output}
fi

View File

@ -389,25 +389,8 @@ function mktemp_with_extension() {
# $2 - check name as an identifier (e.g., GoBuild)
# $3 - failure message (can contain newlines), optional (means success)
function create_junit_xml() {
local xml="$(mktemp_with_extension ${ARTIFACTS}/junit_XXXXXXXX xml)"
local failure=""
if [[ "$3" != "" ]]; then
# Transform newlines into HTML code.
# Also escape `<` and `>` as here: https://github.com/golang/go/blob/50bd1c4d4eb4fac8ddeb5f063c099daccfb71b26/src/encoding/json/encode.go#L48,
# this is temporary solution for fixing https://github.com/knative/test-infra/issues/1204,
# which should be obsolete once Test-infra 2.0 is in place
local msg="$(echo -n "$3" | sed 's/$/\&#xA;/g' | sed 's/</\\u003c/' | sed 's/>/\\u003e/' | sed 's/&/\\u0026/' | tr -d '\n')"
failure="<failure message=\"Failed\" type=\"\">${msg}</failure>"
fi
cat << EOF > "${xml}"
<testsuites>
<testsuite tests="1" failures="1" time="0.000" name="$1">
<testcase classname="" name="$2" time="0.0">
${failure}
</testcase>
</testsuite>
</testsuites>
EOF
local xml="$(mktemp_with_extension "${ARTIFACTS}"/junit_XXXXXXXX xml)"
run_kntest junit --suite="$1" --name="$2" --err-msg="$3" --dest="${xml}" || return 1
}
# Runs a go test and generate a junit summary.
@ -449,14 +432,18 @@ function report_go_test() {
}
# Install Knative Serving in the current cluster.
# Parameters: $1 - Knative Serving manifest.
# Parameters: $1 - Knative Serving crds manifest.
# $2 - Knative Serving core manifest.
# $3 - Knative net-istio manifest.
function start_knative_serving() {
header "Starting Knative Serving"
subheader "Installing Knative Serving"
echo "Installing Serving CRDs from $1"
kubectl apply --selector knative.dev/crd-install=true -f "$1"
echo "Installing the rest of serving components from $1"
kubectl apply -f "$1"
echo "Installing Serving core components from $2"
kubectl apply -f "$2"
echo "Installing net-istio components from $3"
kubectl apply -f "$3"
wait_until_pods_running knative-serving || return 1
}
@ -478,12 +465,14 @@ function start_knative_monitoring() {
# Install the stable release Knative/serving in the current cluster.
# Parameters: $1 - Knative Serving version number, e.g. 0.6.0.
function start_release_knative_serving() {
start_knative_serving "https://storage.googleapis.com/knative-releases/serving/previous/v$1/serving.yaml"
start_knative_serving "https://storage.googleapis.com/knative-releases/serving/previous/v$1/serving-crds.yaml" \
"https://storage.googleapis.com/knative-releases/serving/previous/v$1/serving-core.yaml" \
"https://storage.googleapis.com/knative-releases/net-istio/previous/v$1/net-istio.yaml"
}
# Install the latest stable Knative Serving in the current cluster.
function start_latest_knative_serving() {
start_knative_serving "${KNATIVE_SERVING_RELEASE}"
start_knative_serving "${KNATIVE_SERVING_RELEASE_CRDS}" "${KNATIVE_SERVING_RELEASE_CORE}" "${KNATIVE_NET_ISTIO_RELEASE}"
}
# Install Knative Eventing in the current cluster.
@ -536,6 +525,24 @@ function run_go_tool() {
${tool} "$@"
}
# Run kntest tool, error out and ask users to install it if it's not currently installed.
# Parameters: $1..$n - parameters passed to the tool.
function run_kntest() {
# If the current repo is test-infra, run kntest from source.
if [[ "${REPO_NAME}" == "test-infra" ]]; then
# Each parameter can possibly be in the format of "--xxx yyy", using $@ can automatically split them into multiple positional arguments for the command.
# shellcheck disable=SC2068
go run "${REPO_ROOT_DIR}"/kntest/cmd/kntest $@
# Otherwise kntest must be installed.
else
if [[ ! -x "$(command -v kntest)" ]]; then
echo "--- FAIL: kntest not installed, please clone test-infra repo and run \`go install ./kntest/cmd/kntest\` to install it"; return 1;
fi
# shellcheck disable=SC2068
kntest $@
fi
}
# Run go-licenses to update licenses.
# Parameters: $1 - output file, relative to repo root dir.
# $2 - directory to inspect.
@ -742,6 +749,8 @@ readonly _TEST_INFRA_SCRIPTS_DIR="$(dirname $(get_canonical_path ${BASH_SOURCE[0
readonly REPO_NAME_FORMATTED="Knative $(capitalize ${REPO_NAME//-/ })"
# Public latest nightly or release yaml files.
readonly KNATIVE_SERVING_RELEASE="$(get_latest_knative_yaml_source "serving" "serving")"
readonly KNATIVE_SERVING_RELEASE_CRDS="$(get_latest_knative_yaml_source "serving" "serving-crds")"
readonly KNATIVE_SERVING_RELEASE_CORE="$(get_latest_knative_yaml_source "serving" "serving-core")"
readonly KNATIVE_NET_ISTIO_RELEASE="$(get_latest_knative_yaml_source "net-istio" "net-istio")"
readonly KNATIVE_EVENTING_RELEASE="$(get_latest_knative_yaml_source "eventing" "eventing")"
readonly KNATIVE_MONITORING_RELEASE="$(get_latest_knative_yaml_source "serving" "monitoring")"

View File

@ -0,0 +1,91 @@
#!/usr/bin/env bash
# Copyright 2020 The Knative Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
# This script updates test-infra scripts in-repo.
# Run it to update (usually from hack/update-deps.sh) the current scripts.
# Scripts are installed to REPO_ROOT/scripts/test-infra
# The following arguments are accepted:
# --update
# Do the update
# --ref X
# Defines which ref (branch, tag, commit) of test-infra to get scripts from; defaults to master
# --first-time
# Run this script from your repo root directory to install scripts for the first time
# Will also sed -i non-vendor scripts in the current repo to point to new path
# TODO: --verify
# Verify the contents of scripts/test-infra match the contents from commit sha in scripts/test-infra/COMMIT
# One can verify manually by running the script with '--ref $(cat scripts/test-infra/COMMIT)' and ensuring no files are staged
declare -i FIRST_TIME_SETUP=0
declare -i DO_UPDATE=0
declare SCRIPTS_REF=master
while [[ $# -ne 0 ]]; do
parameter="$1"
case ${parameter} in
--ref)
shift
SCRIPTS_REF="$1"
;;
--first-time)
FIRST_TIME_SETUP=1
;;
--update)
DO_UPDATE=1
;;
*)
echo "unknown option ${parameter}"
exit 1
;;
esac
shift
done
function do_read_tree() {
mkdir -p scripts/test-infra
git read-tree --prefix=scripts/test-infra -u "test-infra/${SCRIPTS_REF}:scripts"
git show-ref -s -- "refs/remotes/test-infra/${SCRIPTS_REF}" > scripts/test-infra/COMMIT
git add scripts/test-infra/COMMIT
echo "test-infra scripts installed to scripts/test-infra from branch ${SCRIPTS_REF}"
}
function run() {
if (( FIRST_TIME_SETUP )); then
if [[ ! -d .git ]]; then
echo "I don't believe you are in a repo root; exiting"
exit 5
fi
git remote add test-infra https://github.com/knative/test-infra.git || echo "test-infra remote already set; not changing"
git fetch test-infra "${SCRIPTS_REF}"
do_read_tree
echo "Attempting to point all scripts to use this new path"
grep -RiIl vendor/knative.dev/test-infra | grep -v ^vendor | grep -v ^scripts/test-infra | xargs sed -i 's+vendor/knative.dev/test-infra/scripts+scripts/test-infra+'
elif (( DO_UPDATE )); then
pushd "$(dirname "${BASH_SOURCE[0]}")/../.."
trap popd EXIT
git remote add test-infra https://github.com/knative/test-infra.git || true
git fetch test-infra "${SCRIPTS_REF}"
git rm -fr scripts/test-infra
rm -fR scripts/test-infra
do_read_tree
fi
}
run

21
vendor/modules.txt vendored
View File

@ -14,7 +14,7 @@ contrib.go.opencensus.io/exporter/stackdriver/monitoredresource
github.com/PuerkitoBio/purell
# github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578
github.com/PuerkitoBio/urlesc
# github.com/aws/aws-sdk-go v1.29.34
# github.com/aws/aws-sdk-go v1.30.5
github.com/aws/aws-sdk-go/aws
github.com/aws/aws-sdk-go/aws/awserr
github.com/aws/aws-sdk-go/aws/awsutil
@ -137,6 +137,8 @@ github.com/influxdata/tdigest
github.com/jmespath/go-jmespath
# github.com/json-iterator/go v1.1.9
github.com/json-iterator/go
# github.com/kelseyhightower/envconfig v1.4.0
github.com/kelseyhightower/envconfig
# github.com/mailru/easyjson v0.7.0
github.com/mailru/easyjson/buffer
github.com/mailru/easyjson/jlexer
@ -180,7 +182,7 @@ github.com/tsenart/vegeta/internal/resolver
github.com/tsenart/vegeta/lib
github.com/tsenart/vegeta/lib/lttb
github.com/tsenart/vegeta/lib/plot
# go.opencensus.io v0.22.3
# go.opencensus.io v0.22.4
go.opencensus.io
go.opencensus.io/internal
go.opencensus.io/internal/tagencoding
@ -221,6 +223,7 @@ golang.org/x/net/context
golang.org/x/net/context/ctxhttp
golang.org/x/net/http/httpguts
golang.org/x/net/http2
golang.org/x/net/http2/h2c
golang.org/x/net/http2/hpack
golang.org/x/net/idna
golang.org/x/net/internal/timeseries
@ -254,7 +257,7 @@ golang.org/x/tools/internal/imports
# golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
golang.org/x/xerrors
golang.org/x/xerrors/internal
# gomodules.xyz/jsonpatch/v2 v2.0.1
# gomodules.xyz/jsonpatch/v2 v2.1.0
gomodules.xyz/jsonpatch/v2
# gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485
gonum.org/v1/gonum/blas
@ -449,6 +452,7 @@ k8s.io/apimachinery/pkg/util/net
k8s.io/apimachinery/pkg/util/runtime
k8s.io/apimachinery/pkg/util/sets
k8s.io/apimachinery/pkg/util/strategicpatch
k8s.io/apimachinery/pkg/util/uuid
k8s.io/apimachinery/pkg/util/validation
k8s.io/apimachinery/pkg/util/validation/field
k8s.io/apimachinery/pkg/util/wait
@ -607,6 +611,8 @@ k8s.io/client-go/rest/watch
k8s.io/client-go/testing
k8s.io/client-go/tools/cache
k8s.io/client-go/tools/clientcmd/api
k8s.io/client-go/tools/leaderelection
k8s.io/client-go/tools/leaderelection/resourcelock
k8s.io/client-go/tools/metrics
k8s.io/client-go/tools/pager
k8s.io/client-go/tools/record
@ -680,7 +686,7 @@ k8s.io/kube-openapi/pkg/util/sets
k8s.io/utils/buffer
k8s.io/utils/integer
k8s.io/utils/trace
# knative.dev/pkg v0.0.0-20200519155757-14eb3ae3a5a7
# knative.dev/pkg v0.0.0-20200630170034-2c1a029eb97f
## explicit
knative.dev/pkg/apis
knative.dev/pkg/apis/duck
@ -695,17 +701,20 @@ knative.dev/pkg/hack
knative.dev/pkg/injection
knative.dev/pkg/kmeta
knative.dev/pkg/kmp
knative.dev/pkg/leaderelection
knative.dev/pkg/logging
knative.dev/pkg/logging/logkey
knative.dev/pkg/metrics
knative.dev/pkg/metrics/metricskey
knative.dev/pkg/network
knative.dev/pkg/reconciler
knative.dev/pkg/system
knative.dev/pkg/tracker
# knative.dev/test-infra v0.0.0-20200519161858-554a95a37986
# knative.dev/test-infra v0.0.0-20200630141629-15f40fe97047
## explicit
knative.dev/test-infra/scripts
knative.dev/test-infra/tools/dep-collector
# sigs.k8s.io/yaml v1.1.0
# sigs.k8s.io/yaml v1.2.0
sigs.k8s.io/yaml
# k8s.io/api => k8s.io/api v0.17.6
# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.17.6

15
vendor/sigs.k8s.io/yaml/.travis.yml generated vendored
View File

@ -1,14 +1,13 @@
language: go
dist: xenial
go:
- 1.9.x
- 1.10.x
- 1.11.x
- 1.12.x
- 1.13.x
script:
- go get -t -v ./...
- diff -u <(echo -n) <(gofmt -d .)
- diff -u <(echo -n) <(gofmt -d *.go)
- diff -u <(echo -n) <(golint $(go list -e ./...) | grep -v YAMLToJSON)
- go tool vet .
- go test -v -race ./...
- GO111MODULE=on go vet .
- GO111MODULE=on go test -v -race ./...
- git diff --exit-code
install:
- go get golang.org/x/lint/golint
- GO111MODULE=off go get golang.org/x/lint/golint

14
vendor/sigs.k8s.io/yaml/README.md generated vendored
View File

@ -1,12 +1,14 @@
# YAML marshaling and unmarshaling support for Go
[![Build Status](https://travis-ci.org/ghodss/yaml.svg)](https://travis-ci.org/ghodss/yaml)
[![Build Status](https://travis-ci.org/kubernetes-sigs/yaml.svg)](https://travis-ci.org/kubernetes-sigs/yaml)
kubernetes-sigs/yaml is a permanent fork of [ghodss/yaml](https://github.com/ghodss/yaml).
## Introduction
A wrapper around [go-yaml](https://github.com/go-yaml/yaml) designed to enable a better way of handling YAML when marshaling to and from structs.
In short, this library first converts YAML to JSON using go-yaml and then uses `json.Marshal` and `json.Unmarshal` to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods `MarshalJSON` and `UnmarshalJSON` unlike go-yaml. For a detailed overview of the rationale behind this method, [see this blog post](http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang/).
In short, this library first converts YAML to JSON using go-yaml and then uses `json.Marshal` and `json.Unmarshal` to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods `MarshalJSON` and `UnmarshalJSON` unlike go-yaml. For a detailed overview of the rationale behind this method, [see this blog post](http://web.archive.org/web/20190603050330/http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang/).
## Compatibility
@ -32,13 +34,13 @@ GOOD:
To install, run:
```
$ go get github.com/ghodss/yaml
$ go get sigs.k8s.io/yaml
```
And import using:
```
import "github.com/ghodss/yaml"
import "sigs.k8s.io/yaml"
```
Usage is very similar to the JSON library:
@ -49,7 +51,7 @@ package main
import (
"fmt"
"github.com/ghodss/yaml"
"sigs.k8s.io/yaml"
)
type Person struct {
@ -93,7 +95,7 @@ package main
import (
"fmt"
"github.com/ghodss/yaml"
"sigs.k8s.io/yaml"
)
func main() {

8
vendor/sigs.k8s.io/yaml/go.mod generated vendored Normal file
View File

@ -0,0 +1,8 @@
module sigs.k8s.io/yaml
go 1.12
require (
github.com/davecgh/go-spew v1.1.1
gopkg.in/yaml.v2 v2.2.8
)

9
vendor/sigs.k8s.io/yaml/go.sum generated vendored Normal file
View File

@ -0,0 +1,9 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

61
vendor/sigs.k8s.io/yaml/yaml.go generated vendored
View File

@ -317,3 +317,64 @@ func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (in
return yamlObj, nil
}
}
// JSONObjectToYAMLObject converts an in-memory JSON object into a YAML in-memory MapSlice,
// without going through a byte representation. A nil or empty map[string]interface{} input is
// converted to an empty map, i.e. yaml.MapSlice(nil).
//
// interface{} slices stay interface{} slices. map[string]interface{} becomes yaml.MapSlice.
//
// int64 and float64 are down casted following the logic of github.com/go-yaml/yaml:
// - float64s are down-casted as far as possible without data-loss to int, int64, uint64.
// - int64s are down-casted to int if possible without data-loss.
//
// Big int/int64/uint64 do not lose precision as in the json-yaml roundtripping case.
//
// string, bool and any other types are unchanged.
func JSONObjectToYAMLObject(j map[string]interface{}) yaml.MapSlice {
if len(j) == 0 {
return nil
}
ret := make(yaml.MapSlice, 0, len(j))
for k, v := range j {
ret = append(ret, yaml.MapItem{Key: k, Value: jsonToYAMLValue(v)})
}
return ret
}
func jsonToYAMLValue(j interface{}) interface{} {
switch j := j.(type) {
case map[string]interface{}:
if j == nil {
return interface{}(nil)
}
return JSONObjectToYAMLObject(j)
case []interface{}:
if j == nil {
return interface{}(nil)
}
ret := make([]interface{}, len(j))
for i := range j {
ret[i] = jsonToYAMLValue(j[i])
}
return ret
case float64:
// replicate the logic in https://github.com/go-yaml/yaml/blob/51d6538a90f86fe93ac480b35f37b2be17fef232/resolve.go#L151
if i64 := int64(j); j == float64(i64) {
if i := int(i64); i64 == int64(i) {
return i
}
return i64
}
if ui64 := uint64(j); j == float64(ui64) {
return ui64
}
return j
case int64:
if i := int(j); j == int64(i) {
return i
}
return j
}
return j
}