mirror of https://github.com/kubernetes/kops.git
update deps
This commit is contained in:
parent
be835064da
commit
2bad52ea8c
20
go.mod
20
go.mod
|
@ -31,7 +31,7 @@ replace (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.94.1
|
cloud.google.com/go v0.97.0
|
||||||
github.com/Azure/azure-pipeline-go v0.2.3
|
github.com/Azure/azure-pipeline-go v0.2.3
|
||||||
github.com/Azure/azure-sdk-for-go v56.2.0+incompatible
|
github.com/Azure/azure-sdk-for-go v56.2.0+incompatible
|
||||||
github.com/Azure/azure-storage-blob-go v0.13.0
|
github.com/Azure/azure-storage-blob-go v0.13.0
|
||||||
|
@ -49,11 +49,11 @@ require (
|
||||||
github.com/go-logr/logr v1.2.0
|
github.com/go-logr/logr v1.2.0
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
github.com/google/go-cmp v0.5.6
|
github.com/google/go-cmp v0.5.6
|
||||||
github.com/google/go-containerregistry v0.6.0
|
github.com/google/go-containerregistry v0.7.0
|
||||||
github.com/google/go-tpm v0.3.2
|
github.com/google/go-tpm v0.3.2
|
||||||
github.com/google/go-tpm-tools v0.3.0-beta1
|
github.com/google/go-tpm-tools v0.3.0-beta1
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/gophercloud/gophercloud v0.23.0
|
github.com/gophercloud/gophercloud v0.24.0
|
||||||
github.com/hashicorp/hcl/v2 v2.10.1
|
github.com/hashicorp/hcl/v2 v2.10.1
|
||||||
github.com/hashicorp/vault/api v1.1.1
|
github.com/hashicorp/vault/api v1.1.1
|
||||||
github.com/jacksontj/memberlistmesh v0.0.0-20190905163944-93462b9d2bb7
|
github.com/jacksontj/memberlistmesh v0.0.0-20190905163944-93462b9d2bb7
|
||||||
|
@ -72,7 +72,7 @@ require (
|
||||||
github.com/zclconf/go-cty v1.8.2
|
github.com/zclconf/go-cty v1.8.2
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
|
||||||
google.golang.org/api v0.57.0
|
google.golang.org/api v0.57.0
|
||||||
|
@ -123,10 +123,10 @@ require (
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||||
github.com/docker/cli v20.10.7+incompatible // indirect
|
github.com/docker/cli v20.10.10+incompatible // indirect
|
||||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||||
github.com/docker/docker v20.10.7+incompatible // indirect
|
github.com/docker/docker v20.10.10+incompatible // indirect
|
||||||
github.com/docker/docker-credential-helpers v0.6.3 // indirect
|
github.com/docker/docker-credential-helpers v0.6.4 // indirect
|
||||||
github.com/docker/go-connections v0.4.0 // indirect
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
github.com/docker/go-metrics v0.0.1 // indirect
|
github.com/docker/go-metrics v0.0.1 // indirect
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
|
@ -190,7 +190,7 @@ require (
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/oklog/ulid v1.3.1 // indirect
|
github.com/oklog/ulid v1.3.1 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
github.com/opencontainers/image-spec v1.0.2-0.20210730191737-8e42a01fb1b7 // indirect
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||||
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
@ -219,8 +219,8 @@ require (
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e // indirect
|
google.golang.org/genproto v0.0.0-20211111162719-482062a4217b // indirect
|
||||||
google.golang.org/grpc v1.41.0 // indirect
|
google.golang.org/grpc v1.42.0 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
|
|
54
go.sum
54
go.sum
|
@ -27,8 +27,9 @@ cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSU
|
||||||
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
||||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||||
cloud.google.com/go v0.94.1 h1:DwuSvDZ1pTYGbXo8yOJevCTr3BoBlE+OVkHAKiYQUXc=
|
|
||||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||||
|
cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8=
|
||||||
|
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
@ -127,8 +128,9 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX
|
||||||
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
|
|
||||||
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
|
github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
|
||||||
|
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
|
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
|
||||||
|
@ -252,8 +254,11 @@ github.com/cloudflare/cloudflare-go v0.20.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
||||||
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
|
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
|
||||||
|
@ -326,8 +331,8 @@ github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJ
|
||||||
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
|
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
|
||||||
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.7.0 h1:1d/rydzTywc76lnjJb6qbPCiTiCwts49AzKps/Ecblw=
|
github.com/containerd/stargz-snapshotter/estargz v0.10.0 h1:glqzafvxBBAMo+x2w2sdDjUDZeTqqLJmqZPY05qehCU=
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.7.0/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw=
|
github.com/containerd/stargz-snapshotter/estargz v0.10.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
|
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
|
||||||
|
@ -385,6 +390,7 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1S
|
||||||
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
||||||
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
||||||
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
|
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
|
||||||
|
github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
|
||||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
@ -403,8 +409,9 @@ github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/
|
||||||
github.com/distribution/distribution/v3 v3.0.0-20210804104954-38ab4c606ee3 h1:rEK0juuU5idazw//KzUcL3yYwUU3DIe2OnfJwjDBqno=
|
github.com/distribution/distribution/v3 v3.0.0-20210804104954-38ab4c606ee3 h1:rEK0juuU5idazw//KzUcL3yYwUU3DIe2OnfJwjDBqno=
|
||||||
github.com/distribution/distribution/v3 v3.0.0-20210804104954-38ab4c606ee3/go.mod h1:gt38b7cvVKazi5XkHvINNytZXgTEntyhtyM3HQz46Nk=
|
github.com/distribution/distribution/v3 v3.0.0-20210804104954-38ab4c606ee3/go.mod h1:gt38b7cvVKazi5XkHvINNytZXgTEntyhtyM3HQz46Nk=
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
github.com/docker/cli v20.10.7+incompatible h1:pv/3NqibQKphWZiAskMzdz8w0PRbtTaEB+f6NwdU7Is=
|
|
||||||
github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
|
github.com/docker/cli v20.10.10+incompatible h1:kcbwdgWbrBOH8QwQzaJmyriHwF7XIl4HT1qh0HTRys4=
|
||||||
|
github.com/docker/cli v20.10.10+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||||
|
@ -412,10 +419,11 @@ github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4Kfc
|
||||||
github.com/docker/docker v1.4.2-0.20200319182547-c7ad2b866182/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v1.4.2-0.20200319182547-c7ad2b866182/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v17.12.1-ce+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v17.12.1-ce+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
|
github.com/docker/docker v20.10.10+incompatible h1:GKkP0T7U4ks6X3lmmHKC2QDprnpRJor2Z5a8m62R9ZM=
|
||||||
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
|
|
||||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||||
|
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
|
||||||
|
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||||
|
@ -622,8 +630,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-containerregistry v0.6.0 h1:niQ+8XD//kKgArIFwDVBXsWVWbde16LPdHMyNwSC8h4=
|
github.com/google/go-containerregistry v0.7.0 h1:u0onUUOcyoCDHEiJoyR1R1gx5er1+r06V5DBhUU5ndk=
|
||||||
github.com/google/go-containerregistry v0.6.0/go.mod h1:euCCtNbZ6tKqi1E72vwDj2xZcN5ttKpZLfa/wSo5iLw=
|
github.com/google/go-containerregistry v0.7.0/go.mod h1:2zaoelrL0d08gGbpdP3LqyUuBmhWbpD6IOe2s9nLS2k=
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
|
github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
|
||||||
|
@ -680,8 +688,8 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c
|
||||||
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
||||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||||
github.com/gophercloud/gophercloud v0.23.0 h1:I3P10oKlGu3DHP9PrEWMr1ya+/+3Rc9uRHNkRZ9wO7g=
|
github.com/gophercloud/gophercloud v0.24.0 h1:jDsIMGJ1KZpAjYfQgGI2coNQj5Q83oPzuiGJRFWgMzw=
|
||||||
github.com/gophercloud/gophercloud v0.23.0/go.mod h1:MRw6uyLj8uCGbIvBlqL7QW67t0QtNZnzydUzewo1Ioc=
|
github.com/gophercloud/gophercloud v0.24.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||||
|
@ -689,7 +697,6 @@ github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu
|
||||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||||
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
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/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
|
@ -838,8 +845,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
|
||||||
github.com/klauspost/compress v1.13.0/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
|
||||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
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.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
@ -1017,8 +1022,9 @@ github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/image-spec v1.0.2-0.20210730191737-8e42a01fb1b7 h1:axgApq2XShTLwQii2zAnIkMPlhGVHbAXHUcHezu5G/k=
|
||||||
|
github.com/opencontainers/image-spec v1.0.2-0.20210730191737-8e42a01fb1b7/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
|
@ -1225,8 +1231,11 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
|
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
|
github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=
|
||||||
|
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
|
||||||
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||||
|
@ -1362,6 +1371,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
@ -1468,6 +1478,7 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
@ -1488,8 +1499,9 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ
|
||||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -1618,6 +1630,7 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
@ -1837,8 +1850,10 @@ google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEc
|
||||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e h1:Im71rbA1N3CbIag/PumYhQcNR8bLNmuOtRIyOnnLsT8=
|
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20211111162719-482062a4217b h1:qvEQEwKjZRAg6rjY/jqfJ7T8/w/D7jTIFJGcaSka96k=
|
||||||
|
google.golang.org/genproto v0.0.0-20211111162719-482062a4217b/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
|
@ -1872,8 +1887,9 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
|
||||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E=
|
|
||||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||||
|
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
|
||||||
|
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
|
|
@ -17,7 +17,7 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.94.1 // indirect
|
cloud.google.com/go v0.97.0 // indirect
|
||||||
cloud.google.com/go/storage v1.12.0 // indirect
|
cloud.google.com/go/storage v1.12.0 // indirect
|
||||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||||
github.com/Azure/azure-storage-blob-go v0.13.0 // indirect
|
github.com/Azure/azure-storage-blob-go v0.13.0 // indirect
|
||||||
|
@ -30,10 +30,10 @@ require (
|
||||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b // indirect
|
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b // indirect
|
||||||
github.com/containers/ocicrypt v1.1.1 // indirect
|
github.com/containers/ocicrypt v1.1.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/cli v20.10.7+incompatible // indirect
|
github.com/docker/cli v20.10.10+incompatible // indirect
|
||||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||||
github.com/docker/docker v20.10.7+incompatible // indirect
|
github.com/docker/docker v20.10.10+incompatible // indirect
|
||||||
github.com/docker/docker-credential-helpers v0.6.3 // indirect
|
github.com/docker/docker-credential-helpers v0.6.4 // indirect
|
||||||
github.com/emirpasic/gods v1.12.0 // indirect
|
github.com/emirpasic/gods v1.12.0 // indirect
|
||||||
github.com/fatih/color v1.12.0 // indirect
|
github.com/fatih/color v1.12.0 // indirect
|
||||||
github.com/go-git/gcfg v1.5.0 // indirect
|
github.com/go-git/gcfg v1.5.0 // indirect
|
||||||
|
@ -47,13 +47,13 @@ require (
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/golang/snappy v0.0.3 // indirect
|
github.com/golang/snappy v0.0.3 // indirect
|
||||||
github.com/google/go-cmp v0.5.6 // indirect
|
github.com/google/go-cmp v0.5.6 // indirect
|
||||||
github.com/google/go-containerregistry v0.6.0 // indirect
|
github.com/google/go-containerregistry v0.7.0 // indirect
|
||||||
github.com/google/go-github/v33 v33.0.0 // indirect
|
github.com/google/go-github/v33 v33.0.0 // indirect
|
||||||
github.com/google/go-querystring v1.0.0 // indirect
|
github.com/google/go-querystring v1.0.0 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.1.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.1.0 // indirect
|
||||||
github.com/gophercloud/gophercloud v0.23.0 // indirect
|
github.com/gophercloud/gophercloud v0.24.0 // indirect
|
||||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.0 // indirect
|
github.com/hashicorp/go-multierror v1.1.0 // indirect
|
||||||
|
@ -81,7 +81,7 @@ require (
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.2-0.20200206005212-79b036d80240 // indirect
|
github.com/opencontainers/image-spec v1.0.2-0.20210730191737-8e42a01fb1b7 // indirect
|
||||||
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pkg/sftp v1.13.4 // indirect
|
github.com/pkg/sftp v1.13.4 // indirect
|
||||||
|
@ -96,18 +96,18 @@ require (
|
||||||
go.opencensus.io v0.23.0 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
google.golang.org/api v0.57.0 // indirect
|
google.golang.org/api v0.57.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e // indirect
|
google.golang.org/genproto v0.0.0-20211111162719-482062a4217b // indirect
|
||||||
google.golang.org/grpc v1.41.0 // indirect
|
google.golang.org/grpc v1.42.0 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
|
|
|
@ -37,8 +37,9 @@ cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSU
|
||||||
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
||||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||||
cloud.google.com/go v0.94.1 h1:DwuSvDZ1pTYGbXo8yOJevCTr3BoBlE+OVkHAKiYQUXc=
|
|
||||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||||
|
cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8=
|
||||||
|
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
@ -181,6 +182,7 @@ github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JP
|
||||||
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
|
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
|
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
|
||||||
|
@ -328,8 +330,11 @@ github.com/cloudflare/cloudflare-go v0.20.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
||||||
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
|
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
|
||||||
|
@ -404,8 +409,8 @@ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFY
|
||||||
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.0.0-20201217071531-2b97b583765b/go.mod h1:E9uVkkBKf0EaC39j2JVW9EzdNhYvpz6eQIjILHebruk=
|
github.com/containerd/stargz-snapshotter/estargz v0.0.0-20201217071531-2b97b583765b/go.mod h1:E9uVkkBKf0EaC39j2JVW9EzdNhYvpz6eQIjILHebruk=
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.7.0 h1:1d/rydzTywc76lnjJb6qbPCiTiCwts49AzKps/Ecblw=
|
github.com/containerd/stargz-snapshotter/estargz v0.10.0 h1:glqzafvxBBAMo+x2w2sdDjUDZeTqqLJmqZPY05qehCU=
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.7.0/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw=
|
github.com/containerd/stargz-snapshotter/estargz v0.10.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
|
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
|
||||||
|
@ -469,6 +474,7 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1S
|
||||||
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
||||||
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
||||||
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
|
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
|
||||||
|
github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
|
||||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -491,8 +497,9 @@ github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dteve
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/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/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/cli v20.10.7+incompatible h1:pv/3NqibQKphWZiAskMzdz8w0PRbtTaEB+f6NwdU7Is=
|
|
||||||
github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
|
github.com/docker/cli v20.10.10+incompatible h1:kcbwdgWbrBOH8QwQzaJmyriHwF7XIl4HT1qh0HTRys4=
|
||||||
|
github.com/docker/cli v20.10.10+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||||
github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
|
@ -505,10 +512,11 @@ github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r
|
||||||
github.com/docker/docker v1.4.2-0.20200319182547-c7ad2b866182/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v1.4.2-0.20200319182547-c7ad2b866182/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v17.12.1-ce+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v17.12.1-ce+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
|
github.com/docker/docker v20.10.10+incompatible h1:GKkP0T7U4ks6X3lmmHKC2QDprnpRJor2Z5a8m62R9ZM=
|
||||||
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
|
|
||||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||||
|
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
|
||||||
|
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||||
|
@ -785,8 +793,8 @@ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-containerregistry v0.0.0-20200115214256-379933c9c22b/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs=
|
github.com/google/go-containerregistry v0.0.0-20200115214256-379933c9c22b/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs=
|
||||||
github.com/google/go-containerregistry v0.3.0/go.mod h1:BJ7VxR1hAhdiZBGGnvGETHEmFs1hzXc4VM1xjOPO9wA=
|
github.com/google/go-containerregistry v0.3.0/go.mod h1:BJ7VxR1hAhdiZBGGnvGETHEmFs1hzXc4VM1xjOPO9wA=
|
||||||
github.com/google/go-containerregistry v0.6.0 h1:niQ+8XD//kKgArIFwDVBXsWVWbde16LPdHMyNwSC8h4=
|
github.com/google/go-containerregistry v0.7.0 h1:u0onUUOcyoCDHEiJoyR1R1gx5er1+r06V5DBhUU5ndk=
|
||||||
github.com/google/go-containerregistry v0.6.0/go.mod h1:euCCtNbZ6tKqi1E72vwDj2xZcN5ttKpZLfa/wSo5iLw=
|
github.com/google/go-containerregistry v0.7.0/go.mod h1:2zaoelrL0d08gGbpdP3LqyUuBmhWbpD6IOe2s9nLS2k=
|
||||||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
github.com/google/go-github/v29 v29.0.3/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E=
|
github.com/google/go-github/v29 v29.0.3/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E=
|
||||||
|
@ -864,8 +872,8 @@ github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3i
|
||||||
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
||||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||||
github.com/gophercloud/gophercloud v0.23.0 h1:I3P10oKlGu3DHP9PrEWMr1ya+/+3Rc9uRHNkRZ9wO7g=
|
github.com/gophercloud/gophercloud v0.24.0 h1:jDsIMGJ1KZpAjYfQgGI2coNQj5Q83oPzuiGJRFWgMzw=
|
||||||
github.com/gophercloud/gophercloud v0.23.0/go.mod h1:MRw6uyLj8uCGbIvBlqL7QW67t0QtNZnzydUzewo1Ioc=
|
github.com/gophercloud/gophercloud v0.24.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||||
|
@ -1051,8 +1059,6 @@ github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
||||||
github.com/klauspost/compress v1.11.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
|
||||||
github.com/klauspost/compress v1.13.0/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
|
||||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
|
@ -1275,8 +1281,9 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I
|
||||||
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.2-0.20200206005212-79b036d80240 h1:SCj6omNRmcflKljYD2u38p+NMOHylupEMEpt3OfsF8g=
|
|
||||||
github.com/opencontainers/image-spec v1.0.2-0.20200206005212-79b036d80240/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2-0.20200206005212-79b036d80240/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/image-spec v1.0.2-0.20210730191737-8e42a01fb1b7 h1:axgApq2XShTLwQii2zAnIkMPlhGVHbAXHUcHezu5G/k=
|
||||||
|
github.com/opencontainers/image-spec v1.0.2-0.20210730191737-8e42a01fb1b7/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
|
@ -1541,6 +1548,7 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
|
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||||
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
|
@ -1550,6 +1558,8 @@ github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk
|
||||||
github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
|
github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
|
||||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||||
github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g=
|
github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g=
|
||||||
|
github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=
|
||||||
|
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
|
||||||
github.com/vbauerster/mpb/v5 v5.3.0/go.mod h1:4yTkvAb8Cm4eylAp6t0JRq6pXDkFJ4krUlDqWYkakAs=
|
github.com/vbauerster/mpb/v5 v5.3.0/go.mod h1:4yTkvAb8Cm4eylAp6t0JRq6pXDkFJ4krUlDqWYkakAs=
|
||||||
github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo=
|
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/vdemeester/k8s-pkg-credentialprovider v1.13.12-1/go.mod h1:Fko0rTxEtDW2kju5Ky7yFJNS3IcNvW8IPsp4/e9oev0=
|
||||||
|
@ -1701,6 +1711,7 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
@ -1818,6 +1829,7 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
@ -1840,8 +1852,9 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ
|
||||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -1983,6 +1996,7 @@ golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
@ -2261,8 +2275,10 @@ google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEc
|
||||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e h1:Im71rbA1N3CbIag/PumYhQcNR8bLNmuOtRIyOnnLsT8=
|
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20211111162719-482062a4217b h1:qvEQEwKjZRAg6rjY/jqfJ7T8/w/D7jTIFJGcaSka96k=
|
||||||
|
google.golang.org/genproto v0.0.0-20211111162719-482062a4217b/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
|
@ -2301,8 +2317,9 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
|
||||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E=
|
|
||||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||||
|
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
|
||||||
|
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
|
|
@ -10,5 +10,4 @@ go_library(
|
||||||
importmap = "k8s.io/kops/vendor/cloud.google.com/go/compute/metadata",
|
importmap = "k8s.io/kops/vendor/cloud.google.com/go/compute/metadata",
|
||||||
importpath = "cloud.google.com/go/compute/metadata",
|
importpath = "cloud.google.com/go/compute/metadata",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = ["//vendor/github.com/googleapis/gax-go/v2:go_default_library"],
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -32,8 +32,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/googleapis/gax-go/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -317,7 +315,7 @@ func (c *Client) getETag(suffix string) (value, etag string, err error) {
|
||||||
code = res.StatusCode
|
code = res.StatusCode
|
||||||
}
|
}
|
||||||
if delay, shouldRetry := retryer.Retry(code, reqErr); shouldRetry {
|
if delay, shouldRetry := retryer.Retry(code, reqErr); shouldRetry {
|
||||||
if err := gax.Sleep(ctx, delay); err != nil {
|
if err := sleep(ctx, delay); err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
package metadata
|
package metadata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/googleapis/gax-go/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -30,8 +30,41 @@ var (
|
||||||
syscallRetryable = func(err error) bool { return false }
|
syscallRetryable = func(err error) bool { return false }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// defaultBackoff is basically equivalent to gax.Backoff without the need for
|
||||||
|
// the dependency.
|
||||||
|
type defaultBackoff struct {
|
||||||
|
max time.Duration
|
||||||
|
mul float64
|
||||||
|
cur time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *defaultBackoff) Pause() time.Duration {
|
||||||
|
d := time.Duration(1 + rand.Int63n(int64(b.cur)))
|
||||||
|
b.cur = time.Duration(float64(b.cur) * b.mul)
|
||||||
|
if b.cur > b.max {
|
||||||
|
b.cur = b.max
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// sleep is the equivalent of gax.Sleep without the need for the dependency.
|
||||||
|
func sleep(ctx context.Context, d time.Duration) error {
|
||||||
|
t := time.NewTimer(d)
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
t.Stop()
|
||||||
|
return ctx.Err()
|
||||||
|
case <-t.C:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newRetryer() *metadataRetryer {
|
func newRetryer() *metadataRetryer {
|
||||||
return &metadataRetryer{bo: &gax.Backoff{Initial: 100 * time.Millisecond}}
|
return &metadataRetryer{bo: &defaultBackoff{
|
||||||
|
cur: 100 * time.Millisecond,
|
||||||
|
max: 30 * time.Second,
|
||||||
|
mul: 2,
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
type backoff interface {
|
type backoff interface {
|
||||||
|
|
|
@ -9,5 +9,8 @@ go_library(
|
||||||
importmap = "k8s.io/kops/vendor/github.com/docker/docker-credential-helpers/client",
|
importmap = "k8s.io/kops/vendor/github.com/docker/docker-credential-helpers/client",
|
||||||
importpath = "github.com/docker/docker-credential-helpers/client",
|
importpath = "github.com/docker/docker-credential-helpers/client",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = ["//vendor/github.com/docker/docker-credential-helpers/credentials:go_default_library"],
|
deps = [
|
||||||
|
"//vendor/github.com/docker/docker-credential-helpers/credentials:go_default_library",
|
||||||
|
"//vendor/golang.org/x/sys/execabs:go_default_library",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
|
exec "golang.org/x/sys/execabs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Program is an interface to execute external programs.
|
// Program is an interface to execute external programs.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package credentials
|
package credentials
|
||||||
|
|
||||||
// Version holds a string describing the current version
|
// Version holds a string describing the current version
|
||||||
const Version = "0.6.3"
|
const Version = "0.6.4"
|
||||||
|
|
|
@ -35,9 +35,9 @@ func stripRunesFn(runes string) func(rune) rune {
|
||||||
func checkElement(name, element, allowedRunes string, minRunes, maxRunes int) error {
|
func checkElement(name, element, allowedRunes string, minRunes, maxRunes int) error {
|
||||||
numRunes := utf8.RuneCountInString(element)
|
numRunes := utf8.RuneCountInString(element)
|
||||||
if (numRunes < minRunes) || (maxRunes < numRunes) {
|
if (numRunes < minRunes) || (maxRunes < numRunes) {
|
||||||
return NewErrBadName("%s must be between %d and %d runes in length: %s", name, minRunes, maxRunes, element)
|
return newErrBadName("%s must be between %d and %d runes in length: %s", name, minRunes, maxRunes, element)
|
||||||
} else if len(strings.Map(stripRunesFn(allowedRunes), element)) != 0 {
|
} else if len(strings.Map(stripRunesFn(allowedRunes), element)) != 0 {
|
||||||
return NewErrBadName("%s can only contain the runes `%s`: %s", name, allowedRunes, element)
|
return newErrBadName("%s can only contain the runes `%s`: %s", name, allowedRunes, element)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ func NewDigest(name string, opts ...Option) (Digest, error) {
|
||||||
// Split on "@"
|
// Split on "@"
|
||||||
parts := strings.Split(name, digestDelim)
|
parts := strings.Split(name, digestDelim)
|
||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
return Digest{}, NewErrBadName("a digest must contain exactly one '@' separator (e.g. registry/repository@digest) saw: %s", name)
|
return Digest{}, newErrBadName("a digest must contain exactly one '@' separator (e.g. registry/repository@digest) saw: %s", name)
|
||||||
}
|
}
|
||||||
base := parts[0]
|
base := parts[0]
|
||||||
digest := parts[1]
|
digest := parts[1]
|
||||||
|
|
|
@ -14,7 +14,10 @@
|
||||||
|
|
||||||
package name
|
package name
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
// ErrBadName is an error for when a bad docker name is supplied.
|
// ErrBadName is an error for when a bad docker name is supplied.
|
||||||
type ErrBadName struct {
|
type ErrBadName struct {
|
||||||
|
@ -25,13 +28,15 @@ func (e *ErrBadName) Error() string {
|
||||||
return e.info
|
return e.info
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewErrBadName returns a ErrBadName which returns the given formatted string from Error().
|
// newErrBadName returns a ErrBadName which returns the given formatted string from Error().
|
||||||
func NewErrBadName(fmtStr string, args ...interface{}) *ErrBadName {
|
func newErrBadName(fmtStr string, args ...interface{}) *ErrBadName {
|
||||||
return &ErrBadName{fmt.Sprintf(fmtStr, args...)}
|
return &ErrBadName{fmt.Sprintf(fmtStr, args...)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrBadName returns true if the given error is an ErrBadName.
|
// IsErrBadName returns true if the given error is an ErrBadName.
|
||||||
|
//
|
||||||
|
// Deprecated: Use errors.Is.
|
||||||
func IsErrBadName(err error) bool {
|
func IsErrBadName(err error) bool {
|
||||||
_, ok := err.(*ErrBadName)
|
var berr *ErrBadName
|
||||||
return ok
|
return errors.As(err, &berr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,7 @@ func ParseReference(s string, opts ...Option) (Reference, error) {
|
||||||
if d, err := NewDigest(s, opts...); err == nil {
|
if d, err := NewDigest(s, opts...); err == nil {
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
return nil, NewErrBadName("could not parse reference: " + s)
|
return nil, newErrBadName("could not parse reference: " + s)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type stringConst string
|
type stringConst string
|
||||||
|
|
|
@ -98,7 +98,7 @@ func checkRegistry(name string) error {
|
||||||
// Per RFC 3986, registries (authorities) are required to be prefixed with "//"
|
// Per RFC 3986, registries (authorities) are required to be prefixed with "//"
|
||||||
// url.Host == hostname[:port] == authority
|
// url.Host == hostname[:port] == authority
|
||||||
if url, err := url.Parse("//" + name); err != nil || url.Host != name {
|
if url, err := url.Parse("//" + name); err != nil || url.Host != name {
|
||||||
return NewErrBadName("registries must be valid RFC 3986 URI authorities: %s", name)
|
return newErrBadName("registries must be valid RFC 3986 URI authorities: %s", name)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ func checkRegistry(name string) error {
|
||||||
func NewRegistry(name string, opts ...Option) (Registry, error) {
|
func NewRegistry(name string, opts ...Option) (Registry, error) {
|
||||||
opt := makeOptions(opts...)
|
opt := makeOptions(opts...)
|
||||||
if opt.strict && len(name) == 0 {
|
if opt.strict && len(name) == 0 {
|
||||||
return Registry{}, NewErrBadName("strict validation requires the registry to be explicitly defined")
|
return Registry{}, newErrBadName("strict validation requires the registry to be explicitly defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkRegistry(name); err != nil {
|
if err := checkRegistry(name); err != nil {
|
||||||
|
|
|
@ -72,7 +72,7 @@ func checkRepository(repository string) error {
|
||||||
func NewRepository(name string, opts ...Option) (Repository, error) {
|
func NewRepository(name string, opts ...Option) (Repository, error) {
|
||||||
opt := makeOptions(opts...)
|
opt := makeOptions(opts...)
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
return Repository{}, NewErrBadName("a repository name must be specified")
|
return Repository{}, newErrBadName("a repository name must be specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
var registry string
|
var registry string
|
||||||
|
@ -95,7 +95,7 @@ func NewRepository(name string, opts ...Option) (Repository, error) {
|
||||||
return Repository{}, err
|
return Repository{}, err
|
||||||
}
|
}
|
||||||
if hasImplicitNamespace(repo, reg) && opt.strict {
|
if hasImplicitNamespace(repo, reg) && opt.strict {
|
||||||
return Repository{}, NewErrBadName("strict validation requires the full repository path (missing 'library')")
|
return Repository{}, newErrBadName("strict validation requires the full repository path (missing 'library')")
|
||||||
}
|
}
|
||||||
return Repository{reg, repo}, nil
|
return Repository{reg, repo}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ In a tarball, blobs are (often) uncompressed, so it's easiest to implement a `v1
|
||||||
of uncompressed layers. `tarball.uncompressedImage` does this by implementing `UncompressedImageCore`:
|
of uncompressed layers. `tarball.uncompressedImage` does this by implementing `UncompressedImageCore`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type CompressedImageCore interface {
|
type UncompressedImageCore interface {
|
||||||
RawConfigFile() ([]byte, error)
|
RawConfigFile() ([]byte, error)
|
||||||
MediaType() (types.MediaType, error)
|
MediaType() (types.MediaType, error)
|
||||||
LayerByDiffID(v1.Hash) (UncompressedLayer, error)
|
LayerByDiffID(v1.Hash) (UncompressedLayer, error)
|
||||||
|
|
|
@ -26,7 +26,7 @@ func FindManifests(index v1.ImageIndex, matcher match.Matcher) ([]v1.Descriptor,
|
||||||
// get the actual manifest list
|
// get the actual manifest list
|
||||||
indexManifest, err := index.IndexManifest()
|
indexManifest, err := index.IndexManifest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to get raw index: %v", err)
|
return nil, fmt.Errorf("unable to get raw index: %w", err)
|
||||||
}
|
}
|
||||||
manifests := []v1.Descriptor{}
|
manifests := []v1.Descriptor{}
|
||||||
// try to get the root of our image
|
// try to get the root of our image
|
||||||
|
|
|
@ -50,10 +50,9 @@ func stringSliceEqual(a, b []string) bool {
|
||||||
|
|
||||||
// stringSliceEqualIgnoreOrder compares 2 string slices and returns if their contents are identical, ignoring order
|
// stringSliceEqualIgnoreOrder compares 2 string slices and returns if their contents are identical, ignoring order
|
||||||
func stringSliceEqualIgnoreOrder(a, b []string) bool {
|
func stringSliceEqualIgnoreOrder(a, b []string) bool {
|
||||||
a1, b1 := a[:], b[:]
|
if a != nil && b != nil {
|
||||||
if a1 != nil && b1 != nil {
|
sort.Strings(a)
|
||||||
sort.Strings(a1)
|
sort.Strings(b)
|
||||||
sort.Strings(b1)
|
|
||||||
}
|
}
|
||||||
return stringSliceEqual(a1, b1)
|
return stringSliceEqual(a, b)
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,9 +91,10 @@ func Catalog(ctx context.Context, target name.Registry, options ...Option) ([]st
|
||||||
Scheme: target.Scheme(),
|
Scheme: target.Scheme(),
|
||||||
Host: target.RegistryStr(),
|
Host: target.RegistryStr(),
|
||||||
Path: "/v2/_catalog",
|
Path: "/v2/_catalog",
|
||||||
// ECR returns an error if n > 1000:
|
}
|
||||||
// https://github.com/google/go-containerregistry/issues/1091
|
|
||||||
RawQuery: "n=1000",
|
if o.pageSize > 0 {
|
||||||
|
uri.RawQuery = fmt.Sprintf("n=%d", o.pageSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := http.Client{Transport: tr}
|
client := http.Client{Transport: tr}
|
||||||
|
|
|
@ -20,13 +20,13 @@ import (
|
||||||
func CheckPushPermission(ref name.Reference, kc authn.Keychain, t http.RoundTripper) error {
|
func CheckPushPermission(ref name.Reference, kc authn.Keychain, t http.RoundTripper) error {
|
||||||
auth, err := kc.Resolve(ref.Context().Registry)
|
auth, err := kc.Resolve(ref.Context().Registry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("resolving authorization for %v failed: %v", ref.Context().Registry, err)
|
return fmt.Errorf("resolving authorization for %v failed: %w", ref.Context().Registry, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
scopes := []string{ref.Scope(transport.PushScope)}
|
scopes := []string{ref.Scope(transport.PushScope)}
|
||||||
tr, err := transport.New(ref.Context().Registry, auth, t, scopes)
|
tr, err := transport.New(ref.Context().Registry, auth, t, scopes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating push check transport for %v failed: %v", ref.Context().Registry, err)
|
return fmt.Errorf("creating push check transport for %v failed: %w", ref.Context().Registry, err)
|
||||||
}
|
}
|
||||||
// TODO(jasonhall): Against GCR, just doing the token handshake is
|
// TODO(jasonhall): Against GCR, just doing the token handshake is
|
||||||
// enough, but this doesn't extend to Dockerhub
|
// enough, but this doesn't extend to Dockerhub
|
||||||
|
|
|
@ -147,6 +147,40 @@ func (r *remoteIndex) Layer(h v1.Hash) (v1.Layer, error) {
|
||||||
return nil, fmt.Errorf("layer not found: %s", h)
|
return nil, fmt.Errorf("layer not found: %s", h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Experiment with a better API for v1.ImageIndex. We might want to move this
|
||||||
|
// to partial?
|
||||||
|
func (r *remoteIndex) Manifests() ([]partial.Describable, error) {
|
||||||
|
m, err := r.IndexManifest()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
manifests := []partial.Describable{}
|
||||||
|
for _, desc := range m.Manifests {
|
||||||
|
switch {
|
||||||
|
case desc.MediaType.IsImage():
|
||||||
|
img, err := r.Image(desc.Digest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
manifests = append(manifests, img)
|
||||||
|
case desc.MediaType.IsIndex():
|
||||||
|
idx, err := r.ImageIndex(desc.Digest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
manifests = append(manifests, idx)
|
||||||
|
default:
|
||||||
|
layer, err := r.Layer(desc.Digest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
manifests = append(manifests, layer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return manifests, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *remoteIndex) imageByPlatform(platform v1.Platform) (v1.Image, error) {
|
func (r *remoteIndex) imageByPlatform(platform v1.Platform) (v1.Image, error) {
|
||||||
desc, err := r.childByPlatform(platform)
|
desc, err := r.childByPlatform(platform)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -180,7 +214,7 @@ func (r *remoteIndex) childByPlatform(platform v1.Platform) (*Descriptor, error)
|
||||||
return r.childDescriptor(childDesc, platform)
|
return r.childDescriptor(childDesc, platform)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("no child with platform %s/%s in index %s", platform.OS, platform.Architecture, r.Ref)
|
return nil, fmt.Errorf("no child with platform %+v in index %s", platform, r.Ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteIndex) childByHash(h v1.Hash) (*Descriptor, error) {
|
func (r *remoteIndex) childByHash(h v1.Hash) (*Descriptor, error) {
|
||||||
|
|
|
@ -55,9 +55,10 @@ func List(repo name.Repository, options ...Option) ([]string, error) {
|
||||||
Scheme: repo.Registry.Scheme(),
|
Scheme: repo.Registry.Scheme(),
|
||||||
Host: repo.Registry.RegistryStr(),
|
Host: repo.Registry.RegistryStr(),
|
||||||
Path: fmt.Sprintf("/v2/%s/tags/list", repo.RepositoryStr()),
|
Path: fmt.Sprintf("/v2/%s/tags/list", repo.RepositoryStr()),
|
||||||
// ECR returns an error if n > 1000:
|
}
|
||||||
// https://github.com/google/go-containerregistry/issues/681
|
|
||||||
RawQuery: "n=1000",
|
if o.pageSize > 0 {
|
||||||
|
uri.RawQuery = fmt.Sprintf("n=%d", o.pageSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := http.Client{Transport: tr}
|
client := http.Client{Transport: tr}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package remote
|
package remote
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -91,12 +92,14 @@ func MultiWrite(m map[name.Reference]Taggable, options ...Option) (rerr error) {
|
||||||
context: o.context,
|
context: o.context,
|
||||||
updates: o.updates,
|
updates: o.updates,
|
||||||
lastUpdate: &v1.Update{},
|
lastUpdate: &v1.Update{},
|
||||||
|
backoff: o.retryBackoff,
|
||||||
|
predicate: o.retryPredicate,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect the total size of blobs and manifests we're about to write.
|
// Collect the total size of blobs and manifests we're about to write.
|
||||||
if o.updates != nil {
|
if o.updates != nil {
|
||||||
defer close(o.updates)
|
defer close(o.updates)
|
||||||
defer func() { sendError(o.updates, rerr) }()
|
defer func() { _ = sendError(o.updates, rerr) }()
|
||||||
for _, b := range blobs {
|
for _, b := range blobs {
|
||||||
size, err := b.Size()
|
size, err := b.Size()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -133,12 +136,13 @@ func MultiWrite(m map[name.Reference]Taggable, options ...Option) (rerr error) {
|
||||||
|
|
||||||
// Upload individual blobs and collect any errors.
|
// Upload individual blobs and collect any errors.
|
||||||
blobChan := make(chan v1.Layer, 2*o.jobs)
|
blobChan := make(chan v1.Layer, 2*o.jobs)
|
||||||
g, ctx := errgroup.WithContext(o.context)
|
ctx := o.context
|
||||||
|
g, gctx := errgroup.WithContext(o.context)
|
||||||
for i := 0; i < o.jobs; i++ {
|
for i := 0; i < o.jobs; i++ {
|
||||||
// Start N workers consuming blobs to upload.
|
// Start N workers consuming blobs to upload.
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
for b := range blobChan {
|
for b := range blobChan {
|
||||||
if err := w.uploadOne(b); err != nil {
|
if err := w.uploadOne(gctx, b); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,8 +154,8 @@ func MultiWrite(m map[name.Reference]Taggable, options ...Option) (rerr error) {
|
||||||
for _, b := range blobs {
|
for _, b := range blobs {
|
||||||
select {
|
select {
|
||||||
case blobChan <- b:
|
case blobChan <- b:
|
||||||
case <-ctx.Done():
|
case <-gctx.Done():
|
||||||
return ctx.Err()
|
return gctx.Err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -160,7 +164,8 @@ func MultiWrite(m map[name.Reference]Taggable, options ...Option) (rerr error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
commitMany := func(m map[name.Reference]Taggable) error {
|
commitMany := func(ctx context.Context, m map[name.Reference]Taggable) error {
|
||||||
|
g, ctx := errgroup.WithContext(ctx)
|
||||||
// With all of the constituent elements uploaded, upload the manifests
|
// With all of the constituent elements uploaded, upload the manifests
|
||||||
// to commit the images and indexes, and collect any errors.
|
// to commit the images and indexes, and collect any errors.
|
||||||
type task struct {
|
type task struct {
|
||||||
|
@ -172,7 +177,7 @@ func MultiWrite(m map[name.Reference]Taggable, options ...Option) (rerr error) {
|
||||||
// Start N workers consuming tasks to upload manifests.
|
// Start N workers consuming tasks to upload manifests.
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
for t := range taskChan {
|
for t := range taskChan {
|
||||||
if err := w.commitManifest(t.i, t.ref); err != nil {
|
if err := w.commitManifest(ctx, t.i, t.ref); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,19 +194,19 @@ func MultiWrite(m map[name.Reference]Taggable, options ...Option) (rerr error) {
|
||||||
}
|
}
|
||||||
// Push originally requested image manifests. These have no
|
// Push originally requested image manifests. These have no
|
||||||
// dependencies.
|
// dependencies.
|
||||||
if err := commitMany(images); err != nil {
|
if err := commitMany(ctx, images); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Push new manifests from lowest levels up.
|
// Push new manifests from lowest levels up.
|
||||||
for i := len(newManifests) - 1; i >= 0; i-- {
|
for i := len(newManifests) - 1; i >= 0; i-- {
|
||||||
if err := commitMany(newManifests[i]); err != nil {
|
if err := commitMany(ctx, newManifests[i]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Push originally requested index manifests, which might depend on
|
// Push originally requested index manifests, which might depend on
|
||||||
// newly discovered manifests.
|
// newly discovered manifests.
|
||||||
|
|
||||||
return commitMany(indexes)
|
return commitMany(ctx, indexes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// addIndexBlobs adds blobs to the set of blobs we intend to upload, and
|
// addIndexBlobs adds blobs to the set of blobs we intend to upload, and
|
||||||
|
|
|
@ -17,8 +17,13 @@ package remote
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-containerregistry/internal/retry"
|
||||||
"github.com/google/go-containerregistry/pkg/authn"
|
"github.com/google/go-containerregistry/pkg/authn"
|
||||||
"github.com/google/go-containerregistry/pkg/logs"
|
"github.com/google/go-containerregistry/pkg/logs"
|
||||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||||
|
@ -38,6 +43,9 @@ type options struct {
|
||||||
userAgent string
|
userAgent string
|
||||||
allowNondistributableArtifacts bool
|
allowNondistributableArtifacts bool
|
||||||
updates chan<- v1.Update
|
updates chan<- v1.Update
|
||||||
|
pageSize int
|
||||||
|
retryBackoff Backoff
|
||||||
|
retryPredicate retry.Predicate
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultPlatform = v1.Platform{
|
var defaultPlatform = v1.Platform{
|
||||||
|
@ -45,15 +53,63 @@ var defaultPlatform = v1.Platform{
|
||||||
OS: "linux",
|
OS: "linux",
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultJobs = 4
|
// Backoff is an alias of retry.Backoff to expose this configuration option to consumers of this lib
|
||||||
|
type Backoff = retry.Backoff
|
||||||
|
|
||||||
|
var defaultRetryPredicate retry.Predicate = func(err error) bool {
|
||||||
|
// Various failure modes here, as we're often reading from and writing to
|
||||||
|
// the network.
|
||||||
|
if retry.IsTemporary(err) || errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, syscall.EPIPE) {
|
||||||
|
logs.Warn.Printf("retrying %v", err)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try this three times, waiting 1s after first failure, 3s after second.
|
||||||
|
var defaultRetryBackoff = Backoff{
|
||||||
|
Duration: 1.0 * time.Second,
|
||||||
|
Factor: 3.0,
|
||||||
|
Jitter: 0.1,
|
||||||
|
Steps: 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultJobs = 4
|
||||||
|
|
||||||
|
// ECR returns an error if n > 1000:
|
||||||
|
// https://github.com/google/go-containerregistry/issues/1091
|
||||||
|
defaultPageSize = 1000
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultTransport is based on http.DefaultTransport with modifications
|
||||||
|
// documented inline below.
|
||||||
|
var DefaultTransport = &http.Transport{
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
DialContext: (&net.Dialer{
|
||||||
|
// By default we wrap the transport in retries, so reduce the
|
||||||
|
// default dial timeout to 5s to avoid 5x 30s of connection
|
||||||
|
// timeouts when doing the "ping" on certain http registries.
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
}).DialContext,
|
||||||
|
ForceAttemptHTTP2: true,
|
||||||
|
MaxIdleConns: 100,
|
||||||
|
IdleConnTimeout: 90 * time.Second,
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
func makeOptions(target authn.Resource, opts ...Option) (*options, error) {
|
func makeOptions(target authn.Resource, opts ...Option) (*options, error) {
|
||||||
o := &options{
|
o := &options{
|
||||||
auth: authn.Anonymous,
|
auth: authn.Anonymous,
|
||||||
transport: http.DefaultTransport,
|
transport: DefaultTransport,
|
||||||
platform: defaultPlatform,
|
platform: defaultPlatform,
|
||||||
context: context.Background(),
|
context: context.Background(),
|
||||||
jobs: defaultJobs,
|
jobs: defaultJobs,
|
||||||
|
pageSize: defaultPageSize,
|
||||||
|
retryPredicate: defaultRetryPredicate,
|
||||||
|
retryBackoff: defaultRetryBackoff,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, option := range opts {
|
for _, option := range opts {
|
||||||
|
@ -70,19 +126,23 @@ func makeOptions(target authn.Resource, opts ...Option) (*options, error) {
|
||||||
o.auth = auth
|
o.auth = auth
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the transport in something that logs requests and responses.
|
// transport.Wrapper is a signal that consumers are opt-ing into providing their own transport without any additional wrapping.
|
||||||
// It's expensive to generate the dumps, so skip it if we're writing
|
// This is to allow consumers full control over the transports logic, such as providing retry logic.
|
||||||
// to nothing.
|
if _, ok := o.transport.(*transport.Wrapper); !ok {
|
||||||
if logs.Enabled(logs.Debug) {
|
// Wrap the transport in something that logs requests and responses.
|
||||||
o.transport = transport.NewLogger(o.transport)
|
// It's expensive to generate the dumps, so skip it if we're writing
|
||||||
}
|
// to nothing.
|
||||||
|
if logs.Enabled(logs.Debug) {
|
||||||
|
o.transport = transport.NewLogger(o.transport)
|
||||||
|
}
|
||||||
|
|
||||||
// Wrap the transport in something that can retry network flakes.
|
// Wrap the transport in something that can retry network flakes.
|
||||||
o.transport = transport.NewRetry(o.transport)
|
o.transport = transport.NewRetry(o.transport)
|
||||||
|
|
||||||
// Wrap this last to prevent transport.New from double-wrapping.
|
// Wrap this last to prevent transport.New from double-wrapping.
|
||||||
if o.userAgent != "" {
|
if o.userAgent != "" {
|
||||||
o.transport = transport.NewUserAgent(o.transport, o.userAgent)
|
o.transport = transport.NewUserAgent(o.transport, o.userAgent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return o, nil
|
return o, nil
|
||||||
|
@ -90,8 +150,10 @@ func makeOptions(target authn.Resource, opts ...Option) (*options, error) {
|
||||||
|
|
||||||
// WithTransport is a functional option for overriding the default transport
|
// WithTransport is a functional option for overriding the default transport
|
||||||
// for remote operations.
|
// for remote operations.
|
||||||
|
// If transport.Wrapper is provided, this signals that the consumer does *not* want any further wrapping to occur.
|
||||||
|
// i.e. logging, retry and useragent
|
||||||
//
|
//
|
||||||
// The default transport its http.DefaultTransport.
|
// The default transport is DefaultTransport.
|
||||||
func WithTransport(t http.RoundTripper) Option {
|
func WithTransport(t http.RoundTripper) Option {
|
||||||
return func(o *options) error {
|
return func(o *options) error {
|
||||||
o.transport = t
|
o.transport = t
|
||||||
|
@ -193,3 +255,30 @@ func WithProgress(updates chan<- v1.Update) Option {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithPageSize sets the given size as the value of parameter 'n' in the request.
|
||||||
|
//
|
||||||
|
// To omit the `n` parameter entirely, use WithPageSize(0).
|
||||||
|
// The default value is 1000.
|
||||||
|
func WithPageSize(size int) Option {
|
||||||
|
return func(o *options) error {
|
||||||
|
o.pageSize = size
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithRetryBackoff sets the httpBackoff for retry HTTP operations.
|
||||||
|
func WithRetryBackoff(backoff Backoff) Option {
|
||||||
|
return func(o *options) error {
|
||||||
|
o.retryBackoff = backoff
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithRetryPredicate sets the predicate for retry HTTP operations.
|
||||||
|
func WithRetryPredicate(predicate retry.Predicate) Option {
|
||||||
|
return func(o *options) error {
|
||||||
|
o.retryPredicate = predicate
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
4
vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go
generated
vendored
4
vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go
generated
vendored
|
@ -17,6 +17,7 @@ package transport
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
@ -139,7 +140,8 @@ func (bt *bearerTransport) refresh(ctx context.Context) error {
|
||||||
// the Username should be set to <token>, which indicates
|
// the Username should be set to <token>, which indicates
|
||||||
// we are using an oauth flow.
|
// we are using an oauth flow.
|
||||||
content, err = bt.refreshOauth(ctx)
|
content, err = bt.refreshOauth(ctx)
|
||||||
if terr, ok := err.(*Error); ok && terr.StatusCode == http.StatusNotFound {
|
var terr *Error
|
||||||
|
if errors.As(err, &terr) && terr.StatusCode == http.StatusNotFound {
|
||||||
// Note: Not all token servers implement oauth2.
|
// Note: Not all token servers implement oauth2.
|
||||||
// If the request to the endpoint returns 404 using the HTTP POST method,
|
// If the request to the endpoint returns 404 using the HTTP POST method,
|
||||||
// refer to Token Documentation for using the HTTP GET method supported by all token servers.
|
// refer to Token Documentation for using the HTTP GET method supported by all token servers.
|
||||||
|
|
15
vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/error.go
generated
vendored
15
vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/error.go
generated
vendored
|
@ -46,10 +46,10 @@ type Error struct {
|
||||||
Errors []Diagnostic `json:"errors,omitempty"`
|
Errors []Diagnostic `json:"errors,omitempty"`
|
||||||
// The http status code returned.
|
// The http status code returned.
|
||||||
StatusCode int
|
StatusCode int
|
||||||
|
// The request that failed.
|
||||||
|
Request *http.Request
|
||||||
// The raw body if we couldn't understand it.
|
// The raw body if we couldn't understand it.
|
||||||
rawBody string
|
rawBody string
|
||||||
// The request that failed.
|
|
||||||
request *http.Request
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that Error implements error
|
// Check that Error implements error
|
||||||
|
@ -58,8 +58,8 @@ var _ error = (*Error)(nil)
|
||||||
// Error implements error
|
// Error implements error
|
||||||
func (e *Error) Error() string {
|
func (e *Error) Error() string {
|
||||||
prefix := ""
|
prefix := ""
|
||||||
if e.request != nil {
|
if e.Request != nil {
|
||||||
prefix = fmt.Sprintf("%s %s: ", e.request.Method, redactURL(e.request.URL))
|
prefix = fmt.Sprintf("%s %s: ", e.Request.Method, redactURL(e.Request.URL))
|
||||||
}
|
}
|
||||||
return prefix + e.responseErr()
|
return prefix + e.responseErr()
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ func (e *Error) responseErr() string {
|
||||||
switch len(e.Errors) {
|
switch len(e.Errors) {
|
||||||
case 0:
|
case 0:
|
||||||
if len(e.rawBody) == 0 {
|
if len(e.rawBody) == 0 {
|
||||||
if e.request != nil && e.request.Method == http.MethodHead {
|
if e.Request != nil && e.Request.Method == http.MethodHead {
|
||||||
return fmt.Sprintf("unexpected status code %d %s (HEAD responses have no body, use GET for details)", e.StatusCode, http.StatusText(e.StatusCode))
|
return fmt.Sprintf("unexpected status code %d %s (HEAD responses have no body, use GET for details)", e.StatusCode, http.StatusText(e.StatusCode))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("unexpected status code %d %s", e.StatusCode, http.StatusText(e.StatusCode))
|
return fmt.Sprintf("unexpected status code %d %s", e.StatusCode, http.StatusText(e.StatusCode))
|
||||||
|
@ -154,12 +154,14 @@ const (
|
||||||
DeniedErrorCode ErrorCode = "DENIED"
|
DeniedErrorCode ErrorCode = "DENIED"
|
||||||
UnsupportedErrorCode ErrorCode = "UNSUPPORTED"
|
UnsupportedErrorCode ErrorCode = "UNSUPPORTED"
|
||||||
TooManyRequestsErrorCode ErrorCode = "TOOMANYREQUESTS"
|
TooManyRequestsErrorCode ErrorCode = "TOOMANYREQUESTS"
|
||||||
|
UnknownErrorCode ErrorCode = "UNKNOWN"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Include other error types.
|
// TODO: Include other error types.
|
||||||
var temporaryErrorCodes = map[ErrorCode]struct{}{
|
var temporaryErrorCodes = map[ErrorCode]struct{}{
|
||||||
BlobUploadInvalidErrorCode: {},
|
BlobUploadInvalidErrorCode: {},
|
||||||
TooManyRequestsErrorCode: {},
|
TooManyRequestsErrorCode: {},
|
||||||
|
UnknownErrorCode: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
var temporaryStatusCodes = map[int]struct{}{
|
var temporaryStatusCodes = map[int]struct{}{
|
||||||
|
@ -167,6 +169,7 @@ var temporaryStatusCodes = map[int]struct{}{
|
||||||
http.StatusInternalServerError: {},
|
http.StatusInternalServerError: {},
|
||||||
http.StatusBadGateway: {},
|
http.StatusBadGateway: {},
|
||||||
http.StatusServiceUnavailable: {},
|
http.StatusServiceUnavailable: {},
|
||||||
|
http.StatusGatewayTimeout: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckError returns a structured error if the response status is not in codes.
|
// CheckError returns a structured error if the response status is not in codes.
|
||||||
|
@ -191,7 +194,7 @@ func CheckError(resp *http.Response, codes ...int) error {
|
||||||
|
|
||||||
structuredError.rawBody = string(b)
|
structuredError.rawBody = string(b)
|
||||||
structuredError.StatusCode = resp.StatusCode
|
structuredError.StatusCode = resp.StatusCode
|
||||||
structuredError.request = resp.Request
|
structuredError.Request = resp.Request
|
||||||
|
|
||||||
return structuredError
|
return structuredError
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,6 @@ func ping(ctx context.Context, reg name.Registry, t http.RoundTripper) (*pingRes
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickFromMultipleChallenges(challenges []authchallenge.Challenge) authchallenge.Challenge {
|
func pickFromMultipleChallenges(challenges []authchallenge.Challenge) authchallenge.Challenge {
|
||||||
|
|
||||||
// It might happen there are multiple www-authenticate headers, e.g. `Negotiate` and `Basic`.
|
// It might happen there are multiple www-authenticate headers, e.g. `Negotiate` and `Basic`.
|
||||||
// Picking simply the first one could result eventually in `unrecognized challenge` error,
|
// Picking simply the first one could result eventually in `unrecognized challenge` error,
|
||||||
// that's why we're looping through the challenges in search for one that can be handled.
|
// that's why we're looping through the challenges in search for one that can be handled.
|
||||||
|
|
|
@ -46,8 +46,11 @@ type options struct {
|
||||||
predicate retry.Predicate
|
predicate retry.Predicate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Backoff is an alias of retry.Backoff to expose this configuration option to consumers of this lib
|
||||||
|
type Backoff = retry.Backoff
|
||||||
|
|
||||||
// WithRetryBackoff sets the backoff for retry operations.
|
// WithRetryBackoff sets the backoff for retry operations.
|
||||||
func WithRetryBackoff(backoff retry.Backoff) Option {
|
func WithRetryBackoff(backoff Backoff) Option {
|
||||||
return func(o *options) {
|
return func(o *options) {
|
||||||
o.backoff = backoff
|
o.backoff = backoff
|
||||||
}
|
}
|
||||||
|
|
17
vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/transport.go
generated
vendored
17
vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/transport.go
generated
vendored
|
@ -69,9 +69,9 @@ func NewWithContext(ctx context.Context, reg name.Registry, auth authn.Authentic
|
||||||
|
|
||||||
switch pr.challenge.Canonical() {
|
switch pr.challenge.Canonical() {
|
||||||
case anonymous:
|
case anonymous:
|
||||||
return t, nil
|
return &Wrapper{t}, nil
|
||||||
case basic:
|
case basic:
|
||||||
return &basicTransport{inner: t, auth: auth, target: reg.RegistryStr()}, nil
|
return &Wrapper{&basicTransport{inner: t, auth: auth, target: reg.RegistryStr()}}, nil
|
||||||
case bearer:
|
case bearer:
|
||||||
// We require the realm, which tells us where to send our Basic auth to turn it into Bearer auth.
|
// We require the realm, which tells us where to send our Basic auth to turn it into Bearer auth.
|
||||||
realm, ok := pr.parameters["realm"]
|
realm, ok := pr.parameters["realm"]
|
||||||
|
@ -96,8 +96,19 @@ func NewWithContext(ctx context.Context, reg name.Registry, auth authn.Authentic
|
||||||
if err := bt.refresh(ctx); err != nil {
|
if err := bt.refresh(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return bt, nil
|
return &Wrapper{bt}, nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unrecognized challenge: %s", pr.challenge)
|
return nil, fmt.Errorf("unrecognized challenge: %s", pr.challenge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapper results in *not* wrapping supplied transport with additional logic such as retries, useragent and debug logging
|
||||||
|
// Consumers are opt-ing into providing their own transport without any additional wrapping.
|
||||||
|
type Wrapper struct {
|
||||||
|
inner http.RoundTripper
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoundTrip delegates to the inner RoundTripper
|
||||||
|
func (w *Wrapper) RoundTrip(in *http.Request) (*http.Response, error) {
|
||||||
|
return w.inner.RoundTrip(in)
|
||||||
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/go-containerregistry/internal/redact"
|
"github.com/google/go-containerregistry/internal/redact"
|
||||||
"github.com/google/go-containerregistry/internal/retry"
|
"github.com/google/go-containerregistry/internal/retry"
|
||||||
|
@ -59,12 +57,12 @@ func Write(ref name.Reference, img v1.Image, options ...Option) (rerr error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer close(o.updates)
|
defer close(o.updates)
|
||||||
defer func() { sendError(o.updates, rerr) }()
|
defer func() { _ = sendError(o.updates, rerr) }()
|
||||||
}
|
}
|
||||||
return writeImage(ref, img, o, lastUpdate)
|
return writeImage(o.context, ref, img, o, lastUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeImage(ref name.Reference, img v1.Image, o *options, lastUpdate *v1.Update) error {
|
func writeImage(ctx context.Context, ref name.Reference, img v1.Image, o *options, lastUpdate *v1.Update) error {
|
||||||
ls, err := img.Layers()
|
ls, err := img.Layers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -77,19 +75,21 @@ func writeImage(ref name.Reference, img v1.Image, o *options, lastUpdate *v1.Upd
|
||||||
w := writer{
|
w := writer{
|
||||||
repo: ref.Context(),
|
repo: ref.Context(),
|
||||||
client: &http.Client{Transport: tr},
|
client: &http.Client{Transport: tr},
|
||||||
context: o.context,
|
context: ctx,
|
||||||
updates: o.updates,
|
updates: o.updates,
|
||||||
lastUpdate: lastUpdate,
|
lastUpdate: lastUpdate,
|
||||||
|
backoff: o.retryBackoff,
|
||||||
|
predicate: o.retryPredicate,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload individual blobs and collect any errors.
|
// Upload individual blobs and collect any errors.
|
||||||
blobChan := make(chan v1.Layer, 2*o.jobs)
|
blobChan := make(chan v1.Layer, 2*o.jobs)
|
||||||
g, ctx := errgroup.WithContext(o.context)
|
g, gctx := errgroup.WithContext(ctx)
|
||||||
for i := 0; i < o.jobs; i++ {
|
for i := 0; i < o.jobs; i++ {
|
||||||
// Start N workers consuming blobs to upload.
|
// Start N workers consuming blobs to upload.
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
for b := range blobChan {
|
for b := range blobChan {
|
||||||
if err := w.uploadOne(b); err != nil {
|
if err := w.uploadOne(gctx, b); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,15 +128,12 @@ func writeImage(ref name.Reference, img v1.Image, o *options, lastUpdate *v1.Upd
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case blobChan <- l:
|
case blobChan <- l:
|
||||||
case <-ctx.Done():
|
case <-gctx.Done():
|
||||||
return ctx.Err()
|
return gctx.Err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err := g.Wait(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if l, err := partial.ConfigLayer(img); err != nil {
|
if l, err := partial.ConfigLayer(img); err != nil {
|
||||||
// We can't read the ConfigLayer, possibly because of streaming layers,
|
// We can't read the ConfigLayer, possibly because of streaming layers,
|
||||||
|
@ -151,13 +148,13 @@ func writeImage(ref name.Reference, img v1.Image, o *options, lastUpdate *v1.Upd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := w.uploadOne(l); err != nil {
|
if err := w.uploadOne(ctx, l); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We *can* read the ConfigLayer, so upload it concurrently with the layers.
|
// We *can* read the ConfigLayer, so upload it concurrently with the layers.
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
return w.uploadOne(l)
|
return w.uploadOne(gctx, l)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Wait for the layers + config.
|
// Wait for the layers + config.
|
||||||
|
@ -168,7 +165,7 @@ func writeImage(ref name.Reference, img v1.Image, o *options, lastUpdate *v1.Upd
|
||||||
|
|
||||||
// With all of the constituent elements uploaded, upload the manifest
|
// With all of the constituent elements uploaded, upload the manifest
|
||||||
// to commit the image.
|
// to commit the image.
|
||||||
return w.commitManifest(img, ref)
|
return w.commitManifest(ctx, img, ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writer writes the elements of an image to a remote image reference.
|
// writer writes the elements of an image to a remote image reference.
|
||||||
|
@ -179,6 +176,8 @@ type writer struct {
|
||||||
|
|
||||||
updates chan<- v1.Update
|
updates chan<- v1.Update
|
||||||
lastUpdate *v1.Update
|
lastUpdate *v1.Update
|
||||||
|
backoff Backoff
|
||||||
|
predicate retry.Predicate
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendError(ch chan<- v1.Update, err error) error {
|
func sendError(ch chan<- v1.Update, err error) error {
|
||||||
|
@ -405,30 +404,12 @@ func (w *writer) incrProgress(written int64) {
|
||||||
}
|
}
|
||||||
w.updates <- v1.Update{
|
w.updates <- v1.Update{
|
||||||
Total: w.lastUpdate.Total,
|
Total: w.lastUpdate.Total,
|
||||||
Complete: atomic.AddInt64(&w.lastUpdate.Complete, int64(written)),
|
Complete: atomic.AddInt64(&w.lastUpdate.Complete, written),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var shouldRetry retry.Predicate = func(err error) bool {
|
|
||||||
// Various failure modes here, as we're often reading from and writing to
|
|
||||||
// the network.
|
|
||||||
if retry.IsTemporary(err) || errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, syscall.EPIPE) {
|
|
||||||
logs.Warn.Printf("retrying %v", err)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try this three times, waiting 1s after first failure, 3s after second.
|
|
||||||
var backoff = retry.Backoff{
|
|
||||||
Duration: 1.0 * time.Second,
|
|
||||||
Factor: 3.0,
|
|
||||||
Jitter: 0.1,
|
|
||||||
Steps: 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
// uploadOne performs a complete upload of a single layer.
|
// uploadOne performs a complete upload of a single layer.
|
||||||
func (w *writer) uploadOne(l v1.Layer) error {
|
func (w *writer) uploadOne(ctx context.Context, l v1.Layer) error {
|
||||||
var from, mount string
|
var from, mount string
|
||||||
if h, err := l.Digest(); err == nil {
|
if h, err := l.Digest(); err == nil {
|
||||||
// If we know the digest, this isn't a streaming layer. Do an existence
|
// If we know the digest, this isn't a streaming layer. Do an existence
|
||||||
|
@ -455,8 +436,6 @@ func (w *writer) uploadOne(l v1.Layer) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := w.context
|
|
||||||
|
|
||||||
tryUpload := func() error {
|
tryUpload := func() error {
|
||||||
location, mounted, err := w.initiateUpload(from, mount)
|
location, mounted, err := w.initiateUpload(from, mount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -508,14 +487,14 @@ func (w *writer) uploadOne(l v1.Layer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return retry.Retry(tryUpload, shouldRetry, backoff)
|
return retry.Retry(tryUpload, w.predicate, w.backoff)
|
||||||
}
|
}
|
||||||
|
|
||||||
type withLayer interface {
|
type withLayer interface {
|
||||||
Layer(v1.Hash) (v1.Layer, error)
|
Layer(v1.Hash) (v1.Layer, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *writer) writeIndex(ref name.Reference, ii v1.ImageIndex, options ...Option) error {
|
func (w *writer) writeIndex(ctx context.Context, ref name.Reference, ii v1.ImageIndex, options ...Option) error {
|
||||||
index, err := ii.IndexManifest()
|
index, err := ii.IndexManifest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -544,7 +523,7 @@ func (w *writer) writeIndex(ref name.Reference, ii v1.ImageIndex, options ...Opt
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := w.writeIndex(ref, ii); err != nil {
|
if err := w.writeIndex(ctx, ref, ii, options...); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case types.OCIManifestSchema1, types.DockerManifestSchema2:
|
case types.OCIManifestSchema1, types.DockerManifestSchema2:
|
||||||
|
@ -552,7 +531,7 @@ func (w *writer) writeIndex(ref name.Reference, ii v1.ImageIndex, options ...Opt
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := writeImage(ref, img, o, w.lastUpdate); err != nil {
|
if err := writeImage(ctx, ref, img, o, w.lastUpdate); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -562,7 +541,7 @@ func (w *writer) writeIndex(ref name.Reference, ii v1.ImageIndex, options ...Opt
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := w.uploadOne(layer); err != nil {
|
if err := w.uploadOne(ctx, layer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,7 +550,7 @@ func (w *writer) writeIndex(ref name.Reference, ii v1.ImageIndex, options ...Opt
|
||||||
|
|
||||||
// With all of the constituent elements uploaded, upload the manifest
|
// With all of the constituent elements uploaded, upload the manifest
|
||||||
// to commit the image.
|
// to commit the image.
|
||||||
return w.commitManifest(ii, ref)
|
return w.commitManifest(ctx, ii, ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
type withMediaType interface {
|
type withMediaType interface {
|
||||||
|
@ -617,7 +596,7 @@ func unpackTaggable(t Taggable) ([]byte, *v1.Descriptor, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// commitManifest does a PUT of the image's manifest.
|
// commitManifest does a PUT of the image's manifest.
|
||||||
func (w *writer) commitManifest(t Taggable, ref name.Reference) error {
|
func (w *writer) commitManifest(ctx context.Context, t Taggable, ref name.Reference) error {
|
||||||
tryUpload := func() error {
|
tryUpload := func() error {
|
||||||
raw, desc, err := unpackTaggable(t)
|
raw, desc, err := unpackTaggable(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -633,7 +612,7 @@ func (w *writer) commitManifest(t Taggable, ref name.Reference) error {
|
||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", string(desc.MediaType))
|
req.Header.Set("Content-Type", string(desc.MediaType))
|
||||||
|
|
||||||
resp, err := w.client.Do(req.WithContext(w.context))
|
resp, err := w.client.Do(req.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -649,7 +628,7 @@ func (w *writer) commitManifest(t Taggable, ref name.Reference) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return retry.Retry(tryUpload, shouldRetry, backoff)
|
return retry.Retry(tryUpload, w.predicate, w.backoff)
|
||||||
}
|
}
|
||||||
|
|
||||||
func scopesForUploadingImage(repo name.Repository, layers []v1.Layer) []string {
|
func scopesForUploadingImage(repo name.Repository, layers []v1.Layer) []string {
|
||||||
|
@ -692,10 +671,12 @@ func WriteIndex(ref name.Reference, ii v1.ImageIndex, options ...Option) (rerr e
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w := writer{
|
w := writer{
|
||||||
repo: ref.Context(),
|
repo: ref.Context(),
|
||||||
client: &http.Client{Transport: tr},
|
client: &http.Client{Transport: tr},
|
||||||
context: o.context,
|
context: o.context,
|
||||||
updates: o.updates,
|
updates: o.updates,
|
||||||
|
backoff: o.retryBackoff,
|
||||||
|
predicate: o.retryPredicate,
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.updates != nil {
|
if o.updates != nil {
|
||||||
|
@ -708,7 +689,7 @@ func WriteIndex(ref name.Reference, ii v1.ImageIndex, options ...Option) (rerr e
|
||||||
defer func() { sendError(o.updates, rerr) }()
|
defer func() { sendError(o.updates, rerr) }()
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.writeIndex(ref, ii, options...)
|
return w.writeIndex(o.context, ref, ii, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// countImage counts the total size of all layers + config blob + manifest for
|
// countImage counts the total size of all layers + config blob + manifest for
|
||||||
|
@ -831,10 +812,12 @@ func WriteLayer(repo name.Repository, layer v1.Layer, options ...Option) (rerr e
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w := writer{
|
w := writer{
|
||||||
repo: repo,
|
repo: repo,
|
||||||
client: &http.Client{Transport: tr},
|
client: &http.Client{Transport: tr},
|
||||||
context: o.context,
|
context: o.context,
|
||||||
updates: o.updates,
|
updates: o.updates,
|
||||||
|
backoff: o.retryBackoff,
|
||||||
|
predicate: o.retryPredicate,
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.updates != nil {
|
if o.updates != nil {
|
||||||
|
@ -851,7 +834,7 @@ func WriteLayer(repo name.Repository, layer v1.Layer, options ...Option) (rerr e
|
||||||
}
|
}
|
||||||
w.lastUpdate = &v1.Update{Total: size}
|
w.lastUpdate = &v1.Update{Total: size}
|
||||||
}
|
}
|
||||||
return w.uploadOne(layer)
|
return w.uploadOne(o.context, layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tag adds a tag to the given Taggable via PUT /v2/.../manifests/<tag>
|
// Tag adds a tag to the given Taggable via PUT /v2/.../manifests/<tag>
|
||||||
|
@ -898,10 +881,12 @@ func Put(ref name.Reference, t Taggable, options ...Option) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w := writer{
|
w := writer{
|
||||||
repo: ref.Context(),
|
repo: ref.Context(),
|
||||||
client: &http.Client{Transport: tr},
|
client: &http.Client{Transport: tr},
|
||||||
context: o.context,
|
context: o.context,
|
||||||
|
backoff: o.retryBackoff,
|
||||||
|
predicate: o.retryPredicate,
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.commitManifest(t, ref)
|
return w.commitManifest(o.context, t, ref)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Copyright 2018 Google LLC All Rights Reserved.
|
// Copyright 2018 Google LLC All Rights Reserved.
|
||||||
|
|
|
@ -76,8 +76,10 @@
|
||||||
- acceptance/openstack/networking/v2/extensions/subnetpools
|
- acceptance/openstack/networking/v2/extensions/subnetpools
|
||||||
- acceptance/openstack/networking/v2/extensions/trunks
|
- acceptance/openstack/networking/v2/extensions/trunks
|
||||||
- acceptance/openstack/networking/v2/extensions/vlantransparent
|
- acceptance/openstack/networking/v2/extensions/vlantransparent
|
||||||
|
devstack_projects: 'openstack/neutron-dynamic-routing'
|
||||||
devstack_services:
|
devstack_services:
|
||||||
- designate
|
- designate
|
||||||
|
- neutron-dynamic-routing
|
||||||
- neutron-ext
|
- neutron-ext
|
||||||
- octavia
|
- octavia
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
## 0.24.0 (December 13, 2021)
|
||||||
|
|
||||||
|
UPGRADE NOTES
|
||||||
|
|
||||||
|
* Set Go minimum version to 1.14 [GH-2294](https://github.com/gophercloud/gophercloud/pull/2294)
|
||||||
|
|
||||||
|
IMPROVEMENTS
|
||||||
|
|
||||||
|
* Added `blockstorage/v3/qos.Get` [GH-2283](https://github.com/gophercloud/gophercloud/pull/2283)
|
||||||
|
* Added `blockstorage/v3/qos.Update` [GH-2283](https://github.com/gophercloud/gophercloud/pull/2283)
|
||||||
|
* Added `blockstorage/v3/qos.DeleteKeys` [GH-2283](https://github.com/gophercloud/gophercloud/pull/2283)
|
||||||
|
* Added `blockstorage/v3/qos.Associate` [GH-2284](https://github.com/gophercloud/gophercloud/pull/2284)
|
||||||
|
* Added `blockstorage/v3/qos.Disassociate` [GH-2284](https://github.com/gophercloud/gophercloud/pull/2284)
|
||||||
|
* Added `blockstorage/v3/qos.DisassociateAll` [GH-2284](https://github.com/gophercloud/gophercloud/pull/2284)
|
||||||
|
* Added `blockstorage/v3/qos.ListAssociations` [GH-2284](https://github.com/gophercloud/gophercloud/pull/2284)
|
||||||
|
|
||||||
## 0.23.0 (November 12, 2021)
|
## 0.23.0 (November 12, 2021)
|
||||||
|
|
||||||
IMPROVEMENTS
|
IMPROVEMENTS
|
||||||
|
|
|
@ -53,4 +53,10 @@ const (
|
||||||
|
|
||||||
// AnnotationDescription is the annotation key for the human-readable description of the software packaged in the image.
|
// AnnotationDescription is the annotation key for the human-readable description of the software packaged in the image.
|
||||||
AnnotationDescription = "org.opencontainers.image.description"
|
AnnotationDescription = "org.opencontainers.image.description"
|
||||||
|
|
||||||
|
// AnnotationBaseImageDigest is the annotation key for the digest of the image's base image.
|
||||||
|
AnnotationBaseImageDigest = "org.opencontainers.image.base.digest"
|
||||||
|
|
||||||
|
// AnnotationBaseImageName is the annotation key for the image reference of the image's base image.
|
||||||
|
AnnotationBaseImageName = "org.opencontainers.image.base.name"
|
||||||
)
|
)
|
||||||
|
|
|
@ -89,9 +89,20 @@ type Image struct {
|
||||||
// Architecture is the CPU architecture which the binaries in this image are built to run on.
|
// Architecture is the CPU architecture which the binaries in this image are built to run on.
|
||||||
Architecture string `json:"architecture"`
|
Architecture string `json:"architecture"`
|
||||||
|
|
||||||
|
// Variant is the variant of the specified CPU architecture which image binaries are intended to run on.
|
||||||
|
Variant string `json:"variant,omitempty"`
|
||||||
|
|
||||||
// OS is the name of the operating system which the image is built to run on.
|
// OS is the name of the operating system which the image is built to run on.
|
||||||
OS string `json:"os"`
|
OS string `json:"os"`
|
||||||
|
|
||||||
|
// OSVersion is an optional field specifying the operating system
|
||||||
|
// version, for example on Windows `10.0.14393.1066`.
|
||||||
|
OSVersion string `json:"os.version,omitempty"`
|
||||||
|
|
||||||
|
// OSFeatures is an optional field specifying an array of strings,
|
||||||
|
// each listing a required OS feature (for example on Windows `win32k`).
|
||||||
|
OSFeatures []string `json:"os.features,omitempty"`
|
||||||
|
|
||||||
// Config defines the execution parameters which should be used as a base when running a container using the image.
|
// Config defines the execution parameters which should be used as a base when running a container using the image.
|
||||||
Config ImageConfig `json:"config,omitempty"`
|
Config ImageConfig `json:"config,omitempty"`
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@ const (
|
||||||
// referenced by the manifest.
|
// referenced by the manifest.
|
||||||
MediaTypeImageLayerGzip = "application/vnd.oci.image.layer.v1.tar+gzip"
|
MediaTypeImageLayerGzip = "application/vnd.oci.image.layer.v1.tar+gzip"
|
||||||
|
|
||||||
|
// MediaTypeImageLayerZstd is the media type used for zstd compressed
|
||||||
|
// layers referenced by the manifest.
|
||||||
|
MediaTypeImageLayerZstd = "application/vnd.oci.image.layer.v1.tar+zstd"
|
||||||
|
|
||||||
// MediaTypeImageLayerNonDistributable is the media type for layers referenced by
|
// MediaTypeImageLayerNonDistributable is the media type for layers referenced by
|
||||||
// the manifest but with distribution restrictions.
|
// the manifest but with distribution restrictions.
|
||||||
MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.v1.tar"
|
MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.v1.tar"
|
||||||
|
@ -43,6 +47,11 @@ const (
|
||||||
// restrictions.
|
// restrictions.
|
||||||
MediaTypeImageLayerNonDistributableGzip = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip"
|
MediaTypeImageLayerNonDistributableGzip = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip"
|
||||||
|
|
||||||
|
// MediaTypeImageLayerNonDistributableZstd is the media type for zstd
|
||||||
|
// compressed layers referenced by the manifest but with distribution
|
||||||
|
// restrictions.
|
||||||
|
MediaTypeImageLayerNonDistributableZstd = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd"
|
||||||
|
|
||||||
// MediaTypeImageConfig specifies the media type for the image configuration.
|
// MediaTypeImageConfig specifies the media type for the image configuration.
|
||||||
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
|
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,7 +25,7 @@ const (
|
||||||
VersionPatch = 1
|
VersionPatch = 1
|
||||||
|
|
||||||
// VersionDev indicates development branch. Releases will be empty string.
|
// VersionDev indicates development branch. Releases will be empty string.
|
||||||
VersionDev = ""
|
VersionDev = "-dev"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version is the specification version that the package types support.
|
// Version is the specification version that the package types support.
|
||||||
|
|
|
@ -92,9 +92,10 @@ func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
|
||||||
|
|
||||||
// JSON key file types.
|
// JSON key file types.
|
||||||
const (
|
const (
|
||||||
serviceAccountKey = "service_account"
|
serviceAccountKey = "service_account"
|
||||||
userCredentialsKey = "authorized_user"
|
userCredentialsKey = "authorized_user"
|
||||||
externalAccountKey = "external_account"
|
externalAccountKey = "external_account"
|
||||||
|
impersonatedServiceAccount = "impersonated_service_account"
|
||||||
)
|
)
|
||||||
|
|
||||||
// credentialsFile is the unmarshalled representation of a credentials file.
|
// credentialsFile is the unmarshalled representation of a credentials file.
|
||||||
|
@ -121,8 +122,13 @@ type credentialsFile struct {
|
||||||
TokenURLExternal string `json:"token_url"`
|
TokenURLExternal string `json:"token_url"`
|
||||||
TokenInfoURL string `json:"token_info_url"`
|
TokenInfoURL string `json:"token_info_url"`
|
||||||
ServiceAccountImpersonationURL string `json:"service_account_impersonation_url"`
|
ServiceAccountImpersonationURL string `json:"service_account_impersonation_url"`
|
||||||
|
Delegates []string `json:"delegates"`
|
||||||
CredentialSource externalaccount.CredentialSource `json:"credential_source"`
|
CredentialSource externalaccount.CredentialSource `json:"credential_source"`
|
||||||
QuotaProjectID string `json:"quota_project_id"`
|
QuotaProjectID string `json:"quota_project_id"`
|
||||||
|
WorkforcePoolUserProject string `json:"workforce_pool_user_project"`
|
||||||
|
|
||||||
|
// Service account impersonation
|
||||||
|
SourceCredentials *credentialsFile `json:"source_credentials"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *credentialsFile) jwtConfig(scopes []string, subject string) *jwt.Config {
|
func (f *credentialsFile) jwtConfig(scopes []string, subject string) *jwt.Config {
|
||||||
|
@ -176,8 +182,26 @@ func (f *credentialsFile) tokenSource(ctx context.Context, params CredentialsPar
|
||||||
CredentialSource: f.CredentialSource,
|
CredentialSource: f.CredentialSource,
|
||||||
QuotaProjectID: f.QuotaProjectID,
|
QuotaProjectID: f.QuotaProjectID,
|
||||||
Scopes: params.Scopes,
|
Scopes: params.Scopes,
|
||||||
|
WorkforcePoolUserProject: f.WorkforcePoolUserProject,
|
||||||
}
|
}
|
||||||
return cfg.TokenSource(ctx)
|
return cfg.TokenSource(ctx)
|
||||||
|
case impersonatedServiceAccount:
|
||||||
|
if f.ServiceAccountImpersonationURL == "" || f.SourceCredentials == nil {
|
||||||
|
return nil, errors.New("missing 'source_credentials' field or 'service_account_impersonation_url' in credentials")
|
||||||
|
}
|
||||||
|
|
||||||
|
ts, err := f.SourceCredentials.tokenSource(ctx, params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
imp := externalaccount.ImpersonateTokenSource{
|
||||||
|
Ctx: ctx,
|
||||||
|
URL: f.ServiceAccountImpersonationURL,
|
||||||
|
Scopes: params.Scopes,
|
||||||
|
Ts: ts,
|
||||||
|
Delegates: f.Delegates,
|
||||||
|
}
|
||||||
|
return oauth2.ReuseTokenSource(nil, imp), nil
|
||||||
case "":
|
case "":
|
||||||
return nil, errors.New("missing 'type' field in credentials")
|
return nil, errors.New("missing 'type' field in credentials")
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -53,6 +53,11 @@ type Config struct {
|
||||||
QuotaProjectID string
|
QuotaProjectID string
|
||||||
// Scopes contains the desired scopes for the returned access token.
|
// Scopes contains the desired scopes for the returned access token.
|
||||||
Scopes []string
|
Scopes []string
|
||||||
|
// The optional workforce pool user project number when the credential
|
||||||
|
// corresponds to a workforce pool and not a workload identity pool.
|
||||||
|
// The underlying principal must still have serviceusage.services.use IAM
|
||||||
|
// permission to use the project for billing/quota.
|
||||||
|
WorkforcePoolUserProject string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Each element consists of a list of patterns. validateURLs checks for matches
|
// Each element consists of a list of patterns. validateURLs checks for matches
|
||||||
|
@ -73,6 +78,7 @@ var (
|
||||||
regexp.MustCompile(`^iamcredentials\.[^\.\s\/\\]+\.googleapis\.com$`),
|
regexp.MustCompile(`^iamcredentials\.[^\.\s\/\\]+\.googleapis\.com$`),
|
||||||
regexp.MustCompile(`^[^\.\s\/\\]+-iamcredentials\.googleapis\.com$`),
|
regexp.MustCompile(`^[^\.\s\/\\]+-iamcredentials\.googleapis\.com$`),
|
||||||
}
|
}
|
||||||
|
validWorkforceAudiencePattern *regexp.Regexp = regexp.MustCompile(`//iam\.googleapis\.com/locations/[^/]+/workforcePools/`)
|
||||||
)
|
)
|
||||||
|
|
||||||
func validateURL(input string, patterns []*regexp.Regexp, scheme string) bool {
|
func validateURL(input string, patterns []*regexp.Regexp, scheme string) bool {
|
||||||
|
@ -86,14 +92,17 @@ func validateURL(input string, patterns []*regexp.Regexp, scheme string) bool {
|
||||||
toTest := parsed.Host
|
toTest := parsed.Host
|
||||||
|
|
||||||
for _, pattern := range patterns {
|
for _, pattern := range patterns {
|
||||||
|
if pattern.MatchString(toTest) {
|
||||||
if valid := pattern.MatchString(toTest); valid {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateWorkforceAudience(input string) bool {
|
||||||
|
return validWorkforceAudiencePattern.MatchString(input)
|
||||||
|
}
|
||||||
|
|
||||||
// TokenSource Returns an external account TokenSource struct. This is to be called by package google to construct a google.Credentials.
|
// TokenSource Returns an external account TokenSource struct. This is to be called by package google to construct a google.Credentials.
|
||||||
func (c *Config) TokenSource(ctx context.Context) (oauth2.TokenSource, error) {
|
func (c *Config) TokenSource(ctx context.Context) (oauth2.TokenSource, error) {
|
||||||
return c.tokenSource(ctx, validTokenURLPatterns, validImpersonateURLPatterns, "https")
|
return c.tokenSource(ctx, validTokenURLPatterns, validImpersonateURLPatterns, "https")
|
||||||
|
@ -115,6 +124,13 @@ func (c *Config) tokenSource(ctx context.Context, tokenURLValidPats []*regexp.Re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.WorkforcePoolUserProject != "" {
|
||||||
|
valid := validateWorkforceAudience(c.Audience)
|
||||||
|
if !valid {
|
||||||
|
return nil, fmt.Errorf("oauth2/google: workforce_pool_user_project should not be set for non-workforce pool credentials")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ts := tokenSource{
|
ts := tokenSource{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
conf: c,
|
conf: c,
|
||||||
|
@ -124,11 +140,11 @@ func (c *Config) tokenSource(ctx context.Context, tokenURLValidPats []*regexp.Re
|
||||||
}
|
}
|
||||||
scopes := c.Scopes
|
scopes := c.Scopes
|
||||||
ts.conf.Scopes = []string{"https://www.googleapis.com/auth/cloud-platform"}
|
ts.conf.Scopes = []string{"https://www.googleapis.com/auth/cloud-platform"}
|
||||||
imp := impersonateTokenSource{
|
imp := ImpersonateTokenSource{
|
||||||
ctx: ctx,
|
Ctx: ctx,
|
||||||
url: c.ServiceAccountImpersonationURL,
|
URL: c.ServiceAccountImpersonationURL,
|
||||||
scopes: scopes,
|
Scopes: scopes,
|
||||||
ts: oauth2.ReuseTokenSource(nil, ts),
|
Ts: oauth2.ReuseTokenSource(nil, ts),
|
||||||
}
|
}
|
||||||
return oauth2.ReuseTokenSource(nil, imp), nil
|
return oauth2.ReuseTokenSource(nil, imp), nil
|
||||||
}
|
}
|
||||||
|
@ -224,7 +240,15 @@ func (ts tokenSource) Token() (*oauth2.Token, error) {
|
||||||
ClientID: conf.ClientID,
|
ClientID: conf.ClientID,
|
||||||
ClientSecret: conf.ClientSecret,
|
ClientSecret: conf.ClientSecret,
|
||||||
}
|
}
|
||||||
stsResp, err := exchangeToken(ts.ctx, conf.TokenURL, &stsRequest, clientAuth, header, nil)
|
var options map[string]interface{}
|
||||||
|
// Do not pass workforce_pool_user_project when client authentication is used.
|
||||||
|
// The client ID is sufficient for determining the user project.
|
||||||
|
if conf.WorkforcePoolUserProject != "" && conf.ClientID == "" {
|
||||||
|
options = map[string]interface{}{
|
||||||
|
"userProject": conf.WorkforcePoolUserProject,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stsResp, err := exchangeToken(ts.ctx, conf.TokenURL, &stsRequest, clientAuth, header, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,30 +29,44 @@ type impersonateTokenResponse struct {
|
||||||
ExpireTime string `json:"expireTime"`
|
ExpireTime string `json:"expireTime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type impersonateTokenSource struct {
|
// ImpersonateTokenSource uses a source credential, stored in Ts, to request an access token to the provided URL.
|
||||||
ctx context.Context
|
// Scopes can be defined when the access token is requested.
|
||||||
ts oauth2.TokenSource
|
type ImpersonateTokenSource struct {
|
||||||
|
// Ctx is the execution context of the impersonation process
|
||||||
|
// used to perform http call to the URL. Required
|
||||||
|
Ctx context.Context
|
||||||
|
// Ts is the source credential used to generate a token on the
|
||||||
|
// impersonated service account. Required.
|
||||||
|
Ts oauth2.TokenSource
|
||||||
|
|
||||||
url string
|
// URL is the endpoint to call to generate a token
|
||||||
scopes []string
|
// on behalf the service account. Required.
|
||||||
|
URL string
|
||||||
|
// Scopes that the impersonated credential should have. Required.
|
||||||
|
Scopes []string
|
||||||
|
// Delegates are the service account email addresses in a delegation chain.
|
||||||
|
// Each service account must be granted roles/iam.serviceAccountTokenCreator
|
||||||
|
// on the next service account in the chain. Optional.
|
||||||
|
Delegates []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Token performs the exchange to get a temporary service account token to allow access to GCP.
|
// Token performs the exchange to get a temporary service account token to allow access to GCP.
|
||||||
func (its impersonateTokenSource) Token() (*oauth2.Token, error) {
|
func (its ImpersonateTokenSource) Token() (*oauth2.Token, error) {
|
||||||
reqBody := generateAccessTokenReq{
|
reqBody := generateAccessTokenReq{
|
||||||
Lifetime: "3600s",
|
Lifetime: "3600s",
|
||||||
Scope: its.scopes,
|
Scope: its.Scopes,
|
||||||
|
Delegates: its.Delegates,
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(reqBody)
|
b, err := json.Marshal(reqBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("oauth2/google: unable to marshal request: %v", err)
|
return nil, fmt.Errorf("oauth2/google: unable to marshal request: %v", err)
|
||||||
}
|
}
|
||||||
client := oauth2.NewClient(its.ctx, its.ts)
|
client := oauth2.NewClient(its.Ctx, its.Ts)
|
||||||
req, err := http.NewRequest("POST", its.url, bytes.NewReader(b))
|
req, err := http.NewRequest("POST", its.URL, bytes.NewReader(b))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("oauth2/google: unable to create impersonation request: %v", err)
|
return nil, fmt.Errorf("oauth2/google: unable to create impersonation request: %v", err)
|
||||||
}
|
}
|
||||||
req = req.WithContext(its.ctx)
|
req = req.WithContext(its.Ctx)
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
|
|
|
@ -25,55 +25,75 @@
|
||||||
// later release.
|
// later release.
|
||||||
package attributes
|
package attributes
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// Attributes is an immutable struct for storing and retrieving generic
|
// Attributes is an immutable struct for storing and retrieving generic
|
||||||
// key/value pairs. Keys must be hashable, and users should define their own
|
// key/value pairs. Keys must be hashable, and users should define their own
|
||||||
// types for keys.
|
// types for keys. Values should not be modified after they are added to an
|
||||||
|
// Attributes or if they were received from one. If values implement 'Equal(o
|
||||||
|
// interface{}) bool', it will be called by (*Attributes).Equal to determine
|
||||||
|
// whether two values with the same key should be considered equal.
|
||||||
type Attributes struct {
|
type Attributes struct {
|
||||||
m map[interface{}]interface{}
|
m map[interface{}]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Attributes containing all key/value pairs in kvs. If the
|
// New returns a new Attributes containing the key/value pair.
|
||||||
// same key appears multiple times, the last value overwrites all previous
|
func New(key, value interface{}) *Attributes {
|
||||||
// values for that key. Panics if len(kvs) is not even.
|
return &Attributes{m: map[interface{}]interface{}{key: value}}
|
||||||
func New(kvs ...interface{}) *Attributes {
|
|
||||||
if len(kvs)%2 != 0 {
|
|
||||||
panic(fmt.Sprintf("attributes.New called with unexpected input: len(kvs) = %v", len(kvs)))
|
|
||||||
}
|
|
||||||
a := &Attributes{m: make(map[interface{}]interface{}, len(kvs)/2)}
|
|
||||||
for i := 0; i < len(kvs)/2; i++ {
|
|
||||||
a.m[kvs[i*2]] = kvs[i*2+1]
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithValues returns a new Attributes containing all key/value pairs in a and
|
// WithValue returns a new Attributes containing the previous keys and values
|
||||||
// kvs. Panics if len(kvs) is not even. If the same key appears multiple
|
// and the new key/value pair. If the same key appears multiple times, the
|
||||||
// times, the last value overwrites all previous values for that key. To
|
// last value overwrites all previous values for that key. To remove an
|
||||||
// remove an existing key, use a nil value.
|
// existing key, use a nil value. value should not be modified later.
|
||||||
func (a *Attributes) WithValues(kvs ...interface{}) *Attributes {
|
func (a *Attributes) WithValue(key, value interface{}) *Attributes {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
return New(kvs...)
|
return New(key, value)
|
||||||
}
|
}
|
||||||
if len(kvs)%2 != 0 {
|
n := &Attributes{m: make(map[interface{}]interface{}, len(a.m)+1)}
|
||||||
panic(fmt.Sprintf("attributes.New called with unexpected input: len(kvs) = %v", len(kvs)))
|
|
||||||
}
|
|
||||||
n := &Attributes{m: make(map[interface{}]interface{}, len(a.m)+len(kvs)/2)}
|
|
||||||
for k, v := range a.m {
|
for k, v := range a.m {
|
||||||
n.m[k] = v
|
n.m[k] = v
|
||||||
}
|
}
|
||||||
for i := 0; i < len(kvs)/2; i++ {
|
n.m[key] = value
|
||||||
n.m[kvs[i*2]] = kvs[i*2+1]
|
|
||||||
}
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value returns the value associated with these attributes for key, or nil if
|
// Value returns the value associated with these attributes for key, or nil if
|
||||||
// no value is associated with key.
|
// no value is associated with key. The returned value should not be modified.
|
||||||
func (a *Attributes) Value(key interface{}) interface{} {
|
func (a *Attributes) Value(key interface{}) interface{} {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return a.m[key]
|
return a.m[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Equal returns whether a and o are equivalent. If 'Equal(o interface{})
|
||||||
|
// bool' is implemented for a value in the attributes, it is called to
|
||||||
|
// determine if the value matches the one stored in the other attributes. If
|
||||||
|
// Equal is not implemented, standard equality is used to determine if the two
|
||||||
|
// values are equal.
|
||||||
|
func (a *Attributes) Equal(o *Attributes) bool {
|
||||||
|
if a == nil && o == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if a == nil || o == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(a.m) != len(o.m) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for k, v := range a.m {
|
||||||
|
ov, ok := o.m[k]
|
||||||
|
if !ok {
|
||||||
|
// o missing element of a
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if eq, ok := v.(interface{ Equal(o interface{}) bool }); ok {
|
||||||
|
if !eq.Equal(ov) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else if v != ov {
|
||||||
|
// Fallback to a standard equality check if Value is unimplemented.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ go_library(
|
||||||
importpath = "google.golang.org/grpc/balancer/base",
|
importpath = "google.golang.org/grpc/balancer/base",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//vendor/google.golang.org/grpc/attributes:go_default_library",
|
|
||||||
"//vendor/google.golang.org/grpc/balancer:go_default_library",
|
"//vendor/google.golang.org/grpc/balancer:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/connectivity:go_default_library",
|
"//vendor/google.golang.org/grpc/connectivity:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/grpclog:go_default_library",
|
"//vendor/google.golang.org/grpc/grpclog:go_default_library",
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"google.golang.org/grpc/attributes"
|
|
||||||
"google.golang.org/grpc/balancer"
|
"google.golang.org/grpc/balancer"
|
||||||
"google.golang.org/grpc/connectivity"
|
"google.golang.org/grpc/connectivity"
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
|
@ -42,7 +41,7 @@ func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions)
|
||||||
cc: cc,
|
cc: cc,
|
||||||
pickerBuilder: bb.pickerBuilder,
|
pickerBuilder: bb.pickerBuilder,
|
||||||
|
|
||||||
subConns: make(map[resolver.Address]subConnInfo),
|
subConns: resolver.NewAddressMap(),
|
||||||
scStates: make(map[balancer.SubConn]connectivity.State),
|
scStates: make(map[balancer.SubConn]connectivity.State),
|
||||||
csEvltr: &balancer.ConnectivityStateEvaluator{},
|
csEvltr: &balancer.ConnectivityStateEvaluator{},
|
||||||
config: bb.config,
|
config: bb.config,
|
||||||
|
@ -58,11 +57,6 @@ func (bb *baseBuilder) Name() string {
|
||||||
return bb.name
|
return bb.name
|
||||||
}
|
}
|
||||||
|
|
||||||
type subConnInfo struct {
|
|
||||||
subConn balancer.SubConn
|
|
||||||
attrs *attributes.Attributes
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseBalancer struct {
|
type baseBalancer struct {
|
||||||
cc balancer.ClientConn
|
cc balancer.ClientConn
|
||||||
pickerBuilder PickerBuilder
|
pickerBuilder PickerBuilder
|
||||||
|
@ -70,7 +64,7 @@ type baseBalancer struct {
|
||||||
csEvltr *balancer.ConnectivityStateEvaluator
|
csEvltr *balancer.ConnectivityStateEvaluator
|
||||||
state connectivity.State
|
state connectivity.State
|
||||||
|
|
||||||
subConns map[resolver.Address]subConnInfo // `attributes` is stripped from the keys of this map (the addresses)
|
subConns *resolver.AddressMap
|
||||||
scStates map[balancer.SubConn]connectivity.State
|
scStates map[balancer.SubConn]connectivity.State
|
||||||
picker balancer.Picker
|
picker balancer.Picker
|
||||||
config Config
|
config Config
|
||||||
|
@ -81,7 +75,7 @@ type baseBalancer struct {
|
||||||
|
|
||||||
func (b *baseBalancer) ResolverError(err error) {
|
func (b *baseBalancer) ResolverError(err error) {
|
||||||
b.resolverErr = err
|
b.resolverErr = err
|
||||||
if len(b.subConns) == 0 {
|
if b.subConns.Len() == 0 {
|
||||||
b.state = connectivity.TransientFailure
|
b.state = connectivity.TransientFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,53 +99,29 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
|
||||||
// Successful resolution; clear resolver error and ensure we return nil.
|
// Successful resolution; clear resolver error and ensure we return nil.
|
||||||
b.resolverErr = nil
|
b.resolverErr = nil
|
||||||
// addrsSet is the set converted from addrs, it's used for quick lookup of an address.
|
// addrsSet is the set converted from addrs, it's used for quick lookup of an address.
|
||||||
addrsSet := make(map[resolver.Address]struct{})
|
addrsSet := resolver.NewAddressMap()
|
||||||
for _, a := range s.ResolverState.Addresses {
|
for _, a := range s.ResolverState.Addresses {
|
||||||
// Strip attributes from addresses before using them as map keys. So
|
addrsSet.Set(a, nil)
|
||||||
// that when two addresses only differ in attributes pointers (but with
|
if _, ok := b.subConns.Get(a); !ok {
|
||||||
// the same attribute content), they are considered the same address.
|
|
||||||
//
|
|
||||||
// Note that this doesn't handle the case where the attribute content is
|
|
||||||
// different. So if users want to set different attributes to create
|
|
||||||
// duplicate connections to the same backend, it doesn't work. This is
|
|
||||||
// fine for now, because duplicate is done by setting Metadata today.
|
|
||||||
//
|
|
||||||
// TODO: read attributes to handle duplicate connections.
|
|
||||||
aNoAttrs := a
|
|
||||||
aNoAttrs.Attributes = nil
|
|
||||||
addrsSet[aNoAttrs] = struct{}{}
|
|
||||||
if scInfo, ok := b.subConns[aNoAttrs]; !ok {
|
|
||||||
// a is a new address (not existing in b.subConns).
|
// a is a new address (not existing in b.subConns).
|
||||||
//
|
|
||||||
// When creating SubConn, the original address with attributes is
|
|
||||||
// passed through. So that connection configurations in attributes
|
|
||||||
// (like creds) will be used.
|
|
||||||
sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck})
|
sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
|
logger.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
b.subConns[aNoAttrs] = subConnInfo{subConn: sc, attrs: a.Attributes}
|
b.subConns.Set(a, sc)
|
||||||
b.scStates[sc] = connectivity.Idle
|
b.scStates[sc] = connectivity.Idle
|
||||||
b.csEvltr.RecordTransition(connectivity.Shutdown, connectivity.Idle)
|
b.csEvltr.RecordTransition(connectivity.Shutdown, connectivity.Idle)
|
||||||
sc.Connect()
|
sc.Connect()
|
||||||
} else {
|
|
||||||
// Always update the subconn's address in case the attributes
|
|
||||||
// changed.
|
|
||||||
//
|
|
||||||
// The SubConn does a reflect.DeepEqual of the new and old
|
|
||||||
// addresses. So this is a noop if the current address is the same
|
|
||||||
// as the old one (including attributes).
|
|
||||||
scInfo.attrs = a.Attributes
|
|
||||||
b.subConns[aNoAttrs] = scInfo
|
|
||||||
b.cc.UpdateAddresses(scInfo.subConn, []resolver.Address{a})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for a, scInfo := range b.subConns {
|
for _, a := range b.subConns.Keys() {
|
||||||
|
sci, _ := b.subConns.Get(a)
|
||||||
|
sc := sci.(balancer.SubConn)
|
||||||
// a was removed by resolver.
|
// a was removed by resolver.
|
||||||
if _, ok := addrsSet[a]; !ok {
|
if _, ok := addrsSet.Get(a); !ok {
|
||||||
b.cc.RemoveSubConn(scInfo.subConn)
|
b.cc.RemoveSubConn(sc)
|
||||||
delete(b.subConns, a)
|
b.subConns.Delete(a)
|
||||||
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
|
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
|
||||||
// The entry will be deleted in UpdateSubConnState.
|
// The entry will be deleted in UpdateSubConnState.
|
||||||
}
|
}
|
||||||
|
@ -193,10 +163,11 @@ func (b *baseBalancer) regeneratePicker() {
|
||||||
readySCs := make(map[balancer.SubConn]SubConnInfo)
|
readySCs := make(map[balancer.SubConn]SubConnInfo)
|
||||||
|
|
||||||
// Filter out all ready SCs from full subConn map.
|
// Filter out all ready SCs from full subConn map.
|
||||||
for addr, scInfo := range b.subConns {
|
for _, addr := range b.subConns.Keys() {
|
||||||
if st, ok := b.scStates[scInfo.subConn]; ok && st == connectivity.Ready {
|
sci, _ := b.subConns.Get(addr)
|
||||||
addr.Attributes = scInfo.attrs
|
sc := sci.(balancer.SubConn)
|
||||||
readySCs[scInfo.subConn] = SubConnInfo{Address: addr}
|
if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
|
||||||
|
readySCs[sc] = SubConnInfo{Address: addr}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs})
|
b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs})
|
||||||
|
|
|
@ -39,7 +39,7 @@ type State struct {
|
||||||
// Set returns a copy of the provided state with attributes containing s. s's
|
// Set returns a copy of the provided state with attributes containing s. s's
|
||||||
// data should not be mutated after calling Set.
|
// data should not be mutated after calling Set.
|
||||||
func Set(state resolver.State, s *State) resolver.State {
|
func Set(state resolver.State, s *State) resolver.State {
|
||||||
state.Attributes = state.Attributes.WithValues(key, s)
|
state.Attributes = state.Attributes.WithValue(key, s)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -37,7 +38,6 @@ import (
|
||||||
"google.golang.org/grpc/internal/backoff"
|
"google.golang.org/grpc/internal/backoff"
|
||||||
"google.golang.org/grpc/internal/channelz"
|
"google.golang.org/grpc/internal/channelz"
|
||||||
"google.golang.org/grpc/internal/grpcsync"
|
"google.golang.org/grpc/internal/grpcsync"
|
||||||
"google.golang.org/grpc/internal/grpcutil"
|
|
||||||
iresolver "google.golang.org/grpc/internal/resolver"
|
iresolver "google.golang.org/grpc/internal/resolver"
|
||||||
"google.golang.org/grpc/internal/transport"
|
"google.golang.org/grpc/internal/transport"
|
||||||
"google.golang.org/grpc/keepalive"
|
"google.golang.org/grpc/keepalive"
|
||||||
|
@ -248,38 +248,15 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the resolver to use.
|
// Determine the resolver to use.
|
||||||
cc.parsedTarget = grpcutil.ParseTarget(cc.target, cc.dopts.copts.Dialer != nil)
|
resolverBuilder, err := cc.parseTargetAndFindResolver()
|
||||||
channelz.Infof(logger, cc.channelzID, "parsed scheme: %q", cc.parsedTarget.Scheme)
|
if err != nil {
|
||||||
resolverBuilder := cc.getResolver(cc.parsedTarget.Scheme)
|
return nil, err
|
||||||
if resolverBuilder == nil {
|
|
||||||
// If resolver builder is still nil, the parsed target's scheme is
|
|
||||||
// not registered. Fallback to default resolver and set Endpoint to
|
|
||||||
// the original target.
|
|
||||||
channelz.Infof(logger, cc.channelzID, "scheme %q not registered, fallback to default scheme", cc.parsedTarget.Scheme)
|
|
||||||
cc.parsedTarget = resolver.Target{
|
|
||||||
Scheme: resolver.GetDefaultScheme(),
|
|
||||||
Endpoint: target,
|
|
||||||
}
|
|
||||||
resolverBuilder = cc.getResolver(cc.parsedTarget.Scheme)
|
|
||||||
if resolverBuilder == nil {
|
|
||||||
return nil, fmt.Errorf("could not get resolver for default scheme: %q", cc.parsedTarget.Scheme)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
cc.authority, err = determineAuthority(cc.parsedTarget.Endpoint, cc.target, cc.dopts)
|
||||||
creds := cc.dopts.copts.TransportCredentials
|
if err != nil {
|
||||||
if creds != nil && creds.Info().ServerName != "" {
|
return nil, err
|
||||||
cc.authority = creds.Info().ServerName
|
|
||||||
} else if cc.dopts.insecure && cc.dopts.authority != "" {
|
|
||||||
cc.authority = cc.dopts.authority
|
|
||||||
} else if strings.HasPrefix(cc.target, "unix:") || strings.HasPrefix(cc.target, "unix-abstract:") {
|
|
||||||
cc.authority = "localhost"
|
|
||||||
} else if strings.HasPrefix(cc.parsedTarget.Endpoint, ":") {
|
|
||||||
cc.authority = "localhost" + cc.parsedTarget.Endpoint
|
|
||||||
} else {
|
|
||||||
// Use endpoint from "scheme://authority/endpoint" as the default
|
|
||||||
// authority for ClientConn.
|
|
||||||
cc.authority = cc.parsedTarget.Endpoint
|
|
||||||
}
|
}
|
||||||
|
channelz.Infof(logger, cc.channelzID, "Channel authority set to %q", cc.authority)
|
||||||
|
|
||||||
if cc.dopts.scChan != nil && !scSet {
|
if cc.dopts.scChan != nil && !scSet {
|
||||||
// Blocking wait for the initial service config.
|
// Blocking wait for the initial service config.
|
||||||
|
@ -902,10 +879,7 @@ func (ac *addrConn) tryUpdateAddrs(addrs []resolver.Address) bool {
|
||||||
// ac.state is Ready, try to find the connected address.
|
// ac.state is Ready, try to find the connected address.
|
||||||
var curAddrFound bool
|
var curAddrFound bool
|
||||||
for _, a := range addrs {
|
for _, a := range addrs {
|
||||||
// a.ServerName takes precedent over ClientConn authority, if present.
|
a.ServerName = ac.cc.getServerName(a)
|
||||||
if a.ServerName == "" {
|
|
||||||
a.ServerName = ac.cc.authority
|
|
||||||
}
|
|
||||||
if reflect.DeepEqual(ac.curAddr, a) {
|
if reflect.DeepEqual(ac.curAddr, a) {
|
||||||
curAddrFound = true
|
curAddrFound = true
|
||||||
break
|
break
|
||||||
|
@ -919,6 +893,26 @@ func (ac *addrConn) tryUpdateAddrs(addrs []resolver.Address) bool {
|
||||||
return curAddrFound
|
return curAddrFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getServerName determines the serverName to be used in the connection
|
||||||
|
// handshake. The default value for the serverName is the authority on the
|
||||||
|
// ClientConn, which either comes from the user's dial target or through an
|
||||||
|
// authority override specified using the WithAuthority dial option. Name
|
||||||
|
// resolvers can specify a per-address override for the serverName through the
|
||||||
|
// resolver.Address.ServerName field which is used only if the WithAuthority
|
||||||
|
// dial option was not used. The rationale is that per-address authority
|
||||||
|
// overrides specified by the name resolver can represent a security risk, while
|
||||||
|
// an override specified by the user is more dependable since they probably know
|
||||||
|
// what they are doing.
|
||||||
|
func (cc *ClientConn) getServerName(addr resolver.Address) string {
|
||||||
|
if cc.dopts.authority != "" {
|
||||||
|
return cc.dopts.authority
|
||||||
|
}
|
||||||
|
if addr.ServerName != "" {
|
||||||
|
return addr.ServerName
|
||||||
|
}
|
||||||
|
return cc.authority
|
||||||
|
}
|
||||||
|
|
||||||
func getMethodConfig(sc *ServiceConfig, method string) MethodConfig {
|
func getMethodConfig(sc *ServiceConfig, method string) MethodConfig {
|
||||||
if sc == nil {
|
if sc == nil {
|
||||||
return MethodConfig{}
|
return MethodConfig{}
|
||||||
|
@ -1275,11 +1269,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
|
||||||
prefaceReceived := grpcsync.NewEvent()
|
prefaceReceived := grpcsync.NewEvent()
|
||||||
connClosed := grpcsync.NewEvent()
|
connClosed := grpcsync.NewEvent()
|
||||||
|
|
||||||
// addr.ServerName takes precedent over ClientConn authority, if present.
|
addr.ServerName = ac.cc.getServerName(addr)
|
||||||
if addr.ServerName == "" {
|
|
||||||
addr.ServerName = ac.cc.authority
|
|
||||||
}
|
|
||||||
|
|
||||||
hctx, hcancel := context.WithCancel(ac.ctx)
|
hctx, hcancel := context.WithCancel(ac.ctx)
|
||||||
hcStarted := false // protected by ac.mu
|
hcStarted := false // protected by ac.mu
|
||||||
|
|
||||||
|
@ -1621,3 +1611,114 @@ func (cc *ClientConn) connectionError() error {
|
||||||
defer cc.lceMu.Unlock()
|
defer cc.lceMu.Unlock()
|
||||||
return cc.lastConnectionError
|
return cc.lastConnectionError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) {
|
||||||
|
channelz.Infof(logger, cc.channelzID, "original dial target is: %q", cc.target)
|
||||||
|
|
||||||
|
var rb resolver.Builder
|
||||||
|
parsedTarget, err := parseTarget(cc.target)
|
||||||
|
if err != nil {
|
||||||
|
channelz.Infof(logger, cc.channelzID, "dial target %q parse failed: %v", cc.target, err)
|
||||||
|
} else {
|
||||||
|
channelz.Infof(logger, cc.channelzID, "parsed dial target is: %+v", parsedTarget)
|
||||||
|
rb = cc.getResolver(parsedTarget.Scheme)
|
||||||
|
if rb != nil {
|
||||||
|
cc.parsedTarget = parsedTarget
|
||||||
|
return rb, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are here because the user's dial target did not contain a scheme or
|
||||||
|
// specified an unregistered scheme. We should fallback to the default
|
||||||
|
// scheme, except when a custom dialer is specified in which case, we should
|
||||||
|
// always use passthrough scheme.
|
||||||
|
defScheme := resolver.GetDefaultScheme()
|
||||||
|
channelz.Infof(logger, cc.channelzID, "fallback to scheme %q", defScheme)
|
||||||
|
canonicalTarget := defScheme + ":///" + cc.target
|
||||||
|
|
||||||
|
parsedTarget, err = parseTarget(canonicalTarget)
|
||||||
|
if err != nil {
|
||||||
|
channelz.Infof(logger, cc.channelzID, "dial target %q parse failed: %v", canonicalTarget, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
channelz.Infof(logger, cc.channelzID, "parsed dial target is: %+v", parsedTarget)
|
||||||
|
rb = cc.getResolver(parsedTarget.Scheme)
|
||||||
|
if rb == nil {
|
||||||
|
return nil, fmt.Errorf("could not get resolver for default scheme: %q", parsedTarget.Scheme)
|
||||||
|
}
|
||||||
|
cc.parsedTarget = parsedTarget
|
||||||
|
return rb, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseTarget uses RFC 3986 semantics to parse the given target into a
|
||||||
|
// resolver.Target struct containing scheme, authority and endpoint. Query
|
||||||
|
// params are stripped from the endpoint.
|
||||||
|
func parseTarget(target string) (resolver.Target, error) {
|
||||||
|
u, err := url.Parse(target)
|
||||||
|
if err != nil {
|
||||||
|
return resolver.Target{}, err
|
||||||
|
}
|
||||||
|
// For targets of the form "[scheme]://[authority]/endpoint, the endpoint
|
||||||
|
// value returned from url.Parse() contains a leading "/". Although this is
|
||||||
|
// in accordance with RFC 3986, we do not want to break existing resolver
|
||||||
|
// implementations which expect the endpoint without the leading "/". So, we
|
||||||
|
// end up stripping the leading "/" here. But this will result in an
|
||||||
|
// incorrect parsing for something like "unix:///path/to/socket". Since we
|
||||||
|
// own the "unix" resolver, we can workaround in the unix resolver by using
|
||||||
|
// the `URL` field instead of the `Endpoint` field.
|
||||||
|
endpoint := u.Path
|
||||||
|
if endpoint == "" {
|
||||||
|
endpoint = u.Opaque
|
||||||
|
}
|
||||||
|
endpoint = strings.TrimPrefix(endpoint, "/")
|
||||||
|
return resolver.Target{
|
||||||
|
Scheme: u.Scheme,
|
||||||
|
Authority: u.Host,
|
||||||
|
Endpoint: endpoint,
|
||||||
|
URL: *u,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine channel authority. The order of precedence is as follows:
|
||||||
|
// - user specified authority override using `WithAuthority` dial option
|
||||||
|
// - creds' notion of server name for the authentication handshake
|
||||||
|
// - endpoint from dial target of the form "scheme://[authority]/endpoint"
|
||||||
|
func determineAuthority(endpoint, target string, dopts dialOptions) (string, error) {
|
||||||
|
// Historically, we had two options for users to specify the serverName or
|
||||||
|
// authority for a channel. One was through the transport credentials
|
||||||
|
// (either in its constructor, or through the OverrideServerName() method).
|
||||||
|
// The other option (for cases where WithInsecure() dial option was used)
|
||||||
|
// was to use the WithAuthority() dial option.
|
||||||
|
//
|
||||||
|
// A few things have changed since:
|
||||||
|
// - `insecure` package with an implementation of the `TransportCredentials`
|
||||||
|
// interface for the insecure case
|
||||||
|
// - WithAuthority() dial option support for secure credentials
|
||||||
|
authorityFromCreds := ""
|
||||||
|
if creds := dopts.copts.TransportCredentials; creds != nil && creds.Info().ServerName != "" {
|
||||||
|
authorityFromCreds = creds.Info().ServerName
|
||||||
|
}
|
||||||
|
authorityFromDialOption := dopts.authority
|
||||||
|
if (authorityFromCreds != "" && authorityFromDialOption != "") && authorityFromCreds != authorityFromDialOption {
|
||||||
|
return "", fmt.Errorf("ClientConn's authority from transport creds %q and dial option %q don't match", authorityFromCreds, authorityFromDialOption)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case authorityFromDialOption != "":
|
||||||
|
return authorityFromDialOption, nil
|
||||||
|
case authorityFromCreds != "":
|
||||||
|
return authorityFromCreds, nil
|
||||||
|
case strings.HasPrefix(target, "unix:") || strings.HasPrefix(target, "unix-abstract:"):
|
||||||
|
// TODO: remove when the unix resolver implements optional interface to
|
||||||
|
// return channel authority.
|
||||||
|
return "localhost", nil
|
||||||
|
case strings.HasPrefix(endpoint, ":"):
|
||||||
|
return "localhost" + endpoint, nil
|
||||||
|
default:
|
||||||
|
// TODO: Define an optional interface on the resolver builder to return
|
||||||
|
// the channel authority given the user's dial target. For resolvers
|
||||||
|
// which don't implement this interface, we will use the endpoint from
|
||||||
|
// "scheme://authority/endpoint" as the default authority.
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -140,6 +140,11 @@ type TransportCredentials interface {
|
||||||
// Additionally, ClientHandshakeInfo data will be available via the context
|
// Additionally, ClientHandshakeInfo data will be available via the context
|
||||||
// passed to this call.
|
// passed to this call.
|
||||||
//
|
//
|
||||||
|
// The second argument to this method is the `:authority` header value used
|
||||||
|
// while creating new streams on this connection after authentication
|
||||||
|
// succeeds. Implementations must use this as the server name during the
|
||||||
|
// authentication handshake.
|
||||||
|
//
|
||||||
// If the returned net.Conn is closed, it MUST close the net.Conn provided.
|
// If the returned net.Conn is closed, it MUST close the net.Conn provided.
|
||||||
ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
|
ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
|
||||||
// ServerHandshake does the authentication handshake for servers. It returns
|
// ServerHandshake does the authentication handshake for servers. It returns
|
||||||
|
@ -153,9 +158,13 @@ type TransportCredentials interface {
|
||||||
Info() ProtocolInfo
|
Info() ProtocolInfo
|
||||||
// Clone makes a copy of this TransportCredentials.
|
// Clone makes a copy of this TransportCredentials.
|
||||||
Clone() TransportCredentials
|
Clone() TransportCredentials
|
||||||
// OverrideServerName overrides the server name used to verify the hostname on the returned certificates from the server.
|
// OverrideServerName specifies the value used for the following:
|
||||||
// gRPC internals also use it to override the virtual hosting name if it is set.
|
// - verifying the hostname on the returned certificates
|
||||||
// It must be called before dialing. Currently, this is only used by grpclb.
|
// - as SNI in the client's handshake to support virtual hosting
|
||||||
|
// - as the value for `:authority` header at stream creation time
|
||||||
|
//
|
||||||
|
// Deprecated: use grpc.WithAuthority instead. Will be supported
|
||||||
|
// throughout 1.x.
|
||||||
OverrideServerName(string) error
|
OverrideServerName(string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -482,8 +482,7 @@ func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithAuthority returns a DialOption that specifies the value to be used as the
|
// WithAuthority returns a DialOption that specifies the value to be used as the
|
||||||
// :authority pseudo-header. This value only works with WithInsecure and has no
|
// :authority pseudo-header and as the server name in authentication handshake.
|
||||||
// effect if TransportCredentials are present.
|
|
||||||
func WithAuthority(a string) DialOption {
|
func WithAuthority(a string) DialOption {
|
||||||
return newFuncDialOption(func(o *dialOptions) {
|
return newFuncDialOption(func(o *dialOptions) {
|
||||||
o.authority = a
|
o.authority = a
|
||||||
|
@ -519,14 +518,16 @@ func WithDisableServiceConfig() DialOption {
|
||||||
// WithDefaultServiceConfig returns a DialOption that configures the default
|
// WithDefaultServiceConfig returns a DialOption that configures the default
|
||||||
// service config, which will be used in cases where:
|
// service config, which will be used in cases where:
|
||||||
//
|
//
|
||||||
// 1. WithDisableServiceConfig is also used.
|
// 1. WithDisableServiceConfig is also used, or
|
||||||
// 2. Resolver does not return a service config or if the resolver returns an
|
|
||||||
// invalid service config.
|
|
||||||
//
|
//
|
||||||
// Experimental
|
// 2. The name resolver does not provide a service config or provides an
|
||||||
|
// invalid service config.
|
||||||
//
|
//
|
||||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
// The parameter s is the JSON representation of the default service config.
|
||||||
// later release.
|
// For more information about service configs, see:
|
||||||
|
// https://github.com/grpc/grpc/blob/master/doc/service_config.md
|
||||||
|
// For a simple example of usage, see:
|
||||||
|
// examples/features/load_balancing/client/main.go
|
||||||
func WithDefaultServiceConfig(s string) DialOption {
|
func WithDefaultServiceConfig(s string) DialOption {
|
||||||
return newFuncDialOption(func(o *dialOptions) {
|
return newFuncDialOption(func(o *dialOptions) {
|
||||||
o.defaultServiceConfigRawJSON = &s
|
o.defaultServiceConfigRawJSON = &s
|
||||||
|
@ -538,14 +539,8 @@ func WithDefaultServiceConfig(s string) DialOption {
|
||||||
// will happen automatically if no data is written to the wire or if the RPC is
|
// will happen automatically if no data is written to the wire or if the RPC is
|
||||||
// unprocessed by the remote server.
|
// unprocessed by the remote server.
|
||||||
//
|
//
|
||||||
// Retry support is currently disabled by default, but will be enabled by
|
// Retry support is currently enabled by default, but may be disabled by
|
||||||
// default in the future. Until then, it may be enabled by setting the
|
// setting the environment variable "GRPC_GO_RETRY" to "off".
|
||||||
// environment variable "GRPC_GO_RETRY" to "on".
|
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
func WithDisableRetry() DialOption {
|
func WithDisableRetry() DialOption {
|
||||||
return newFuncDialOption(func(o *dialOptions) {
|
return newFuncDialOption(func(o *dialOptions) {
|
||||||
o.disableRetry = true
|
o.disableRetry = true
|
||||||
|
|
|
@ -19,11 +19,14 @@
|
||||||
package grpclog
|
package grpclog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"google.golang.org/grpc/internal/grpclog"
|
"google.golang.org/grpc/internal/grpclog"
|
||||||
)
|
)
|
||||||
|
@ -95,8 +98,9 @@ var severityName = []string{
|
||||||
|
|
||||||
// loggerT is the default logger used by grpclog.
|
// loggerT is the default logger used by grpclog.
|
||||||
type loggerT struct {
|
type loggerT struct {
|
||||||
m []*log.Logger
|
m []*log.Logger
|
||||||
v int
|
v int
|
||||||
|
jsonFormat bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLoggerV2 creates a loggerV2 with the provided writers.
|
// NewLoggerV2 creates a loggerV2 with the provided writers.
|
||||||
|
@ -105,19 +109,32 @@ type loggerT struct {
|
||||||
// Warning logs will be written to warningW and infoW.
|
// Warning logs will be written to warningW and infoW.
|
||||||
// Info logs will be written to infoW.
|
// Info logs will be written to infoW.
|
||||||
func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 {
|
func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 {
|
||||||
return NewLoggerV2WithVerbosity(infoW, warningW, errorW, 0)
|
return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and
|
// NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and
|
||||||
// verbosity level.
|
// verbosity level.
|
||||||
func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 {
|
func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 {
|
||||||
|
return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{verbose: v})
|
||||||
|
}
|
||||||
|
|
||||||
|
type loggerV2Config struct {
|
||||||
|
verbose int
|
||||||
|
jsonFormat bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLoggerV2WithConfig(infoW, warningW, errorW io.Writer, c loggerV2Config) LoggerV2 {
|
||||||
var m []*log.Logger
|
var m []*log.Logger
|
||||||
m = append(m, log.New(infoW, severityName[infoLog]+": ", log.LstdFlags))
|
flag := log.LstdFlags
|
||||||
m = append(m, log.New(io.MultiWriter(infoW, warningW), severityName[warningLog]+": ", log.LstdFlags))
|
if c.jsonFormat {
|
||||||
|
flag = 0
|
||||||
|
}
|
||||||
|
m = append(m, log.New(infoW, "", flag))
|
||||||
|
m = append(m, log.New(io.MultiWriter(infoW, warningW), "", flag))
|
||||||
ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal.
|
ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal.
|
||||||
m = append(m, log.New(ew, severityName[errorLog]+": ", log.LstdFlags))
|
m = append(m, log.New(ew, "", flag))
|
||||||
m = append(m, log.New(ew, severityName[fatalLog]+": ", log.LstdFlags))
|
m = append(m, log.New(ew, "", flag))
|
||||||
return &loggerT{m: m, v: v}
|
return &loggerT{m: m, v: c.verbose, jsonFormat: c.jsonFormat}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLoggerV2 creates a loggerV2 to be used as default logger.
|
// newLoggerV2 creates a loggerV2 to be used as default logger.
|
||||||
|
@ -142,58 +159,79 @@ func newLoggerV2() LoggerV2 {
|
||||||
if vl, err := strconv.Atoi(vLevel); err == nil {
|
if vl, err := strconv.Atoi(vLevel); err == nil {
|
||||||
v = vl
|
v = vl
|
||||||
}
|
}
|
||||||
return NewLoggerV2WithVerbosity(infoW, warningW, errorW, v)
|
|
||||||
|
jsonFormat := strings.EqualFold(os.Getenv("GRPC_GO_LOG_FORMATTER"), "json")
|
||||||
|
|
||||||
|
return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{
|
||||||
|
verbose: v,
|
||||||
|
jsonFormat: jsonFormat,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *loggerT) output(severity int, s string) {
|
||||||
|
sevStr := severityName[severity]
|
||||||
|
if !g.jsonFormat {
|
||||||
|
g.m[severity].Output(2, fmt.Sprintf("%v: %v", sevStr, s))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO: we can also include the logging component, but that needs more
|
||||||
|
// (API) changes.
|
||||||
|
b, _ := json.Marshal(map[string]string{
|
||||||
|
"severity": sevStr,
|
||||||
|
"message": s,
|
||||||
|
})
|
||||||
|
g.m[severity].Output(2, string(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Info(args ...interface{}) {
|
func (g *loggerT) Info(args ...interface{}) {
|
||||||
g.m[infoLog].Print(args...)
|
g.output(infoLog, fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Infoln(args ...interface{}) {
|
func (g *loggerT) Infoln(args ...interface{}) {
|
||||||
g.m[infoLog].Println(args...)
|
g.output(infoLog, fmt.Sprintln(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Infof(format string, args ...interface{}) {
|
func (g *loggerT) Infof(format string, args ...interface{}) {
|
||||||
g.m[infoLog].Printf(format, args...)
|
g.output(infoLog, fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Warning(args ...interface{}) {
|
func (g *loggerT) Warning(args ...interface{}) {
|
||||||
g.m[warningLog].Print(args...)
|
g.output(warningLog, fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Warningln(args ...interface{}) {
|
func (g *loggerT) Warningln(args ...interface{}) {
|
||||||
g.m[warningLog].Println(args...)
|
g.output(warningLog, fmt.Sprintln(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Warningf(format string, args ...interface{}) {
|
func (g *loggerT) Warningf(format string, args ...interface{}) {
|
||||||
g.m[warningLog].Printf(format, args...)
|
g.output(warningLog, fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Error(args ...interface{}) {
|
func (g *loggerT) Error(args ...interface{}) {
|
||||||
g.m[errorLog].Print(args...)
|
g.output(errorLog, fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Errorln(args ...interface{}) {
|
func (g *loggerT) Errorln(args ...interface{}) {
|
||||||
g.m[errorLog].Println(args...)
|
g.output(errorLog, fmt.Sprintln(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Errorf(format string, args ...interface{}) {
|
func (g *loggerT) Errorf(format string, args ...interface{}) {
|
||||||
g.m[errorLog].Printf(format, args...)
|
g.output(errorLog, fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Fatal(args ...interface{}) {
|
func (g *loggerT) Fatal(args ...interface{}) {
|
||||||
g.m[fatalLog].Fatal(args...)
|
g.output(fatalLog, fmt.Sprint(args...))
|
||||||
// No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit().
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Fatalln(args ...interface{}) {
|
func (g *loggerT) Fatalln(args ...interface{}) {
|
||||||
g.m[fatalLog].Fatalln(args...)
|
g.output(fatalLog, fmt.Sprintln(args...))
|
||||||
// No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit().
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) Fatalf(format string, args ...interface{}) {
|
func (g *loggerT) Fatalf(format string, args ...interface{}) {
|
||||||
g.m[fatalLog].Fatalf(format, args...)
|
g.output(fatalLog, fmt.Sprintf(format, args...))
|
||||||
// No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit().
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *loggerT) V(l int) bool {
|
func (g *loggerT) V(l int) bool {
|
||||||
|
|
|
@ -33,8 +33,9 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Retry is set if retry is explicitly enabled via "GRPC_GO_RETRY=on" or if XDS retry support is enabled.
|
// Retry is enabled unless explicitly disabled via "GRPC_GO_RETRY=off" or
|
||||||
Retry = strings.EqualFold(os.Getenv(retryStr), "on") || xdsenv.RetrySupport
|
// if XDS retry support is explicitly disabled.
|
||||||
|
Retry = !strings.EqualFold(os.Getenv(retryStr), "off") && xdsenv.RetrySupport
|
||||||
// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
|
// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
|
||||||
TXTErrIgnore = !strings.EqualFold(os.Getenv(txtErrIgnoreStr), "false")
|
TXTErrIgnore = !strings.EqualFold(os.Getenv(txtErrIgnoreStr), "false")
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,15 +4,13 @@ go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
"encode_duration.go",
|
"encode_duration.go",
|
||||||
|
"grpcutil.go",
|
||||||
"metadata.go",
|
"metadata.go",
|
||||||
"method.go",
|
"method.go",
|
||||||
"target.go",
|
"regex.go",
|
||||||
],
|
],
|
||||||
importmap = "k8s.io/kops/vendor/google.golang.org/grpc/internal/grpcutil",
|
importmap = "k8s.io/kops/vendor/google.golang.org/grpc/internal/grpcutil",
|
||||||
importpath = "google.golang.org/grpc/internal/grpcutil",
|
importpath = "google.golang.org/grpc/internal/grpcutil",
|
||||||
visibility = ["//vendor/google.golang.org/grpc:__subpackages__"],
|
visibility = ["//vendor/google.golang.org/grpc:__subpackages__"],
|
||||||
deps = [
|
deps = ["//vendor/google.golang.org/grpc/metadata:go_default_library"],
|
||||||
"//vendor/google.golang.org/grpc/metadata:go_default_library",
|
|
||||||
"//vendor/google.golang.org/grpc/resolver:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright 2021 gRPC 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 grpcutil provides utility functions used across the gRPC codebase.
|
||||||
|
package grpcutil
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright 2021 gRPC 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 grpcutil
|
||||||
|
|
||||||
|
import "regexp"
|
||||||
|
|
||||||
|
// FullMatchWithRegex returns whether the full string matches the regex provided.
|
||||||
|
func FullMatchWithRegex(re *regexp.Regexp, string string) bool {
|
||||||
|
re.Longest()
|
||||||
|
rem := re.FindString(string)
|
||||||
|
return len(rem) == len(string)
|
||||||
|
}
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2020 gRPC 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 grpcutil provides a bunch of utility functions to be used across the
|
|
||||||
// gRPC codebase.
|
|
||||||
package grpcutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"google.golang.org/grpc/resolver"
|
|
||||||
)
|
|
||||||
|
|
||||||
// split2 returns the values from strings.SplitN(s, sep, 2).
|
|
||||||
// If sep is not found, it returns ("", "", false) instead.
|
|
||||||
func split2(s, sep string) (string, string, bool) {
|
|
||||||
spl := strings.SplitN(s, sep, 2)
|
|
||||||
if len(spl) < 2 {
|
|
||||||
return "", "", false
|
|
||||||
}
|
|
||||||
return spl[0], spl[1], true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseTarget splits target into a resolver.Target struct containing scheme,
|
|
||||||
// authority and endpoint. skipUnixColonParsing indicates that the parse should
|
|
||||||
// not parse "unix:[path]" cases. This should be true in cases where a custom
|
|
||||||
// dialer is present, to prevent a behavior change.
|
|
||||||
//
|
|
||||||
// If target is not a valid scheme://authority/endpoint as specified in
|
|
||||||
// https://github.com/grpc/grpc/blob/master/doc/naming.md,
|
|
||||||
// it returns {Endpoint: target}.
|
|
||||||
func ParseTarget(target string, skipUnixColonParsing bool) (ret resolver.Target) {
|
|
||||||
var ok bool
|
|
||||||
if strings.HasPrefix(target, "unix-abstract:") {
|
|
||||||
if strings.HasPrefix(target, "unix-abstract://") {
|
|
||||||
// Maybe, with Authority specified, try to parse it
|
|
||||||
var remain string
|
|
||||||
ret.Scheme, remain, _ = split2(target, "://")
|
|
||||||
ret.Authority, ret.Endpoint, ok = split2(remain, "/")
|
|
||||||
if !ok {
|
|
||||||
// No Authority, add the "//" back
|
|
||||||
ret.Endpoint = "//" + remain
|
|
||||||
} else {
|
|
||||||
// Found Authority, add the "/" back
|
|
||||||
ret.Endpoint = "/" + ret.Endpoint
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Without Authority specified, split target on ":"
|
|
||||||
ret.Scheme, ret.Endpoint, _ = split2(target, ":")
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
ret.Scheme, ret.Endpoint, ok = split2(target, "://")
|
|
||||||
if !ok {
|
|
||||||
if strings.HasPrefix(target, "unix:") && !skipUnixColonParsing {
|
|
||||||
// Handle the "unix:[local/path]" and "unix:[/absolute/path]" cases,
|
|
||||||
// because splitting on :// only handles the
|
|
||||||
// "unix://[/absolute/path]" case. Only handle if the dialer is nil,
|
|
||||||
// to avoid a behavior change with custom dialers.
|
|
||||||
return resolver.Target{Scheme: "unix", Endpoint: target[len("unix:"):]}
|
|
||||||
}
|
|
||||||
return resolver.Target{Endpoint: target}
|
|
||||||
}
|
|
||||||
ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/")
|
|
||||||
if !ok {
|
|
||||||
return resolver.Target{Endpoint: target}
|
|
||||||
}
|
|
||||||
if ret.Scheme == "unix" {
|
|
||||||
// Add the "/" back in the unix case, so the unix resolver receives the
|
|
||||||
// actual endpoint in the "unix://[/absolute/path]" case.
|
|
||||||
ret.Endpoint = "/" + ret.Endpoint
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
|
@ -30,14 +30,38 @@ type mdKeyType string
|
||||||
|
|
||||||
const mdKey = mdKeyType("grpc.internal.address.metadata")
|
const mdKey = mdKeyType("grpc.internal.address.metadata")
|
||||||
|
|
||||||
|
type mdValue metadata.MD
|
||||||
|
|
||||||
|
func (m mdValue) Equal(o interface{}) bool {
|
||||||
|
om, ok := o.(mdValue)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(m) != len(om) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for k, v := range m {
|
||||||
|
ov := om[k]
|
||||||
|
if len(ov) != len(v) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, ve := range v {
|
||||||
|
if ov[i] != ve {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the metadata of addr.
|
// Get returns the metadata of addr.
|
||||||
func Get(addr resolver.Address) metadata.MD {
|
func Get(addr resolver.Address) metadata.MD {
|
||||||
attrs := addr.Attributes
|
attrs := addr.Attributes
|
||||||
if attrs == nil {
|
if attrs == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
md, _ := attrs.Value(mdKey).(metadata.MD)
|
md, _ := attrs.Value(mdKey).(mdValue)
|
||||||
return md
|
return metadata.MD(md)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets (overrides) the metadata in addr.
|
// Set sets (overrides) the metadata in addr.
|
||||||
|
@ -45,6 +69,6 @@ func Get(addr resolver.Address) metadata.MD {
|
||||||
// When a SubConn is created with this address, the RPCs sent on it will all
|
// When a SubConn is created with this address, the RPCs sent on it will all
|
||||||
// have this metadata.
|
// have this metadata.
|
||||||
func Set(addr resolver.Address, md metadata.MD) resolver.Address {
|
func Set(addr resolver.Address, md metadata.MD) resolver.Address {
|
||||||
addr.Attributes = addr.Attributes.WithValues(mdKey, md)
|
addr.Attributes = addr.Attributes.WithValue(mdKey, mdValue(md))
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ const csKey = csKeyType("grpc.internal.resolver.configSelector")
|
||||||
// SetConfigSelector sets the config selector in state and returns the new
|
// SetConfigSelector sets the config selector in state and returns the new
|
||||||
// state.
|
// state.
|
||||||
func SetConfigSelector(state resolver.State, cs ConfigSelector) resolver.State {
|
func SetConfigSelector(state resolver.State, cs ConfigSelector) resolver.State {
|
||||||
state.Attributes = state.Attributes.WithValues(csKey, cs)
|
state.Attributes = state.Attributes.WithValue(csKey, cs)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,17 @@ func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolv
|
||||||
if target.Authority != "" {
|
if target.Authority != "" {
|
||||||
return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.Authority)
|
return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.Authority)
|
||||||
}
|
}
|
||||||
addr := resolver.Address{Addr: target.Endpoint}
|
|
||||||
|
// gRPC was parsing the dial target manually before PR #4817, and we
|
||||||
|
// switched to using url.Parse() in that PR. To avoid breaking existing
|
||||||
|
// resolver implementations we ended up stripping the leading "/" from the
|
||||||
|
// endpoint. This obviously does not work for the "unix" scheme. Hence we
|
||||||
|
// end up using the parsed URL instead.
|
||||||
|
endpoint := target.URL.Path
|
||||||
|
if endpoint == "" {
|
||||||
|
endpoint = target.URL.Opaque
|
||||||
|
}
|
||||||
|
addr := resolver.Address{Addr: endpoint}
|
||||||
if b.scheme == unixAbstractScheme {
|
if b.scheme == unixAbstractScheme {
|
||||||
// prepend "\x00" to address for unix-abstract
|
// prepend "\x00" to address for unix-abstract
|
||||||
addr.Addr = "\x00" + addr.Addr
|
addr.Addr = "\x00" + addr.Addr
|
||||||
|
|
|
@ -133,6 +133,7 @@ type cleanupStream struct {
|
||||||
func (c *cleanupStream) isTransportResponseFrame() bool { return c.rst } // Results in a RST_STREAM
|
func (c *cleanupStream) isTransportResponseFrame() bool { return c.rst } // Results in a RST_STREAM
|
||||||
|
|
||||||
type earlyAbortStream struct {
|
type earlyAbortStream struct {
|
||||||
|
httpStatus uint32
|
||||||
streamID uint32
|
streamID uint32
|
||||||
contentSubtype string
|
contentSubtype string
|
||||||
status *status.Status
|
status *status.Status
|
||||||
|
@ -771,9 +772,12 @@ func (l *loopyWriter) earlyAbortStreamHandler(eas *earlyAbortStream) error {
|
||||||
if l.side == clientSide {
|
if l.side == clientSide {
|
||||||
return errors.New("earlyAbortStream not handled on client")
|
return errors.New("earlyAbortStream not handled on client")
|
||||||
}
|
}
|
||||||
|
// In case the caller forgets to set the http status, default to 200.
|
||||||
|
if eas.httpStatus == 0 {
|
||||||
|
eas.httpStatus = 200
|
||||||
|
}
|
||||||
headerFields := []hpack.HeaderField{
|
headerFields := []hpack.HeaderField{
|
||||||
{Name: ":status", Value: "200"},
|
{Name: ":status", Value: strconv.Itoa(int(eas.httpStatus))},
|
||||||
{Name: "content-type", Value: grpcutil.ContentType(eas.contentSubtype)},
|
{Name: "content-type", Value: grpcutil.ContentType(eas.contentSubtype)},
|
||||||
{Name: "grpc-status", Value: strconv.Itoa(int(eas.status.Code()))},
|
{Name: "grpc-status", Value: strconv.Itoa(int(eas.status.Code()))},
|
||||||
{Name: "grpc-message", Value: encodeGrpcMessage(eas.status.Message())},
|
{Name: "grpc-message", Value: encodeGrpcMessage(eas.status.Message())},
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -146,13 +147,20 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error
|
||||||
address := addr.Addr
|
address := addr.Addr
|
||||||
networkType, ok := networktype.Get(addr)
|
networkType, ok := networktype.Get(addr)
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
|
// Special handling for unix scheme with custom dialer. Back in the day,
|
||||||
|
// we did not have a unix resolver and therefore targets with a unix
|
||||||
|
// scheme would end up using the passthrough resolver. So, user's used a
|
||||||
|
// custom dialer in this case and expected the original dial target to
|
||||||
|
// be passed to the custom dialer. Now, we have a unix resolver. But if
|
||||||
|
// a custom dialer is specified, we want to retain the old behavior in
|
||||||
|
// terms of the address being passed to the custom dialer.
|
||||||
if networkType == "unix" && !strings.HasPrefix(address, "\x00") {
|
if networkType == "unix" && !strings.HasPrefix(address, "\x00") {
|
||||||
// For backward compatibility, if the user dialed "unix:///path",
|
// Supported unix targets are either "unix://absolute-path" or
|
||||||
// the passthrough resolver would be used and the user's custom
|
// "unix:relative-path".
|
||||||
// dialer would see "unix:///path". Since the unix resolver is used
|
if filepath.IsAbs(address) {
|
||||||
// and the address is now "/path", prepend "unix://" so the user's
|
return fn(ctx, "unix://"+address)
|
||||||
// custom dialer sees the same address.
|
}
|
||||||
return fn(ctx, "unix://"+address)
|
return fn(ctx, "unix:"+address)
|
||||||
}
|
}
|
||||||
return fn(ctx, address)
|
return fn(ctx, address)
|
||||||
}
|
}
|
||||||
|
@ -1073,7 +1081,7 @@ func (t *http2Client) handleData(f *http2.DataFrame) {
|
||||||
}
|
}
|
||||||
// The server has closed the stream without sending trailers. Record that
|
// The server has closed the stream without sending trailers. Record that
|
||||||
// the read direction is closed, and set the status appropriately.
|
// the read direction is closed, and set the status appropriately.
|
||||||
if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) {
|
if f.StreamEnded() {
|
||||||
t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.New(codes.Internal, "server closed the stream without sending trailers"), nil, true)
|
t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.New(codes.Internal, "server closed the stream without sending trailers"), nil, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1403,26 +1411,6 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
|
||||||
}
|
}
|
||||||
|
|
||||||
isHeader := false
|
isHeader := false
|
||||||
defer func() {
|
|
||||||
if t.statsHandler != nil {
|
|
||||||
if isHeader {
|
|
||||||
inHeader := &stats.InHeader{
|
|
||||||
Client: true,
|
|
||||||
WireLength: int(frame.Header().Length),
|
|
||||||
Header: s.header.Copy(),
|
|
||||||
Compression: s.recvCompress,
|
|
||||||
}
|
|
||||||
t.statsHandler.HandleRPC(s.ctx, inHeader)
|
|
||||||
} else {
|
|
||||||
inTrailer := &stats.InTrailer{
|
|
||||||
Client: true,
|
|
||||||
WireLength: int(frame.Header().Length),
|
|
||||||
Trailer: s.trailer.Copy(),
|
|
||||||
}
|
|
||||||
t.statsHandler.HandleRPC(s.ctx, inTrailer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// If headerChan hasn't been closed yet
|
// If headerChan hasn't been closed yet
|
||||||
if atomic.CompareAndSwapUint32(&s.headerChanClosed, 0, 1) {
|
if atomic.CompareAndSwapUint32(&s.headerChanClosed, 0, 1) {
|
||||||
|
@ -1444,6 +1432,25 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
|
||||||
close(s.headerChan)
|
close(s.headerChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t.statsHandler != nil {
|
||||||
|
if isHeader {
|
||||||
|
inHeader := &stats.InHeader{
|
||||||
|
Client: true,
|
||||||
|
WireLength: int(frame.Header().Length),
|
||||||
|
Header: metadata.MD(mdata).Copy(),
|
||||||
|
Compression: s.recvCompress,
|
||||||
|
}
|
||||||
|
t.statsHandler.HandleRPC(s.ctx, inHeader)
|
||||||
|
} else {
|
||||||
|
inTrailer := &stats.InTrailer{
|
||||||
|
Client: true,
|
||||||
|
WireLength: int(frame.Header().Length),
|
||||||
|
Trailer: metadata.MD(mdata).Copy(),
|
||||||
|
}
|
||||||
|
t.statsHandler.HandleRPC(s.ctx, inTrailer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !endStream {
|
if !endStream {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ type http2Server struct {
|
||||||
// options from config.
|
// options from config.
|
||||||
//
|
//
|
||||||
// It returns a non-nil transport and a nil error on success. On failure, it
|
// It returns a non-nil transport and a nil error on success. On failure, it
|
||||||
// returns a non-nil transport and a nil-error. For a special case where the
|
// returns a nil transport and a non-nil error. For a special case where the
|
||||||
// underlying conn gets closed before the client preface could be read, it
|
// underlying conn gets closed before the client preface could be read, it
|
||||||
// returns a nil transport and a nil error.
|
// returns a nil transport and a nil error.
|
||||||
func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) {
|
func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) {
|
||||||
|
@ -290,10 +290,11 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
||||||
if _, err := io.ReadFull(t.conn, preface); err != nil {
|
if _, err := io.ReadFull(t.conn, preface); err != nil {
|
||||||
// In deployments where a gRPC server runs behind a cloud load balancer
|
// In deployments where a gRPC server runs behind a cloud load balancer
|
||||||
// which performs regular TCP level health checks, the connection is
|
// which performs regular TCP level health checks, the connection is
|
||||||
// closed immediately by the latter. Skipping the error here will help
|
// closed immediately by the latter. Returning io.EOF here allows the
|
||||||
// reduce log clutter.
|
// grpc server implementation to recognize this scenario and suppress
|
||||||
|
// logging to reduce spam.
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return nil, nil
|
return nil, io.EOF
|
||||||
}
|
}
|
||||||
return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err)
|
return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -390,6 +391,13 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||||
if timeout, err = decodeTimeout(hf.Value); err != nil {
|
if timeout, err = decodeTimeout(hf.Value); err != nil {
|
||||||
headerError = true
|
headerError = true
|
||||||
}
|
}
|
||||||
|
// "Transports must consider requests containing the Connection header
|
||||||
|
// as malformed." - A41
|
||||||
|
case "connection":
|
||||||
|
if logger.V(logLevel) {
|
||||||
|
logger.Errorf("transport: http2Server.operateHeaders parsed a :connection header which makes a request malformed as per the HTTP/2 spec")
|
||||||
|
}
|
||||||
|
headerError = true
|
||||||
default:
|
default:
|
||||||
if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) {
|
if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) {
|
||||||
break
|
break
|
||||||
|
@ -404,6 +412,25 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "If multiple Host headers or multiple :authority headers are present, the
|
||||||
|
// request must be rejected with an HTTP status code 400 as required by Host
|
||||||
|
// validation in RFC 7230 §5.4, gRPC status code INTERNAL, or RST_STREAM
|
||||||
|
// with HTTP/2 error code PROTOCOL_ERROR." - A41. Since this is a HTTP/2
|
||||||
|
// error, this takes precedence over a client not speaking gRPC.
|
||||||
|
if len(mdata[":authority"]) > 1 || len(mdata["host"]) > 1 {
|
||||||
|
errMsg := fmt.Sprintf("num values of :authority: %v, num values of host: %v, both must only have 1 value as per HTTP/2 spec", len(mdata[":authority"]), len(mdata["host"]))
|
||||||
|
if logger.V(logLevel) {
|
||||||
|
logger.Errorf("transport: %v", errMsg)
|
||||||
|
}
|
||||||
|
t.controlBuf.put(&earlyAbortStream{
|
||||||
|
httpStatus: 400,
|
||||||
|
streamID: streamID,
|
||||||
|
contentSubtype: s.contentSubtype,
|
||||||
|
status: status.New(codes.Internal, errMsg),
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
if !isGRPC || headerError {
|
if !isGRPC || headerError {
|
||||||
t.controlBuf.put(&cleanupStream{
|
t.controlBuf.put(&cleanupStream{
|
||||||
streamID: streamID,
|
streamID: streamID,
|
||||||
|
@ -414,6 +441,19 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "If :authority is missing, Host must be renamed to :authority." - A41
|
||||||
|
if len(mdata[":authority"]) == 0 {
|
||||||
|
// No-op if host isn't present, no eventual :authority header is a valid
|
||||||
|
// RPC.
|
||||||
|
if host, ok := mdata["host"]; ok {
|
||||||
|
mdata[":authority"] = host
|
||||||
|
delete(mdata, "host")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// "If :authority is present, Host must be discarded" - A41
|
||||||
|
delete(mdata, "host")
|
||||||
|
}
|
||||||
|
|
||||||
if frame.StreamEnded() {
|
if frame.StreamEnded() {
|
||||||
// s is just created by the caller. No lock needed.
|
// s is just created by the caller. No lock needed.
|
||||||
s.state = streamReadDone
|
s.state = streamReadDone
|
||||||
|
@ -494,6 +534,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||||
stat = status.New(codes.PermissionDenied, err.Error())
|
stat = status.New(codes.PermissionDenied, err.Error())
|
||||||
}
|
}
|
||||||
t.controlBuf.put(&earlyAbortStream{
|
t.controlBuf.put(&earlyAbortStream{
|
||||||
|
httpStatus: 200,
|
||||||
streamID: s.id,
|
streamID: s.id,
|
||||||
contentSubtype: s.contentSubtype,
|
contentSubtype: s.contentSubtype,
|
||||||
status: stat,
|
status: stat,
|
||||||
|
@ -734,7 +775,7 @@ func (t *http2Server) handleData(f *http2.DataFrame) {
|
||||||
s.write(recvMsg{buffer: buffer})
|
s.write(recvMsg{buffer: buffer})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f.Header().Flags.Has(http2.FlagDataEndStream) {
|
if f.StreamEnded() {
|
||||||
// Received the end of stream from the client.
|
// Received the end of stream from the client.
|
||||||
s.compareAndSwapState(streamActive, streamReadDone)
|
s.compareAndSwapState(streamActive, streamReadDone)
|
||||||
s.write(recvMsg{err: io.EOF})
|
s.write(recvMsg{err: io.EOF})
|
||||||
|
|
|
@ -31,7 +31,7 @@ const key = keyType("grpc.internal.transport.networktype")
|
||||||
|
|
||||||
// Set returns a copy of the provided address with attributes containing networkType.
|
// Set returns a copy of the provided address with attributes containing networkType.
|
||||||
func Set(address resolver.Address, networkType string) resolver.Address {
|
func Set(address resolver.Address, networkType string) resolver.Address {
|
||||||
address.Attributes = address.Attributes.WithValues(key, networkType)
|
address.Attributes = address.Attributes.WithValue(key, networkType)
|
||||||
return address
|
return address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ const (
|
||||||
clientSideSecuritySupportEnv = "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT"
|
clientSideSecuritySupportEnv = "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT"
|
||||||
aggregateAndDNSSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"
|
aggregateAndDNSSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"
|
||||||
retrySupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_RETRY"
|
retrySupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_RETRY"
|
||||||
rbacSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_RBAC"
|
rbacSupportEnv = "GRPC_XDS_EXPERIMENTAL_RBAC"
|
||||||
|
|
||||||
c2pResolverSupportEnv = "GRPC_EXPERIMENTAL_GOOGLE_C2P_RESOLVER"
|
c2pResolverSupportEnv = "GRPC_EXPERIMENTAL_GOOGLE_C2P_RESOLVER"
|
||||||
c2pResolverTestOnlyTrafficDirectorURIEnv = "GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI"
|
c2pResolverTestOnlyTrafficDirectorURIEnv = "GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI"
|
||||||
|
@ -83,8 +83,10 @@ var (
|
||||||
// RetrySupport indicates whether xDS retry is enabled.
|
// RetrySupport indicates whether xDS retry is enabled.
|
||||||
RetrySupport = !strings.EqualFold(os.Getenv(retrySupportEnv), "false")
|
RetrySupport = !strings.EqualFold(os.Getenv(retrySupportEnv), "false")
|
||||||
|
|
||||||
// RBACSupport indicates whether xDS configured RBAC HTTP Filter is enabled.
|
// RBACSupport indicates whether xDS configured RBAC HTTP Filter is enabled,
|
||||||
RBACSupport = strings.EqualFold(os.Getenv(rbacSupportEnv), "true")
|
// which can be disabled by setting the environment variable
|
||||||
|
// "GRPC_XDS_EXPERIMENTAL_RBAC" to "false".
|
||||||
|
RBACSupport = !strings.EqualFold(os.Getenv(rbacSupportEnv), "false")
|
||||||
|
|
||||||
// C2PResolverSupport indicates whether support for C2P resolver is enabled.
|
// C2PResolverSupport indicates whether support for C2P resolver is enabled.
|
||||||
// This can be enabled by setting the environment variable
|
// This can be enabled by setting the environment variable
|
||||||
|
|
|
@ -28,7 +28,7 @@ type handshakeClusterNameKey struct{}
|
||||||
// SetXDSHandshakeClusterName returns a copy of addr in which the Attributes field
|
// SetXDSHandshakeClusterName returns a copy of addr in which the Attributes field
|
||||||
// is updated with the cluster name.
|
// is updated with the cluster name.
|
||||||
func SetXDSHandshakeClusterName(addr resolver.Address, clusterName string) resolver.Address {
|
func SetXDSHandshakeClusterName(addr resolver.Address, clusterName string) resolver.Address {
|
||||||
addr.Attributes = addr.Attributes.WithValues(handshakeClusterNameKey{}, clusterName)
|
addr.Attributes = addr.Attributes.WithValue(handshakeClusterNameKey{}, clusterName)
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
|
||||||
|
|
||||||
acw, ok := pickResult.SubConn.(*acBalancerWrapper)
|
acw, ok := pickResult.SubConn.(*acBalancerWrapper)
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Error("subconn returned from pick is not *acBalancerWrapper")
|
logger.Errorf("subconn returned from pick is type %T, not *acBalancerWrapper", pickResult.SubConn)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if t := acw.getAddrConn().getReadyTransport(); t != nil {
|
if t := acw.getAddrConn().getReadyTransport(); t != nil {
|
||||||
|
|
|
@ -2,7 +2,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = ["resolver.go"],
|
srcs = [
|
||||||
|
"map.go",
|
||||||
|
"resolver.go",
|
||||||
|
],
|
||||||
importmap = "k8s.io/kops/vendor/google.golang.org/grpc/resolver",
|
importmap = "k8s.io/kops/vendor/google.golang.org/grpc/resolver",
|
||||||
importpath = "google.golang.org/grpc/resolver",
|
importpath = "google.golang.org/grpc/resolver",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright 2021 gRPC 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 resolver
|
||||||
|
|
||||||
|
type addressMapEntry struct {
|
||||||
|
addr Address
|
||||||
|
value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddressMap is a map of addresses to arbitrary values taking into account
|
||||||
|
// Attributes. BalancerAttributes are ignored, as are Metadata and Type.
|
||||||
|
// Multiple accesses may not be performed concurrently. Must be created via
|
||||||
|
// NewAddressMap; do not construct directly.
|
||||||
|
type AddressMap struct {
|
||||||
|
m map[string]addressMapEntryList
|
||||||
|
}
|
||||||
|
|
||||||
|
type addressMapEntryList []*addressMapEntry
|
||||||
|
|
||||||
|
// NewAddressMap creates a new AddressMap.
|
||||||
|
func NewAddressMap() *AddressMap {
|
||||||
|
return &AddressMap{m: make(map[string]addressMapEntryList)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find returns the index of addr in the addressMapEntry slice, or -1 if not
|
||||||
|
// present.
|
||||||
|
func (l addressMapEntryList) find(addr Address) int {
|
||||||
|
if len(l) == 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
for i, entry := range l {
|
||||||
|
if entry.addr.ServerName == addr.ServerName &&
|
||||||
|
entry.addr.Attributes.Equal(addr.Attributes) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the value for the address in the map, if present.
|
||||||
|
func (a *AddressMap) Get(addr Address) (value interface{}, ok bool) {
|
||||||
|
entryList := a.m[addr.Addr]
|
||||||
|
if entry := entryList.find(addr); entry != -1 {
|
||||||
|
return entryList[entry].value, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set updates or adds the value to the address in the map.
|
||||||
|
func (a *AddressMap) Set(addr Address, value interface{}) {
|
||||||
|
entryList := a.m[addr.Addr]
|
||||||
|
if entry := entryList.find(addr); entry != -1 {
|
||||||
|
a.m[addr.Addr][entry].value = value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.m[addr.Addr] = append(a.m[addr.Addr], &addressMapEntry{addr: addr, value: value})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete removes addr from the map.
|
||||||
|
func (a *AddressMap) Delete(addr Address) {
|
||||||
|
entryList := a.m[addr.Addr]
|
||||||
|
entry := entryList.find(addr)
|
||||||
|
if entry == -1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(entryList) == 1 {
|
||||||
|
entryList = nil
|
||||||
|
} else {
|
||||||
|
copy(entryList[entry:], entryList[entry+1:])
|
||||||
|
entryList = entryList[:len(entryList)-1]
|
||||||
|
}
|
||||||
|
a.m[addr.Addr] = entryList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of entries in the map.
|
||||||
|
func (a *AddressMap) Len() int {
|
||||||
|
ret := 0
|
||||||
|
for _, entryList := range a.m {
|
||||||
|
ret += len(entryList)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns a slice of all current map keys.
|
||||||
|
func (a *AddressMap) Keys() []Address {
|
||||||
|
ret := make([]Address, 0, a.Len())
|
||||||
|
for _, entryList := range a.m {
|
||||||
|
for _, entry := range entryList {
|
||||||
|
ret = append(ret, entry.addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ package resolver
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"google.golang.org/grpc/attributes"
|
"google.golang.org/grpc/attributes"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
@ -116,9 +117,14 @@ type Address struct {
|
||||||
ServerName string
|
ServerName string
|
||||||
|
|
||||||
// Attributes contains arbitrary data about this address intended for
|
// Attributes contains arbitrary data about this address intended for
|
||||||
// consumption by the load balancing policy.
|
// consumption by the SubConn.
|
||||||
Attributes *attributes.Attributes
|
Attributes *attributes.Attributes
|
||||||
|
|
||||||
|
// BalancerAttributes contains arbitrary data about this address intended
|
||||||
|
// for consumption by the LB policy. These attribes do not affect SubConn
|
||||||
|
// creation, connection establishment, handshaking, etc.
|
||||||
|
BalancerAttributes *attributes.Attributes
|
||||||
|
|
||||||
// Type is the type of this address.
|
// Type is the type of this address.
|
||||||
//
|
//
|
||||||
// Deprecated: use Attributes instead.
|
// Deprecated: use Attributes instead.
|
||||||
|
@ -131,6 +137,15 @@ type Address struct {
|
||||||
Metadata interface{}
|
Metadata interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Equal returns whether a and o are identical. Metadata is compared directly,
|
||||||
|
// not with any recursive introspection.
|
||||||
|
func (a *Address) Equal(o Address) bool {
|
||||||
|
return a.Addr == o.Addr && a.ServerName == o.ServerName &&
|
||||||
|
a.Attributes.Equal(o.Attributes) &&
|
||||||
|
a.BalancerAttributes.Equal(o.BalancerAttributes) &&
|
||||||
|
a.Type == o.Type && a.Metadata == o.Metadata
|
||||||
|
}
|
||||||
|
|
||||||
// BuildOptions includes additional information for the builder to create
|
// BuildOptions includes additional information for the builder to create
|
||||||
// the resolver.
|
// the resolver.
|
||||||
type BuildOptions struct {
|
type BuildOptions struct {
|
||||||
|
@ -204,25 +219,36 @@ type ClientConn interface {
|
||||||
|
|
||||||
// Target represents a target for gRPC, as specified in:
|
// Target represents a target for gRPC, as specified in:
|
||||||
// https://github.com/grpc/grpc/blob/master/doc/naming.md.
|
// https://github.com/grpc/grpc/blob/master/doc/naming.md.
|
||||||
// It is parsed from the target string that gets passed into Dial or DialContext by the user. And
|
// It is parsed from the target string that gets passed into Dial or DialContext
|
||||||
// grpc passes it to the resolver and the balancer.
|
// by the user. And gRPC passes it to the resolver and the balancer.
|
||||||
//
|
//
|
||||||
// If the target follows the naming spec, and the parsed scheme is registered with grpc, we will
|
// If the target follows the naming spec, and the parsed scheme is registered
|
||||||
// parse the target string according to the spec. e.g. "dns://some_authority/foo.bar" will be parsed
|
// with gRPC, we will parse the target string according to the spec. If the
|
||||||
// into &Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"}
|
// target does not contain a scheme or if the parsed scheme is not registered
|
||||||
|
// (i.e. no corresponding resolver available to resolve the endpoint), we will
|
||||||
|
// apply the default scheme, and will attempt to reparse it.
|
||||||
//
|
//
|
||||||
// If the target does not contain a scheme, we will apply the default scheme, and set the Target to
|
// Examples:
|
||||||
// be the full target string. e.g. "foo.bar" will be parsed into
|
|
||||||
// &Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "foo.bar"}.
|
|
||||||
//
|
//
|
||||||
// If the parsed scheme is not registered (i.e. no corresponding resolver available to resolve the
|
// - "dns://some_authority/foo.bar"
|
||||||
// endpoint), we set the Scheme to be the default scheme, and set the Endpoint to be the full target
|
// Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"}
|
||||||
// string. e.g. target string "unknown_scheme://authority/endpoint" will be parsed into
|
// - "foo.bar"
|
||||||
// &Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "unknown_scheme://authority/endpoint"}.
|
// Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "foo.bar"}
|
||||||
|
// - "unknown_scheme://authority/endpoint"
|
||||||
|
// Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "unknown_scheme://authority/endpoint"}
|
||||||
type Target struct {
|
type Target struct {
|
||||||
Scheme string
|
// Deprecated: use URL.Scheme instead.
|
||||||
|
Scheme string
|
||||||
|
// Deprecated: use URL.Host instead.
|
||||||
Authority string
|
Authority string
|
||||||
Endpoint string
|
// Deprecated: use URL.Path or URL.Opaque instead. The latter is set when
|
||||||
|
// the former is empty.
|
||||||
|
Endpoint string
|
||||||
|
// URL contains the parsed dial target with an optional default scheme added
|
||||||
|
// to it if the original dial target contained no scheme or contained an
|
||||||
|
// unregistered scheme. Any query params specified in the original dial
|
||||||
|
// target can be accessed from here.
|
||||||
|
URL url.URL
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builder creates a resolver that will be used to watch name resolution updates.
|
// Builder creates a resolver that will be used to watch name resolution updates.
|
||||||
|
|
|
@ -885,13 +885,11 @@ func (s *Server) newHTTP2Transport(c net.Conn) transport.ServerTransport {
|
||||||
// ErrConnDispatched means that the connection was dispatched away from
|
// ErrConnDispatched means that the connection was dispatched away from
|
||||||
// gRPC; those connections should be left open.
|
// gRPC; those connections should be left open.
|
||||||
if err != credentials.ErrConnDispatched {
|
if err != credentials.ErrConnDispatched {
|
||||||
c.Close()
|
// Don't log on ErrConnDispatched and io.EOF to prevent log spam.
|
||||||
}
|
|
||||||
// Don't log on ErrConnDispatched and io.EOF to prevent log spam.
|
|
||||||
if err != credentials.ErrConnDispatched {
|
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
channelz.Warning(logger, s.channelzID, "grpc: Server.Serve failed to create ServerTransport: ", err)
|
channelz.Warning(logger, s.channelzID, "grpc: Server.Serve failed to create ServerTransport: ", err)
|
||||||
}
|
}
|
||||||
|
c.Close()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1106,16 +1104,21 @@ func chainUnaryServerInterceptors(s *Server) {
|
||||||
|
|
||||||
func chainUnaryInterceptors(interceptors []UnaryServerInterceptor) UnaryServerInterceptor {
|
func chainUnaryInterceptors(interceptors []UnaryServerInterceptor) UnaryServerInterceptor {
|
||||||
return func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (interface{}, error) {
|
return func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (interface{}, error) {
|
||||||
var i int
|
// the struct ensures the variables are allocated together, rather than separately, since we
|
||||||
var next UnaryHandler
|
// know they should be garbage collected together. This saves 1 allocation and decreases
|
||||||
next = func(ctx context.Context, req interface{}) (interface{}, error) {
|
// time/call by about 10% on the microbenchmark.
|
||||||
if i == len(interceptors)-1 {
|
var state struct {
|
||||||
return interceptors[i](ctx, req, info, handler)
|
i int
|
||||||
}
|
next UnaryHandler
|
||||||
i++
|
|
||||||
return interceptors[i-1](ctx, req, info, next)
|
|
||||||
}
|
}
|
||||||
return next(ctx, req)
|
state.next = func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
if state.i == len(interceptors)-1 {
|
||||||
|
return interceptors[state.i](ctx, req, info, handler)
|
||||||
|
}
|
||||||
|
state.i++
|
||||||
|
return interceptors[state.i-1](ctx, req, info, state.next)
|
||||||
|
}
|
||||||
|
return state.next(ctx, req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1391,16 +1394,21 @@ func chainStreamServerInterceptors(s *Server) {
|
||||||
|
|
||||||
func chainStreamInterceptors(interceptors []StreamServerInterceptor) StreamServerInterceptor {
|
func chainStreamInterceptors(interceptors []StreamServerInterceptor) StreamServerInterceptor {
|
||||||
return func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error {
|
return func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error {
|
||||||
var i int
|
// the struct ensures the variables are allocated together, rather than separately, since we
|
||||||
var next StreamHandler
|
// know they should be garbage collected together. This saves 1 allocation and decreases
|
||||||
next = func(srv interface{}, ss ServerStream) error {
|
// time/call by about 10% on the microbenchmark.
|
||||||
if i == len(interceptors)-1 {
|
var state struct {
|
||||||
return interceptors[i](srv, ss, info, handler)
|
i int
|
||||||
}
|
next StreamHandler
|
||||||
i++
|
|
||||||
return interceptors[i-1](srv, ss, info, next)
|
|
||||||
}
|
}
|
||||||
return next(srv, ss)
|
state.next = func(srv interface{}, ss ServerStream) error {
|
||||||
|
if state.i == len(interceptors)-1 {
|
||||||
|
return interceptors[state.i](srv, ss, info, handler)
|
||||||
|
}
|
||||||
|
state.i++
|
||||||
|
return interceptors[state.i-1](srv, ss, info, state.next)
|
||||||
|
}
|
||||||
|
return state.next(srv, ss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,11 +73,16 @@ func FromProto(s *spb.Status) *Status {
|
||||||
return status.FromProto(s)
|
return status.FromProto(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromError returns a Status representing err if it was produced by this
|
// FromError returns a Status representation of err.
|
||||||
// package or has a method `GRPCStatus() *Status`.
|
//
|
||||||
// If err is nil, a Status is returned with codes.OK and no message.
|
// - If err was produced by this package or implements the method `GRPCStatus()
|
||||||
// Otherwise, ok is false and a Status is returned with codes.Unknown and
|
// *Status`, the appropriate Status is returned.
|
||||||
// the original error message.
|
//
|
||||||
|
// - If err is nil, a Status is returned with codes.OK and no message.
|
||||||
|
//
|
||||||
|
// - Otherwise, err is an error not compatible with this package. In this
|
||||||
|
// case, a Status is returned with codes.Unknown and err's Error() message,
|
||||||
|
// and ok is false.
|
||||||
func FromError(err error) (s *Status, ok bool) {
|
func FromError(err error) (s *Status, ok bool) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil, true
|
return nil, true
|
||||||
|
|
|
@ -19,4 +19,4 @@
|
||||||
package grpc
|
package grpc
|
||||||
|
|
||||||
// Version is the current grpc version.
|
// Version is the current grpc version.
|
||||||
const Version = "1.41.0"
|
const Version = "1.42.0"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# cloud.google.com/go v0.94.1
|
# cloud.google.com/go v0.97.0
|
||||||
## explicit; go 1.11
|
## explicit; go 1.11
|
||||||
cloud.google.com/go/compute/metadata
|
cloud.google.com/go/compute/metadata
|
||||||
# github.com/Azure/azure-pipeline-go v0.2.3
|
# github.com/Azure/azure-pipeline-go v0.2.3
|
||||||
|
@ -215,7 +215,7 @@ github.com/digitalocean/godo
|
||||||
# github.com/dimchansky/utfbom v1.1.1
|
# github.com/dimchansky/utfbom v1.1.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/dimchansky/utfbom
|
github.com/dimchansky/utfbom
|
||||||
# github.com/docker/cli v20.10.7+incompatible
|
# github.com/docker/cli v20.10.10+incompatible
|
||||||
## explicit
|
## explicit
|
||||||
github.com/docker/cli/cli/config
|
github.com/docker/cli/cli/config
|
||||||
github.com/docker/cli/cli/config/configfile
|
github.com/docker/cli/cli/config/configfile
|
||||||
|
@ -235,7 +235,7 @@ github.com/docker/distribution/registry/client/auth/challenge
|
||||||
github.com/docker/distribution/registry/client/transport
|
github.com/docker/distribution/registry/client/transport
|
||||||
github.com/docker/distribution/registry/storage/cache
|
github.com/docker/distribution/registry/storage/cache
|
||||||
github.com/docker/distribution/registry/storage/cache/memory
|
github.com/docker/distribution/registry/storage/cache/memory
|
||||||
# github.com/docker/docker v20.10.7+incompatible
|
# github.com/docker/docker v20.10.10+incompatible
|
||||||
## explicit
|
## explicit
|
||||||
github.com/docker/docker/api/types
|
github.com/docker/docker/api/types
|
||||||
github.com/docker/docker/api/types/blkiodev
|
github.com/docker/docker/api/types/blkiodev
|
||||||
|
@ -256,8 +256,8 @@ github.com/docker/docker/pkg/longpath
|
||||||
github.com/docker/docker/pkg/stringid
|
github.com/docker/docker/pkg/stringid
|
||||||
github.com/docker/docker/registry
|
github.com/docker/docker/registry
|
||||||
github.com/docker/docker/rootless
|
github.com/docker/docker/rootless
|
||||||
# github.com/docker/docker-credential-helpers v0.6.3
|
# github.com/docker/docker-credential-helpers v0.6.4
|
||||||
## explicit
|
## explicit; go 1.13
|
||||||
github.com/docker/docker-credential-helpers/client
|
github.com/docker/docker-credential-helpers/client
|
||||||
github.com/docker/docker-credential-helpers/credentials
|
github.com/docker/docker-credential-helpers/credentials
|
||||||
# github.com/docker/go-connections v0.4.0
|
# github.com/docker/go-connections v0.4.0
|
||||||
|
@ -335,7 +335,7 @@ github.com/google/go-cmp/cmp/internal/diff
|
||||||
github.com/google/go-cmp/cmp/internal/flags
|
github.com/google/go-cmp/cmp/internal/flags
|
||||||
github.com/google/go-cmp/cmp/internal/function
|
github.com/google/go-cmp/cmp/internal/function
|
||||||
github.com/google/go-cmp/cmp/internal/value
|
github.com/google/go-cmp/cmp/internal/value
|
||||||
# github.com/google/go-containerregistry v0.6.0
|
# github.com/google/go-containerregistry v0.7.0
|
||||||
## explicit; go 1.14
|
## explicit; go 1.14
|
||||||
github.com/google/go-containerregistry/internal/and
|
github.com/google/go-containerregistry/internal/and
|
||||||
github.com/google/go-containerregistry/internal/gzip
|
github.com/google/go-containerregistry/internal/gzip
|
||||||
|
@ -388,8 +388,8 @@ github.com/googleapis/gnostic/compiler
|
||||||
github.com/googleapis/gnostic/extensions
|
github.com/googleapis/gnostic/extensions
|
||||||
github.com/googleapis/gnostic/jsonschema
|
github.com/googleapis/gnostic/jsonschema
|
||||||
github.com/googleapis/gnostic/openapiv2
|
github.com/googleapis/gnostic/openapiv2
|
||||||
# github.com/gophercloud/gophercloud v0.23.0
|
# github.com/gophercloud/gophercloud v0.24.0
|
||||||
## explicit; go 1.13
|
## explicit; go 1.14
|
||||||
github.com/gophercloud/gophercloud
|
github.com/gophercloud/gophercloud
|
||||||
github.com/gophercloud/gophercloud/openstack
|
github.com/gophercloud/gophercloud/openstack
|
||||||
github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes
|
github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes
|
||||||
|
@ -625,7 +625,7 @@ github.com/oklog/ulid
|
||||||
# github.com/opencontainers/go-digest v1.0.0
|
# github.com/opencontainers/go-digest v1.0.0
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/opencontainers/go-digest
|
github.com/opencontainers/go-digest
|
||||||
# github.com/opencontainers/image-spec v1.0.1
|
# github.com/opencontainers/image-spec v1.0.2-0.20210730191737-8e42a01fb1b7
|
||||||
## explicit
|
## explicit
|
||||||
github.com/opencontainers/image-spec/specs-go
|
github.com/opencontainers/image-spec/specs-go
|
||||||
github.com/opencontainers/image-spec/specs-go/v1
|
github.com/opencontainers/image-spec/specs-go/v1
|
||||||
|
@ -820,7 +820,7 @@ golang.org/x/net/internal/timeseries
|
||||||
golang.org/x/net/ipv4
|
golang.org/x/net/ipv4
|
||||||
golang.org/x/net/ipv6
|
golang.org/x/net/ipv6
|
||||||
golang.org/x/net/trace
|
golang.org/x/net/trace
|
||||||
# golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
# golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||||
## explicit; go 1.11
|
## explicit; go 1.11
|
||||||
golang.org/x/oauth2
|
golang.org/x/oauth2
|
||||||
golang.org/x/oauth2/authhandler
|
golang.org/x/oauth2/authhandler
|
||||||
|
@ -917,12 +917,12 @@ google.golang.org/appengine/internal/modules
|
||||||
google.golang.org/appengine/internal/remote_api
|
google.golang.org/appengine/internal/remote_api
|
||||||
google.golang.org/appengine/internal/urlfetch
|
google.golang.org/appengine/internal/urlfetch
|
||||||
google.golang.org/appengine/urlfetch
|
google.golang.org/appengine/urlfetch
|
||||||
# google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e
|
# google.golang.org/genproto v0.0.0-20211111162719-482062a4217b
|
||||||
## explicit; go 1.11
|
## explicit; go 1.11
|
||||||
google.golang.org/genproto/googleapis/rpc/code
|
google.golang.org/genproto/googleapis/rpc/code
|
||||||
google.golang.org/genproto/googleapis/rpc/errdetails
|
google.golang.org/genproto/googleapis/rpc/errdetails
|
||||||
google.golang.org/genproto/googleapis/rpc/status
|
google.golang.org/genproto/googleapis/rpc/status
|
||||||
# google.golang.org/grpc v1.41.0
|
# google.golang.org/grpc v1.42.0
|
||||||
## explicit; go 1.14
|
## explicit; go 1.14
|
||||||
google.golang.org/grpc
|
google.golang.org/grpc
|
||||||
google.golang.org/grpc/attributes
|
google.golang.org/grpc/attributes
|
||||||
|
|
Loading…
Reference in New Issue